`
dato0123
  • 浏览: 913484 次
文章分类
社区版块
存档分类
最新评论

Linux那些事儿 之 戏说USB(33)驱动的生命线(一)

 
阅读更多

给女生:“如果有一个男生追你,那你不过是达到了咱学校mm的平均水平;如果有五个男生追你,那你勉强可算是班花系花级别;如果有十个男生追你,~~~哼哼,这事儿也就是在咱交大有~~”

usb_generic_driver不仅仅有十个男生追,是个usb设备都会拜倒在她的石榴裙下,争先恐后的找她配对儿,什么班花系花校花什么的根本就是在诋毁她的身份。但是她要想成为一个usb世界花,必须得满足一个前提,就是她必须得来到usb的这个大世界里,在usb的大舞台上展示自己的魅力,林妹妹那种没有登过T台的世界名模毕竟是个特殊到不能再特殊的特例。
现在开始就沿着usb_generic_driver的成名之路走一走,设备的生命线你可以想当然的认为是从你的usb设备连接到hub的某个端口时开始,驱动的生命线就必须得回溯到usb子系统的初始化函数usb_init了。
896 if (!retval)
897 goto out;
在usb子系统初始化的时候就调用driver.c里的usb_register_device_driver函数将usb_generic_driver注册给系统了,怀胎十月,嗷嗷一声之后,usb世界里的一个超级大美女诞生了。这个美女长什么样早先贴过了,现在看看带她来到这个世界上的usb_register_device_driver函数。
661 /**
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.
665*
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.
670*/
672 struct module *owner)
673 {
674 int retval = 0;
677 return -ENODEV;
679 new_udriver->drvwrap.for_devices = 1;
680 new_udriver->drvwrap.driver.name = (char *) new_udriver->name;
681 new_udriver->drvwrap.driver.bus = &usb_bus_type;
682 new_udriver->drvwrap.driver.probe = usb_probe_device;
683 new_udriver->drvwrap.driver.remove = usb_unbind_device;
684 new_udriver->drvwrap.driver.owner = owner;
686 retval = driver_register(&new_udriver->drvwrap.driver);
688 if (!retval) {
689 pr_info("%s: registered new device driver %s/n",
690 usbcore_name, new_udriver->name);
692 } else {
693 printk(KERN_ERR "%s: error %d registering device "
694 " driver %s/n",
695 usbcore_name, retval, new_udriver->name);
696 }
698 return retval;
699 }
676行,判断一下usb子系统是不是在你启动内核的时候就被禁止了,如果是的话,这个超级大美女的生命也就太短暂了,正是应了那句“自古美女多薄命”的古话,不过一般来说,你不至于无聊到那种地步和她过不去吧。usb_disabled在usb.c里定义
852 /*
853* for external read access to <nousb>
854*/
855 int usb_disabled(void)
856 {
857 return nousb;
858 }
如果你不是存心和我过不去的话,是应该知道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 */
152 static int usb_probe_device(struct device *dev)
153 {
155 struct usb_device *udev;
156 int error = -ENODEV;
160 if (!is_usb_device(dev)) /* Sanity check */
161 return error;
165 /* TODO: Add real matching code */
167 /* The device should always appear to be in use
168 * unless the driver suports autosuspend.
169 */
170 udev->pm_usage_cnt = !(udriver->supports_autosuspend);
172 error = udriver->probe(udev);
173 return error;
174 }
154行,to_usb_device_driver是include/linux/usb.h里定义的一个宏,和前面遇到的那个to_usb_device有异曲同工之妙,
890 drvwrap.driver)
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里定义
153 static int generic_probe(struct usb_device *udev)
154 {
155 int err, 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.
162 */
164 if (c >= 0) {
166 if (err) {
167 dev_err(&udev->dev, "can't set config #%d, error %d/n",
168 c, err);
169 /* This need not be fatal.The user can try to
170 * set other configurations. */
171 }
172 }
174 /* USB device state == configured ... usable */
177 return 0;
178 }
这函数说简单也简单,说复杂也复杂,简单的是外表,复杂的是内心。用一句话去概括它的中心思想,就是从设备可能的众多配置中选择一个合适的,然后去配置设备,从而让设备进入期待已久的Configured状态。概括了中心思想,再去看看细节。先看看是怎么选择一个配置的,调用的是generic.c里的choose_configuration函数。
42 static int choose_configuration(struct usb_device *udev)
43 {
44 int i;
45 int num_configs;
46 int insufficient_power = 0;
47 struct usb_host_config *c, *best;
49 best = NULL;
50 c = udev->config;
51 num_configs = udev->descriptor.bNumConfigurations;
52 for (i = 0; i < num_configs; (i++, c++)) {
55 /* It's possible that a config has no interfaces! */
56 if (c->desc.bNumInterfaces > 0)
57 desc = &c->intf_cache[0]->altsetting->desc;
59 /*
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.
68 *
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.
74 *
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.
78 */
79 #if 0
80 /* Rule out self-powered configs for a bus-powered device */
81 if (bus_powered && (c->desc.bmAttributes &
83 continue;
84 #endif
86 /*
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.
92 *
93 * This is a fairly benign sort of failure.It won't
94 * cause us to reject configurations that we should have
95 * accepted.
96 */
98 /* Rule out configs that draw too much bus current */
99 if (c->desc.bMaxPower * 2 > udev->bus_mA) {
100 insufficient_power++;
101 continue;
102 }
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.
107 */
108 if (i == 0 && desc && (is_rndis(desc) || is_activesync(desc))) {
109 #if !defined(CONFIG_USB_NET_RNDIS_HOST) && !defined(CONFIG_USB_NET_RNDIS_HOST_MODULE)
110 continue;
111 #else
112 best = c;
113 #endif
114 }
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. */
120 else if (udev->descriptor.bDeviceClass !=
122 (!desc || desc->bInterfaceClass !=
124 best = c;
125 break;
126 }
128 /* If all the remaining configs are vendor-specific,
129 * choose the first one. */
130 else if (!best)
131 best = c;
132 }
134 if (insufficient_power > 0)
135 dev_info(&udev->dev, "rejected %d configuration%s "
136 "due to insufficient available bus power/n",
137 insufficient_power, plural(insufficient_power));
139 if (best) {
140 i = best->desc.bConfigurationValue;
141 dev_info(&udev->dev,
142 "configuration #%d chosen from %d choice%s/n",
143 i, num_configs, plural(num_configs));
144 } else {
145 i = -1;
146 dev_warn(&udev->dev,
147 "no configuration chosen from %d choice%s/n",
148 num_configs, plural(num_configs));
149 }
150 return i;
151 }
设备各个配置的详细信息在设备自身的漫漫人生旅途中就已经获取存放在相关的几个成员里了,怎么从中挑选一个让人满意的?显然谁都会说去一个一个的浏览每个配置,看看有没有称心如意的,于是就有了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)
24 {
25 return (n == 1 ? "" : "s");
26 }
参数n为1返回一个空字符串,否则返回一个‘s’,瞄一下使用了这个函数的那几个打印语句,就明白它是用来打印一个英语名词的单复数的,复数的话就加上个s。呵呵,那些不规律的名词单复数形式咋办?凉拌!

不管你疑惑也好,满意也好,choose_configuration就是这样按照自己的标准挑选了一个比较合自己心意的配置,接下来当然就是要用这个配置去配置设备以便让它迈进Configured状态了。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics