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

Linux那些事儿之我是U盘(17)冬天来了,春天还会远吗?(一)

 
阅读更多

整个usb-storage模块的代码中,其最灵魂的部分在一个叫做usb_stor_control_thread()的函数中,而那也自然是我们整个故事的高潮.这个函数的调用有些特殊,我们是从usb_stor_acquire_resources()函数进入的,而后者我们即将遇到,它在整部戏中只出现过一次,storage_probe,行号为998的地方.然而在此之前,有四个函数挡在我们面前,它们就是get_device_info,get_transport,get_protocol,get_pipes.如我前面所说,两个人要走到一起,首先要了解彼此,这四个函数就是让driver去认识device.这一点我们从名字上也能看出来.driver需要知道device姓甚名谁,所以有了get_device_info,driver需要知道device喜欢用什么方式沟通,是用QQ还是用msn还是只用手机短信,如果是某一种,那么账号是多少,或者手机号是多少,写代码的人把这些工作分配给了get_transport,get_protocol,get_pipes.

实际上,这四个函数,加上之前刚说过的那个associate_dev(),是整个故事中最平淡最枯燥的部分,第一次读这部分代码总让人困惑,怎么没看见一点usb数据通信啊?完全没有看到usb hostusb device是如何在交流的,这是usb?这一刻,这颗浮躁的心,在这个城市,迷失了.但是,我们知道,爱情,并非都与风花雪月有关,友情,并非总与疯斗打闹有关.这几个函数应该说是给后面做铺垫,红花总要有绿叶配,没有这段代码的铺垫,到了后面usb设备恐怕也无法正常工作吧.不过,一个利好消息是,这几个函数我们只会遇见这一次,它们在整个故事中就这么一次露脸的机会,像我们每个人的青春,只有一次,无法回头.和我们每个人的青春一样,都是绝版的.所以,让我们享受这段平淡无奇的代码吧.

get_device_info, 这个函数定义于drivers/usb/storage/usb.c:

466 /* Get the unusual_devs entries and the string descriptors */
467 static void get_device_info(struct us_data *us, int id_index)
468 {
469 struct usb_device *dev = us->pusb_dev;
470 struct usb_interface_descriptor *idesc =
471 &us->pusb_intf->cur_altsetting->desc;
472 struct us_unusual_dev *unusual_dev = &us_unusual_dev_list[id_index];
473 struct usb_device_id *id = &storage_usb_ids[id_index];
474
475 /* Store the entries */
476 us->unusual_dev = unusual_dev;
477 us->subclass = (unusual_dev->useProtocol == US_SC_DEVICE) ?
478 idesc->bInterfaceSubClass :
479 unusual_dev->useProtocol;
480 us->protocol = (unusual_dev->useTransport == US_PR_DEVICE) ?
481 idesc->bInterfaceProtocol :
482 unusual_dev->useTransport;
483 us->flags = unusual_dev->flags;
484
485 /* Log a message if a non-generic unusual_dev entry contains an
486 * unnecessary subclass or protocol override. This may stimulate
487 * reports from users that will help us remove unneeded entries
488 * from the unusual_devs.h table.
489 */
490 if (id->idVendor || id->idProduct) {
491 static char *msgs[3] = {
492 "an unneeded SubClass entry",
493 "an unneeded Protocol entry",
494 "unneeded SubClass and Protocol entries"};
495 struct usb_device_descriptor *ddesc = &dev->descriptor;
496 int msg = -1;
497
498 if (unusual_dev->useProtocol != US_SC_DEVICE &&
499 us->subclass == idesc->bInterfaceSubClass)
500 msg += 1;
501 if (unusual_dev->useTransport != US_PR_DEVICE &&
502 us->protocol == idesc->bInterfaceProtocol)
503 msg += 2;
504 if (msg >= 0 && !(unusual_dev->flags & US_FL_NEED_OVERRIDE))
505 printk(KERN_NOTICE USB_STORAGE "This device "
506 "(%04x,%04x,%04x S %02x P %02x)"
507 " has %s in unusual_devs.h/n"
508 " Please send a copy of this message to "
509 "<linux-usb-devel@lists.sourceforge.net>/n",
510 ddesc->idVendor, ddesc->idProduct,
511 ddesc->bcdDevice,
512 idesc->bInterfaceSubClass,
513 idesc->bInterfaceProtocol,
514 msgs[msg]);
515 }
516
517 /* Read the device's string descriptors */
518 if (dev->descriptor.iManufacturer)
519 usb_string(dev, dev->descriptor.iManufacturer,
520 us->vendor, sizeof(us->vendor));
521 if (dev->descriptor.iProduct)
522 usb_string(dev, dev->descriptor.iProduct,
523 us->product, sizeof(us->product));
524 if (dev->descriptor.iSerialNumber)
525 usb_string(dev, dev->descriptor.iSerialNumber,
526 us->serial, sizeof(us->serial));
527
528 /* Use the unusual_dev strings if the device didn't provide them */
529 if (strlen(us->vendor) == 0) {
530 if (unusual_dev->vendorName)
531 strlcpy(us->vendor, unusual_dev->vendorName,
532 sizeof(us->vendor));
533 else
534 strcpy(us->vendor, "Unknown");
535 }
536 if (strlen(us->product) == 0) {
537 if (unusual_dev->productName)
538 strlcpy(us->product, unusual_dev->productName,
539 sizeof(us->product));
540 else
541 strcpy(us->product, "Unknown");
542 }
543 if (strlen(us->serial) == 0)
544 strcpy(us->serial, "None");
545
546 US_DEBUGP("Vendor: %s, Product: %s/n", us->vendor, us->product);
547 }

469,不多说,dev还是那个dev.

470,struct usb_interface_descriptor *idesc,这个也无须再说,之前那个associate_dev函数里已经介绍过这个结构体,而且整个故事就是针对一个interface,一个interface就对应一个interface描述符.所以不管在哪里看到,她总还是她.

472, struct us_unusual_dev,这个结构体是第一次出现,她定义于drivers/usb/storage/usb.h,

55 /*
56 * Unusual device list definitions
57 */
58
59 struct us_unusual_dev {
60 const char* vendorName;
61 const char* productName;
62 __u8 useProtocol;
63 __u8 useTransport;
64 int (*initFunction)(struct us_data *);
65 unsigned int flags;
66 };

而等号右边的us_unusal_dev_list是一个数组,定义于drivers/usb/storage/usb.c:

157 /* This is the list of devices we recognize, along with their flag data */

158

159 /* The vendor name should be kept at eight characters or less, and

160 * the product name should be kept at 16 characters or less. If a device

161 * has the US_FL_FIX_INQUIRY flag, then the vendor and product names

162 * normally generated by a device thorugh the INQUIRY response will be

163 * taken from this list, and this is the reason for the above size

164 * restriction. However, if the flag is not present, then you

165 * are free to use as many characters as you like.

166 */

167

168 #undef UNUSUAL_DEV

169 #define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, /

170 vendor_name, product_name, use_protocol, use_transport, /

171 init_function, Flags) /

172 { /

173 .vendorName = vendor_name, /

174 .productName = product_name, /

175 .useProtocol = use_protocol, /

176 .useTransport = use_transport, /

177 .initFunction = init_function, /

178 .flags = Flags, /

179 }

180

181 static struct us_unusual_dev us_unusual_dev_list[] = {

182 # include "unusual_devs.h"

183 # undef UNUSUAL_DEV

184 /* Control/Bulk transport for all SubClass values */

185 { .useProtocol = US_SC_RBC,

186 .useTransport = US_PR_CB},

187 { .useProtocol = US_SC_8020,

188 .useTransport = US_PR_CB},

189 { .useProtocol = US_SC_QIC,

190 .useTransport = US_PR_CB},

191 { .useProtocol = US_SC_UFI,

192 .useTransport = US_PR_CB},

193 { .useProtocol = US_SC_8070,

194 .useTransport = US_PR_CB},

195 { .useProtocol = US_SC_SCSI,

196 .useTransport = US_PR_CB},

197

198 /* Control/Bulk/Interrupt transport for all SubClass values */

199 { .useProtocol = US_SC_RBC,

200 .useTransport = US_PR_CBI},

201 { .useProtocol = US_SC_8020,

202 .useTransport = US_PR_CBI},

203 { .useProtocol = US_SC_QIC,

204 .useTransport = US_PR_CBI},

205 { .useProtocol = US_SC_UFI,

206 .useTransport = US_PR_CBI},

207 { .useProtocol = US_SC_8070,

208 .useTransport = US_PR_CBI},

209 { .useProtocol = US_SC_SCSI,

210 .useTransport = US_PR_CBI},

211

212 /* Bulk-only transport for all SubClass values */

213 { .useProtocol = US_SC_RBC,

214 .useTransport = US_PR_BULK},

215 { .useProtocol = US_SC_8020,

216 .useTransport = US_PR_BULK},

217 { .useProtocol = US_SC_QIC,

218 .useTransport = US_PR_BULK},

219 { .useProtocol = US_SC_UFI,

220 .useTransport = US_PR_BULK},

221 { .useProtocol = US_SC_8070,

222 .useTransport = US_PR_BULK},

223 #if !defined(CONFIG_BLK_DEV_UB) && !defined(CONFIG_BLK_DEV_UB_MODULE)

224 { .useProtocol = US_SC_SCSI,

225 .useTransport = US_PR_BULK},

226 #endif

227

228 /* Terminating entry */

229 { NULL }

230 };

无可奈何花落去,似曾相识燕归来.这个数组看上去特别面熟对不对?可曾记得当初我们见过的那个storage_usb_ids,仔细对比一下会发现,这两个数组的元素个数完全一样,只不过,一个由是struct usb_device_id结构体构成的,另一个则是struct us_unusual_dev结构体构成的,其实这两个表格是一一对应的,它们也都定义于同一个文件中. 细心一点会注意到,UNUSUAL_DEV这个宏在这个文件里被定义了两次,这是干嘛用的?听仔细了,我们曾经提过unusual_devs.h这个文件,这个文件的作用是什么?假设没有这个文件,那么storage_usb_ids这张表就是用USB_INTERFACE_INFO这个宏定义了几种常规的usb mass storage的设备,比如,

{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_RBC, US_PR_CB) },

这一行就是定义一个设备的bInterfaceClass,bInterfaceSubClass,bInterfaceProtocol,也就是说一个usb interface只要其这三个项特点与这张表里定义的任何一行匹配,那么就可以把这个设备和这个驱动绑定,但是这三个条件毕竟只是规定了一些主流的或者说常规的设备的特点,这个世界上usb mass storage设备有许多种,林子大了,什么鸟都有.如果你的设备不符合这三个条件但是你仍然要用这个驱动怎么办?或者说你的设备不一般,在正式工作之前需要进行一些初始化的操作,你想自己提供一个初始化函数,那怎么办?伟大的Linux内核开发者们为你准备了一个文件,它就是让诸多usb mass storage设备厂家欢欣鼓舞的unusual_devs.h,有了它,厂家们不用再为自己的设备不被Linux内核支持而烦恼了.虽然我们的U盘基本上不属于这些另类设备,但作为一个有责任心的社会主义新青年,我们有必要为这个文件说两句.

分享到:
评论

相关推荐

    Linux那些事儿之我是U盘

    Linux那些事儿之我是U盘

    Linux那些事儿之我是U盘.pdf

    Linux那些事儿之我是U盘-有书签版.pdf

    Linux那些事儿

    Linux那些事儿之我是U盘 Linux那些事儿之我是Hub Linux那些事儿之我是USB Core Linux那些事儿之我是UHCI Linux那些事儿之我是EHCI控制器 Linux那些事儿之我是PCI Linux那些事儿之我是SCSI硬盘 Linux那些事儿之我是...

    Linux那些事儿1-9合集

    读过《linux那些事儿之我是U盘》的人,都知道其风格,我就不多说了。 导读: linux那些事儿之我是U盘 linux那些事儿之我是HUB linux那些事儿之我是USB Core linux那些事儿之我是UHCI Linux那些事儿之我是EHCI主机控制...

    Linux那些事儿之全集

    导读.doc Linux那些事儿之我是Block层.pdf Linux那些事儿之我是EHCI主机控制器.pdf Linux那些事儿之我是Hub.pdf Linux那些事儿之我是USB_core.pdf Linux那些事儿之我是U盘.pdf等等 Linux那些事儿系列全在这里了

    Linux那些事儿系列.rar

    》包括《Linux那些事儿之我是Hub》、《Linux那些事儿之我是Sysfs》《Linux那些事儿之我是UHCI》、《Linux那些事儿之我是USB core》、《Linux那些事儿之我是U盘》,令人叹为观止的一个linux系列书籍。只能说,江山代...

    Linux那些事儿(linux内核写的很详细)

    Linux那些事儿 Linux那些事儿之我是Block层 Linux那些事儿之我是Sysfs Linux那些事儿之我是U盘

    Linux那些事儿之我是USB(第2版).pdf

    本次改版修改了第1版中出现的错误,增加了一个附录,主要内容是关于Linux内核的学习方法,是作者的经验总结,值得一读。 本书使用幽默诙谐的笔调对Linux内核中的USB子系统源代码进行了分析,形象且详尽地介绍了USB在...

    Linux那些事儿之我是Hub

    Linux那些事儿之我是Hub,是前面Linux那些事之我是U盘,usb等的姐妹篇

    linux那些事儿之我是U盘

    深入浅出学linux,linux那些事儿系列之我是U盘

    linux的那些事儿全集

    Linux那些事儿之我是Block层 Linux那些事儿之我是EHCI主机控制器 Linux那些事儿之我是Hub Linux那些事儿之我是PCI Linux那些事儿之我是SCSI硬盘 Linux那些事儿之我是Sysfs ...Linux那些事儿之我是U盘

    linux那些事全集

    Linux那些事儿之我是U盘 Linux那些事儿之我是USB_core Linux那些事儿之我是UHCI Linux那些事儿之我是Sysfs Linux那些事儿之我是SCSI硬盘 Linux那些事儿之我是PCI Linux那些事儿之我是Hub Linux那些事儿之我是EHCI...

    Linux那些事儿之我是XXX全集.rar

    Linux那些事儿之我是XXX全集 包含USB core U盘 UHCI PCI SCSI硬盘 Block Hub EHCI 。 想学驱动的童鞋,不妨看看。该书主要是进行源代码的分析

    Linux那些事儿系列

    本人整理的fudan_abc的专栏中以完结的文章,在此向原作者表示感谢,给...内容包括:linux那些事儿之我是U盘,linux那些事儿之我是USB,linux那些事儿之我是HUB,linux那些事儿之我是UHCI,linux那些事儿之我是Sysfs。

Global site tag (gtag.js) - Google Analytics