24去抖动技术

原则上,spec规定,只有持续了100ms的插入才算真正的插入,或者说才算稳定的插入.hub_port_debounce 就是干这件事情的,这个函数会让你至少等待 100ms,如果设备依然在,那说明稳定了;

25printk_ratelimit: printk 的变种,printk_ratelimit 的用途就是当你某条消息可能会重复的被多次打印的,甚至极限情况下,打印个成千上万条,直接导致日志文件溢出,把别的信息都冲掉了,所以这样是不好的,于是进化出来一个 printk_ratelimit(),它会控制打印消息的频率,如果短期内连续出现打印消息,那么它把消息抛弃,这种情况下这个函数返回 0,所以,只有返回非 0值的情况下才会真正打印.

26hub是如何去实现调用设备提供的probe接口:

        首先:一个usb设备申请内存空间,设置它的状态,把它复位,为它设置地址,获取它的描述符,然后就向设备模型中添加这么一个设备,再然后会为这个设备寻找它的驱动程序,再然后驱动程序提供的 probe()函数就会被调用.

        usb 这边来说,只要调用 device_add 这么一个函数向设备模型核心层添加设备就够了,剩下的事情设备模型层会去处理,这就是设备模型的优点,所以也叫统一的设备模型.就是说不管你是 pci 还是 usb还是 scsi,

总线驱动的工作:是申请并建立总线的数据结构,

设备驱动的工作:是往这条总线上注册,调用 driver_add,

而设备这边也是一样,也往该总线上注册,即调用 device_add.driver_add 就会在总线上寻找每一个设备,如果找到了自己支持的设备,并且该设备没有和别的驱动相绑定,那么就绑定它.反过来,设备这边的做法也一样,device_add 在总线上寻找每一个设备驱动,找到了合适的就绑定它.最后,调用 probe 函数,然后兵权就交给了设备驱动.整个这个过程就叫做 usb 设备初始化

27endpoint 0SET_CONFIG_TRIES

        endpoint 0.0号端点是usb spec 中一个特殊的端点;

        usb spec中是这样规定的,所有的USB设备都有一个默认的控制管道.英文叫Default Control Pipe.与这条管道对应的端点叫做0号端点,也就是传说中的 endpoint zero.这个端点的信息不需要纪录在配置描述符里,就是说并没有一个专门的端点描述符来描述这个 0 号端点,因为不需要,原因是 endpoint zero 基本上所有的特性都是在 spec 规定好了的;

         maximum packet size:每个端点都有这么一个特性,即告诉你该端点能够发送或者接收的包的最大值.

         对于通常的端点来说,这个值被保存在该端点描述符中的 wMaxPacketSize 这一个 field,

        对于端点 0,由于它自己没有一个描述符,而每个设备又都有这么一个端点,所以这个信息被保存在了设备描述符,所以我们在设备描述符里可以看到这么一项, ,而且 spec 还规定了,这个值只能是 8,16,32 或者 64 这四者之一,而且,如果一个设备工作在高速模式,这个值还只能是 64,取别的值都不行.

Linux vs Windows to get bMaxPacketSize0

Linux

max packet size只能是8,16,32或者64,这也就是说,至少你得是8,而我们惊人的发现,设备描述符公共是 18 bytes,其中, byte7 恰恰就是 bMaxPacketSize0,byte0 byte7 算起来就是 8个字节,那也就是说,我先读8个字节,然后设备返回 device descriptor

的前8个字节,于是我就知道它真正的max packet size,于是我再读一次,这次才把整个描述

18 个字节都给读出来,不就 ok 了吗?我靠,写代码的你们他妈的太有才了.

Windows

直接发送64个字节的请求过去,即要求你设备返回64个字节过来,如果你设备端点0max packet size32或者64,那么你反正只要把18个字节的设备描述传递过来就可以了,但是如果你设备端点 0 max packet size就是 8或者 16,而设备描述符是 18个字节,一次肯定传递不完,那么你必然是传递了一次以后还等待着继续传递,但是我从驱动角度来说,我只要获得了 8 个字节就够了,而对于设备,你不是等着继续传吗,我直接对你做一次reset,让你复位,这样不就清掉了你剩下的想传的数据了么?然后我获得了前 8个字节我就可以知道你真正的 max packet size,然后我就按这个真正的最大值来进行下面的传输,首先就是获得你那个 18 个字节的真正的完整的设备描述符.这样子,也就达到了目的了.这就是 Windows下面的处理方法.