给女生:“如果有一个男生追你,那你不过是达到了咱学校mm的平均水平;如果有五个男生追你,那你勉强可算是班花系花级别;如果有十个男生追你,~~~哼哼,这事儿也就是在咱交大有~~”
usb_generic_driver不仅仅有十个男生追,是个usb设备都会拜倒在她的石榴裙下,争先恐后的找她配对儿,什么班花系花校花什么的根本就是在诋毁她的身份。但是她要想成为一个usb世界花,必须得满足一个前提,就是她必须得来到usb的这个大世界里,在usb的大舞台上展示自己的魅力,林妹妹那种没有登过T台的世界名模毕竟是个特殊到不能再特殊的特例。
现在开始就沿着usb_generic_driver的成名之路走一走,设备的生命线你可以想当然的认为是从你的usb设备连接到hub的某个端口时开始,驱动的生命线就必须得回溯到usb子系统的初始化函数usb_init了。
在usb子系统初始化的时候就调用driver.c里的usb_register_device_driver函数将usb_generic_driver注册给系统了,怀胎十月,嗷嗷一声之后,usb世界里的一个超级大美女诞生了。这个美女长什么样早先贴过了,现在看看带她来到这个世界上的usb_register_device_driver函数。
662* usb_register_device_driver - register a USB device (not interface) driver
663* @new_udriver: USB operations for the device driver
664* @owner: module owner of this driver.
666* Registers a USB device driver with the USB core.The list of
667* unattached devices will be rescanned whenever a new driver is
668* added, allowing the new driver to attach to any recognized devices.
669* Returns a negative error code on failure and 0 on success.
679 new_udriver->drvwrap.for_devices = 1;
684 new_udriver->drvwrap.driver.owner = owner;
689 pr_info("%s: registered new device driver %s/n",
676行,判断一下usb子系统是不是在你启动内核的时候就被禁止了,如果是的话,这个超级大美女的生命也就太短暂了,正是应了那句“自古美女多薄命”的古话,不过一般来说,你不至于无聊到那种地步和她过不去吧。usb_disabled在usb.c里定义
853* for external read access to <nousb>
如果你不是存心和我过不去的话,是应该知道nosub表示什么意思的。
679行,看到没,for_devices就是在这儿被初始化为1的,有了它,match里的那个is_usb_device_driver把门儿的才有章可循有凭可依。
下面就是充实了下usb_generic_driver里嵌入的那个struct device_driver结构体,usb_generic_driver就是通过它和设备模型搭上关系的。name就是usb_generic_driver的名字,即usb,所属的总线类型同样被设置为usb_bus_type,然后是指定probe函数和remove函数。
686行,调用设备模型的函数driver_register将usb_generic_driver添加到usb总线的那条驱动链表里,然后它就可以接受usb设备的讨好、献殷勤、表白。
usb_generic_driver和usb设备匹配成功后,就会调用682行指定的probe函数usb_probe_device(),现在看看driver.c里定义的这个函数
151 /* called from driver core with dev locked */
165 /* TODO: Add real matching code */
167 /* The device should always appear to be in use
168 * unless the driver suports autosuspend.
170 udev->pm_usage_cnt = !(udriver->supports_autosuspend);
154行,to_usb_device_driver是include/linux/usb.h里定义的一个宏,和前面遇到的那个to_usb_device有异曲同工之妙,
160行,match函数543行的那个把门儿的又调到这儿来把门儿了,如果你这个设备的类型不是usb_device_type,那怎么从前面走到这儿的他管不着,但是到他这里就不可能再蒙混过关了。你的设备虽然和咱们的大美女usb_generic_driver是match成功了,但是还要经过双方父母的近距离审查,没房子没车子没票子没马子这种条件怎么配得上美女那,该躲哪儿哭泣就躲哪儿哭泣去吧。
163行,说曹操曹操就到,前面刚提到to_usb_device它这就来了。
170行,pm_usage_cnt和supports_autosuspend这两个前面都提到过那么一下,现在将那两个片断给回顾一下。每个struct usb_interface或struct usb_device里都有一个pm_usage_cnt,每个struct usb_driver或struct usb_device_driver里都有一个supports_autosuspend。提到pm_usage_cnt时说只有它为0时才会允许接口autosuspend,提到supports_autosuspend时说如果它为0就不再允许绑定到这个驱动的接口autosuspend。接口乎?设备乎?有些时候需要那么难得糊涂一下。需要的时候,群众的眼睛是雪亮的,接口是接口设备是设备,不需要的时候,群众是不明真相的,接口设备一个样。这里就是不需要的时候,所以将上面的话里的接口换成设备套一下就是:pm_usage_cnt为0时才会允许设备autosuspend,supports_autosuspend为0就不再允许绑定到这个驱动的设备autosuspend。
所有的usb设备都是绑定到usb_generic_driver上面的,usb_generic_driver的supports_autosuspend字段又是为1的,所以这行就是将设备struct usb_device结构体的pm_usage_cnt置为了0,也就是说允许设备autosuspend。但是不是说这里将pm_usage_cnt轻轻松松置为0,设备就能够autosuspend了,什么事都是说起来简单,做起来就不是那么回事儿,驱动必须得实现一对儿suspend/resume函数供PM子系统那块驱使,usb_generic_driver里的这对函数就是generic_suspend/generic_resume。此处不是久留之地,就不多说它们了。
172行,飘过了上面有关电源管理的那行之后,这里要调用usb_generic_driver自己私有的probe函数generic_probe()对你的设备进行进一步的审查,它在generic.c里定义
157 /* put device-specific files into sysfs */
160 /* Choose and set the configuration.This registers the interfaces
161 * with the driver core and lets interface drivers bind to them.
169 /* This need not be fatal.The user can try to
170 * set other configurations. */
174 /* USB device state == configured ... usable */
这函数说简单也简单,说复杂也复杂,简单的是外表,复杂的是内心。用一句话去概括它的中心思想,就是从设备可能的众多配置中选择一个合适的,然后去配置设备,从而让设备进入期待已久的Configured状态。概括了中心思想,再去看看细节。先看看是怎么选择一个配置的,调用的是generic.c里的choose_configuration函数。
46 int insufficient_power = 0;
52 for (i = 0; i < num_configs; (i++, c++)) {
55 /* It's possible that a config has no interfaces! */
60 * HP's USB bus-powered keyboard has only one configuration
61 * and it claims to be self-powered; other devices may have
62 * similar errors in their descriptors.If the next test
63 * were allowed to execute, such configurations would always
64 * be rejected and the devices would not work as expected.
65 * In the meantime, we run the risk of selecting a config
66 * that requires external power at a time when that power
67 * isn't available.It seems to be the lesser of two evils.
69 * Bugzilla #6448 reports a device that appears to crash
70 * when it receives a GET_DEVICE_STATUS request!We don't
71 * have any other way to tell whether a device is self-powered,
72 * but since we don't use that information anywhere but here,
73 * the call has been removed.
75 * Maybe the GET_DEVICE_STATUS call and the test below can
76 * be reinstated when device firmwares become more reliable.
77 * Don't hold your breath.
80 /* Rule out self-powered configs for a bus-powered device */
81 if (bus_powered && (c->desc.bmAttributes &
87 * The next test may not be as effective as it should be.
88 * Some hubs have errors in their descriptor, claiming
89 * to be self-powered when they are really bus-powered.
90 * We will overestimate the amount of current such hubs
91 * make available for each port.
93 * This is a fairly benign sort of failure.It won't
94 * cause us to reject configurations that we should have
98 /* Rule out configs that draw too much bus current */
99 if (c->desc.bMaxPower * 2 > udev->bus_mA) {
100 insufficient_power++;
104 /* When the first config's first interface is one of Microsoft's
105 * pet nonstandard Ethernet-over-USB protocols, ignore it unless
106 * this kernel has enabled the necessary host side driver.
109 #if !defined(CONFIG_USB_NET_RNDIS_HOST) && !defined(CONFIG_USB_NET_RNDIS_HOST_MODULE)
116 /* From the remaining configs, choose the first one whose
117 * first interface is for a non-vendor-specific class.
118 * Reason: Linux is more likely to have a class driver
119 * than a vendor-specific driver. */
128 /* If all the remaining configs are vendor-specific,
129 * choose the first one. */
134 if (insufficient_power > 0)
136 "due to insufficient available bus power/n",
137 insufficient_power, plural(insufficient_power));
142 "configuration #%d chosen from %d choice%s/n",
147 "no configuration chosen from %d choice%s/n",
设备各个配置的详细信息在设备自身的漫漫人生旅途中就已经获取存放在相关的几个成员里了,怎么从中挑选一个让人满意的?显然谁都会说去一个一个的浏览每个配置,看看有没有称心如意的,于是就有了52行的for循环。
刚看到这个for循环就有点傻眼了,就好像武侠小说里一个闭上眼睛准备好要受虐的人却突然发现神功秘笈奇花异果绝世美女都跑到自己怀里了一样,有点不大相信,居然注释要远远多于代码,很少受过这样的优待,都要让人忍不住去学琼瑶阿姨娇嗔一句:你好好讨厌好讨厌哦!。
这么一个for循环,咱们把它分成三大段,59~84这一大段你什么都可以不看,就是不能不看那个#if 0,一见到它,你就应该像迎面见到一个大美女那样热血沸腾,因为它就意味着你可以华丽丽的飘过这么一大段了。
第二段是98~102行,这一段牵扯到人世间最让人无可奈何的一对矛盾,索取与给予。一个配置索取的电流比hub所能给予的还要大,显然它不会是一个让人满意的配置。
第三段是108~131行,关于这段只说一个原则,linux更care那些标准的东西,比如USB_CLASS_VIDEO、USB_CLASS_AUDIO等等这样子的设备和接口就更讨人喜欢一些,所以就会优先选择非USB_CLASS_VENDOR_SPEC的接口。
for循环之后,残余的那些部分都是调试用的,输出一些调试信息,不需要去关心,不过里面出现了个有趣的函数plural,它是一个在generic.c开头儿定义的内联函数
23 static inline const char *plural(int n)
25 return (n == 1 ? "" : "s");
参数n为1返回一个空字符串,否则返回一个‘s’,瞄一下使用了这个函数的那几个打印语句,就明白它是用来打印一个英语名词的单复数的,复数的话就加上个s。呵呵,那些不规律的名词单复数形式咋办?凉拌!
不管你疑惑也好,满意也好,choose_configuration就是这样按照自己的标准挑选了一个比较合自己心意的配置,接下来当然就是要用这个配置去配置设备以便让它迈进Configured状态了。
分享到:
相关推荐
2.6.22内核的usb core源码分析。原文为blog.csdn.net/fudan_abc上的《linux那些事儿之戏说USB》。
我是U盘 说的是2.6.10的内核 我是Sysfs 说的是2.6.10的内核 戏说USB 说的是2.6.22的内核 我是Hub/UHCI/EHCI 说的是2.6.22.1的内核
然后是usb core(也就是戏说USB),这一阶段是个承上启下的角色,承的是U盘/HUB,启的是UHCI/EHCI,主要描述一个usb设备连接到hub上之后,在HUB和UHCI/EHCI之间也就是usb core里发生的故事. 再然后可以开始看UHCI/EHCI.这...
第一章面试受挫——代码无错就是好? 第二章代码规范、重构 第三章复制 VS复用 第四章业务的封装 第五章体会简单工厂模式的美妙 第六章工厂不好用了? 第七章用“策略模式”是一种好策略 第八章反射——程序员的快乐...
兄弟连Linux基础知识与系统管理课件
大班音乐:戏说脸谱.ppt
戏说指针 如何分析指针类型 细说指针 指针的类型 指针所指向的类型 指针的值 指针本身所占据的内存区
一本很不错的讲面向对象的书,给大家分享下 !
C# 面向对象设计 让你了解C#的面向对象的设计原理 更好的掌握C#的学习 真正的成为C#高手
指针的本质、指针的三要素、类型与变量名
幼儿园大班歌唱教案:戏说脸谱.doc
简单明了的解释 很实用
1.使用轻松的方式解释23种设计模式,很容易理解
戏说面向对象程序设计(C#版)面向对象程序设计(C#版)
戏说国学.doc
戏说绩效工资.doc
【作者:李高栓】戏说质量管理体系之四:我的2015年度管理评审——一位质量人的年终总结.doc
从狭义上讲,持续集成可以认为是一种基于某种或者某些变化对软件系统进行的经常性的构建活动(注:这里的构建活动不仅指编译打包 管Thoughtworks的首席科学家Martionfolwer为“持续集成”下了定义,但由于自身背景...