读Linux那些事儿之我是HUB笔记(四)

简介:

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下面的处理方法.

 

 



本文转自 曾永刚 51CTO博客,原文链接:http://blog.51cto.com/zyg0227/557040

相关文章
|
2月前
|
Ubuntu Linux Python
Tkinter错误笔记(一):tkinter.Button在linux下出现乱码
在Linux系统中,使用Tkinter库时可能会遇到中文显示乱码的问题,这通常是由于字体支持问题导致的,可以通过更换支持中文的字体来解决。
157 0
Tkinter错误笔记(一):tkinter.Button在linux下出现乱码
|
4月前
|
Linux
Linux源码阅读笔记10-进程NICE案例分析2
Linux源码阅读笔记10-进程NICE案例分析2
|
4月前
|
Linux
Linux源码阅读笔记09-进程NICE案例分析1
Linux源码阅读笔记09-进程NICE案例分析1
|
2月前
|
Linux API 开发工具
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
ijkplayer是由B站研发的移动端播放器,基于FFmpeg 3.4,支持Android和iOS。其源码托管于GitHub,截至2024年9月15日,获得了3.24万星标和0.81万分支,尽管已停止更新6年。本文档介绍了如何在Linux环境下编译ijkplayer的so库,以便在较新的开发环境中使用。首先需安装编译工具并调整/tmp分区大小,接着下载并安装Android SDK和NDK,最后下载ijkplayer源码并编译。详细步骤包括环境准备、工具安装及库编译等。更多FFmpeg开发知识可参考相关书籍。
108 0
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
|
4月前
|
Unix Linux 开发工具
linux笔记 diff及patch的制作与使用
这篇文章是关于Linux系统中使用`diff`命令生成补丁文件以及使用`patch`命令应用这些补丁的详细教程和实战案例。
109 2
linux笔记 diff及patch的制作与使用
|
4月前
|
安全 Linux 开发者
Linux笔记之ldd命令详解
`ldd`命令是Linux环境下一个非常实用的工具,用于显示一个程序运行时所需的共享库依赖。它帮助开发者和系统管理员快速诊断程序运行问题,特别是在处理"找不到库文件"或者"错误的库文件版本"等错误时。然而,出于安全的考虑,对于不信任的可执行文件,应该慎用 `ldd`命令,可以考虑使用其他工具如 `objdump`。总的来说,懂得如何妥善且安全地使用 `ldd`,对于维护一个稳定和高效的Linux系统来说,是非常重要的。
99 9
|
4月前
|
存储 缓存 编译器
Linux源码阅读笔记06-RCU机制和内存优化屏障
Linux源码阅读笔记06-RCU机制和内存优化屏障
|
4月前
|
Linux
Linux源码阅读笔记13-进程通信组件中
Linux源码阅读笔记13-进程通信组件中
|
4月前
|
消息中间件 安全 Java
Linux源码阅读笔记13-进程通信组件上
Linux源码阅读笔记13-进程通信组件上
|
4月前
|
Linux 开发者
Linux源码阅读笔记18-插入模型及删除模块操作
Linux源码阅读笔记18-插入模型及删除模块操作