2008年(27)
分类: LINUX
2008-06-05 21:26:02
probe,disconnect,id_table,这三个咚咚中首先要登场亮相的是id_table,它是干嘛用的呢?
我们说过,一个device只能绑定一个driver,但driver并非只能支持一种设备,道理很简单,比如我有两块U盘,那么我可以一起都插入,但是我只需要加载一个模块,usb-storage,没听说过插入两块U盘就得加载两次驱动程序的,除非这两块U盘本身就得使用不同的驱动程序.也正是因为一个模块可以被多个设备共用,才会有模块计数这么一个说法.
ok,既然一个driver可以支持多个device,那么当发现一个device的时候,如何知道哪个driver才是她的Mr.Right呢?这就是id_table的用处,让每一个struct usb_driver准备一张表,里边注明该driver支持哪些设备,这总可以了吧.如果你这个设备属于这张表里的,那么ok,绑定吧,如果不属于这张表里的,那么不好意思,您请便.哪凉快上哪去.
来自struct usb_driver中的id_table,
const struct usb_device_id *id_table;
实际上是一个指针,一个struct usb_device_id结构体的指针,当然赋了值以后就是代表一个数组名了,正如我们在定义struct usb_driver usb_storage_driver中所赋的值那样,.id_table=storage_usb_ids,那好,我们来看一下usb_device_id这究竟是怎样一个结构体.
struct usb_device_id来自include/linux/mod_devicetable.h,
40 /*
41 * Device table entry for "new style" table-driven USB drivers.
42 * User mode code can read these tables to choose which modules to load.
43 * Declare the table as a MODULE_DEVICE_TABLE.
44 *
45 * A probe() parameter will point to a matching entry from this table.
46 * Use the driver_info field for each match to hold information tied
47 * to that match: device quirks, etc.
48 *
49 * Terminate the driver's table with an all-zeroes entry.
50 * Use the flag values to control which fields are compared.
51 */
52
53 /**
54 * struct usb_device_id - identifies USB devices for probing and hotplugging
55 * @match_flags: Bit mask controlling of the other fields are used to match
56 * against new devices. Any field except for driver_info may be used,
57 * although some only make sense in conjunction with other fields.
58 * This is usually set by a USB_DEVICE_*() macro, which sets all
59 * other fields in this structure except for driver_info.
60 * @idVendor: USB vendor ID for a device; numbers are assigned
61 * by the USB forum to its members.
62 * @idProduct: Vendor-assigned product ID.
63 * @bcdDevice_lo: Low end of range of vendor-assigned product version numbers.
64 * This is also used to identify individual product versions, for
65 * a range consisting of a single device.
66 * @bcdDevice_hi: High end of version number range. The range of product
67 * versions is inclusive.
68 * @bDeviceClass: Class of device; numbers are assigned
69 * by the USB forum. Products may choose to implement classes,
70 * or be vendor-specific. Device classes specify behavior of all
71 * the interfaces on a devices.
72 * @bDeviceSubClass: Subclass of device; associated with bDeviceClass.
73 * @bDeviceProtocol: Protocol of device; associated with bDeviceClass.
74 * @bInterfaceClass: Class of interface; numbers are assigned
75 * by the USB forum. Products may choose to implement classes,
76 * or be vendor-specific. Interface classes specify behavior only
77 * of a given interface; other interfaces may support other classes.
78 * @bInterfaceSubClass: Subclass of interface; associated with bInterfaceClass.
79 * @bInterfaceProtocol: Protocol of interface; associated with bInterfaceClass.
80 * @driver_info: Holds information used by the driver. Usually it holds
81 * a pointer to a descriptor understood by the driver, or perhaps
82 * device flags.
83 *
84 * In most cases, drivers will create a table of device IDs by using
85 * USB_DEVICE(), or similar macros designed for that purpose.
86 * They will then export it to userspace using MODULE_DEVICE_TABLE(),
87 * and provide it to the USB core through their usb_driver structure.
88 *
89 * See the usb_match_id() function for information about how matches are
90 * performed. Briefly, you will normally use one of several macros to help
91 * construct these entries. Each entry you provide will either identify
92 * one or more specific products, or will identify a class of products
93 * which have agreed to behave the same. You should put the more specific
94 * matches towards the beginning of your table, so that driver_info can
95 * record quirks of specific products.
96 */
97 struct usb_device_id {
98 /* which fields to match against? */
99 __u16 match_flags;
100
101 /* Used for product specific matches; range is inclusive */
102 __u16 idVendor;
103 __u16 idProduct;
104 __u16 bcdDevice_lo;
105 __u16 bcdDevice_hi;
106
107 /* Used for device class matches */
108 __u8 bDeviceClass;
109 __u8 bDeviceSubClass;
110 __u8 bDeviceProtocol;
111
112 /* Used for interface class matches */
113 __u8 bInterfaceClass;
114 __u8 bInterfaceSubClass;
115 __u8 bInterfaceProtocol;
116
117 /* not matched against */
118 kernel_ulong_t driver_info;
119 };
实际上这个结构体对每一个usb设备来说,就相当于是她的身份证,记录了她的一些基本信息,通常我们的身份证上会记录我们的姓名,性别,出生年月,户口地址等等,而usb设备她也有她需要记录的信息,以区分她和别的usb设备,比如Vendor-厂家,Product-产品,以及其他一些比如产品编号,产品的类别,遵循的协议,这些都会在usb的规范里边找到对应的冬冬.暂且先不细说.
于是我们知道,一个usb_driver会把它的这张id表去和每一个usb设备的实际情况进行比较,如果该设备的实际情况和这张表里的某一个id相同,准确地说,只有这许多特征都吻合,才能够把一个usb device和这个usb driver进行绑定,这些特征哪怕差一点也不行.就像我们每个人都是一道弧,都在不停寻找能让彼此嵌成完整的圆的另一道弧,事实却是,每个人对∏(PI)的理解不尽相同,而圆心能否重合,或许只有痛过才知道.差之毫厘,失之交臂.
那么usb设备的实际情况是什么时候建立起来的?嗯,在介绍.probe指针之前有必要先谈一谈另一个数据结构了,她就是struct usb_device.
在struct usb_driver中,.probe和.disconnect的原型如下:
int (*probe) (struct usb_interface *intf,const struct usb_device_id *id);
void (*disconnect) (struct usb_interface *intf);
我们来看其中的参数,struct usb_device_id这个不用说了,刚才已经介绍过,那么struct usb_interface从何而来?还是让我们先从struct usb_device说起.
我们知道每一个device对应一个struct device结构体变量,但是device不可能是万能的,生命是多样性的,就像我们可以用"人"来统称全人类,但是分的细一点,又有男人和女人的区别,那么device也一样,由于有各种各样的设备,于是又出来了更多的词汇(数据结构),比如针对usb设备,开发者们设计了一个叫做struct usb_device的结构体.她定义于include/linux/usb.h,
294 /*
295 * struct usb_device - kernel's representation of a USB device
296 *
297 * FIXME: Write the kerneldoc!
298 *
299 * Usbcore drivers should not set usbdev->state directly. Instead use
300 * usb_set_device_state().
301 */
302 struct usb_device {
303 int devnum; /* Address on USB bus */
304 char devpath [16]; /* Use in messages: /port/port/... */
305 enum usb_device_state state; /* configured, not attached, etc */
306 enum usb_device_speed speed; /* high/full/low (or error) */
307
308 struct usb_tt *tt; /* low/full speed dev, highspeed hub */
309 int ttport; /* device port on that tt hub */
310
311 struct semaphore serialize;
312
313 unsigned int toggle[2]; /* one bit for each endpoint ([0] = IN, [1] = OUT) */
314 int epmaxpacketin[16]; /* INput endpoint specific maximums */
315 int epmaxpacketout[16]; /* OUTput endpoint specific maximums */
316
317 struct usb_device *parent; /* our hub, unless we're the root */
318 struct usb_bus *bus; /* Bus we're part of */
319
320 struct device dev; /* Generic device interface */
321
322 struct usb_device_descriptor descriptor;/* Descriptor */
323 struct usb_host_config *config; /* All of the configs */
324 struct usb_host_config *actconfig;/* the active configuration */
325
326 char **rawdescriptors; /* Raw descriptors for each config */
327
328 int have_langid; /* whether string_langid is valid yet */
329 int string_langid; /* language ID for strings */
330
331 void *hcpriv; /* Host Controller private data */
332
333 struct list_head filelist;
334 struct dentry *usbfs_dentry; /* usbfs dentry entry for the device */
335
336 /*
337 * Child devices - these can be either new devices
338 * (if this is a hub device), or different instances
339 * of this same device.
340 *
341 * Each instance needs its own set of data structures.
342 */
343
344 int maxchild; /* Number of ports if hub */
345 struct usb_device *children[USB_MAXCHILDREN];
346 };
347 #define to_usb_device(d) container_of(d, struct usb_device, dev)
看起来很复杂的一个数据结构,不过我们目前不需要去理解她的每一个成员,不过我们可以看到,其中有一个成员struct device dev,没错,这就是前面说的那个属于每个设备的struct device结构体变量.
实际上,U盘驱动里边并不会直接去处理这个结构体,因为对于一个U盘来说,她就是对应这么一个struct usb_device的变量,这个变量由usb core负责申请和赋值.但是我们需要记住这个结构体变量,因为日后我们调用usb core提供的函数的时候,会把这个变量作为参数传递上去,因为很简单,要和usb core交流,总得让人家知道我们是谁吧,比如后来要调用的一个函数,usb_buffer_alloc,它就需要这个参数.
而对U盘设备驱动来说,比这个struct usb_device更重要的数据结构是,struct usb_interface.走到这一步,我们不得不去了解一点usb设备的规范了,或者专业一点说,usb协议.因为我们至少要知道什么是usb interface.
星爷说,人有人他妈,妖有妖他妈.说的就是任何事物都有其要遵守的规矩.usb设备要遵循的就是usb协议. 不管是软件还是硬件,在设计的伊始,总是要参考usb协议.怎么设计硬件,如何编写软件,不看usb协议,谁也不可能凭空想象出来.毕竟不是写小说,有几人能像海岩那样,光凭想象就能写出便衣警察,永不瞑目,玉观音这些经典的爱情加案情的作品来呢.
usb协议规定了,每个usb设备都得有些基本的元素,称为描述符,有四类描述符是任何一种usb设备都得有的.他们是,device descriptor,configuration descriptor,interface descriptor,endpoint descriptor.描述符里的冬冬是一个设备出厂的时候就被厂家给固化在设备里了.这种东西不管怎样也改变不了,比如我有个Intel的U盘,那里边的固有的信息肯定是在Intel出厂的时候就被烙在里边了,厂家早已把它的一切,烙上Intel印.所以当我插入U盘,用cat /proc/scsi/scsi命令看一下的话,"Vendor"那一项显示的肯定是Intel. 关于这几种描述符,usb core在总线扫描那会就会去读取,会去获得里边的信息,其中,device描述符描述的是整个device,注意了,这个device和咱们一直讲的device和driver那里的device是不一样的.因为一个usb device实际上指的是一种宏观上的概念,它可以是一种多功能的设备,改革开放之后,多功能的东西越来越多了,比如外企常见的多功能一体机,就是集打印机,复印机,扫描仪,传真机于一体的设备, 当然,这不属于usb设备,但是usb设备当然也有这种情况,比如电台DJ可能会用到的,一个键盘,上边带一个扬声器,它们用两个usb接口接到usb hub上去,而device描述符描述的就是这整个设备的特点.那么configuration描述符呢,老实说,对我们了解U盘驱动真是没有什么意义,但是作为一个有责任心的男人,此刻,我必须为它多说几句,虽然只是很简单的说几句.一个设备可以有一种或者几种配置,这能理解吧?没见过具体的usb设备?那么好,手机见过吧,每个手机都会有多种配置,或者说"设定",比如,我的这款,Nokia6300,手机语言,可以设定为English,繁体中文,简体中文,一旦选择了其中一种,那么手机里边所显示的所有的信息都是该种语言/字体.还有最简单的例子,操作模式也有好几种,标准,无声,会议,etc.基本上如果我设为"会议",那么就是只振动不发声,要是设为无声,那么就啥动静也不会有,只能凭感觉了,以前去公司面试的话通常就是设为无声,因为觉得振动也不好,让人家面试官听到了还是不合适.那么usb设备的配置也是如此,不同的usb设备当然有不同的配置了,或者说需要配置哪些东西也会不一样.好了,关于配置,就说这么多,更多的我们暂时也不需要了解了.
对于usb设备驱动程序编写者来说,更为关键的是下面两个,interface和endpoint.先说,interface.第一句,一个interface对应一个usb设备驱动程序.没错,还说前边那个例子,一个usb设备,两种功能,一个键盘,上面带一个扬声器,两个接口,那这样肯定得要两个驱动程序,一个是键盘驱动程序,一个是音频流驱动程序.道上的兄弟喜欢把这样两个整合在一起的东西叫做一个设备,那好,让他们去叫吧,我门用interface来区分这两者行了吧.于是有了我们前面提到的那个数据结构,struct usb_interface.它定义于include/linux/usb.h:
71 /**
72 * struct usb_interface - what usb device drivers talk to
73 * @altsetting: array of interface structures, one for each alternate
74 * setting that may be selected. Each one includes a set of
75 * endpoint configurations. They will be in no particular order.
76 * @num_altsetting: number of altsettings defined.
77 * @cur_altsetting: the current altsetting.
78 * @driver: the USB driver that is bound to this interface.
79 * @minor: the minor number assigned to this interface, if this
80 * interface is bound to a driver that uses the USB major number.
81 * If this interface does not use the USB major, this field should
82 * be unused. The driver should set this value in the probe()
83 * function of the driver, after it has been assigned a minor
84 * number from the USB core by calling usb_register_dev().
85 * @condition: binding state of the interface: not bound, binding
86 * (in probe()), bound to a driver, or unbinding (in disconnect())
87 * @dev: driver model's view of this device
88 * @class_dev: driver model's class view of this device.
89 *
90 * USB device drivers attach to interfaces on a physical device. Each
91 * interface encapsulates a single high level function, such as feeding
92 * an audio stream to a speaker or reporting a change in a volume control.
93 * Many USB devices only have one interface. The protocol used to talk to
94 * an interface's endpoints can be defined in a usb "class" specification,
95 * or by a product's vendor. The (default) control endpoint is part of
96 * every interface, but is never listed among the interface's descriptors.
97 *
98 * The driver that is bound to the interface can use standard driver model
99 * calls such as dev_get_drvdata() on the dev member of this structure.
100 *
101 * Each interface may have alternate settings. The initial configuration
102 * of a device sets altsetting 0, but the device driver can change
103 * that setting using usb_set_interface(). Alternate settings are often
104 * used to control the the use of periodic endpoints, such as by having
105 * different endpoints use different amounts of reserved USB bandwidth.
106 * All standards-conformant USB devices that use isochronous endpoints
107 * will use them in non-default settings.
108 *
109 * The USB specification says that alternate setting numbers must run from
110 * 0 to one less than the total number of alternate settings. But some
111 * devices manage to mess this up, and the structures aren't necessarily
112 * stored in numerical order anyhow. Use usb_altnum_to_altsetting() to
113 * look up an alternate setting in the altsetting array based on its number.
114 */
115 struct usb_interface {
116 /* array of alternate settings for this interface,
117 * stored in no particular order */
118 struct usb_host_interface *altsetting;
119
120 struct usb_host_interface *cur_altsetting; /* the currently
121 * active alternate setting */
122 unsigned num_altsetting; /* number of alternate settings */
123
124 int minor; /* minor number this interface is bound to */
125 enum usb_interface_condition condition; /* state of binding */
126 struct device dev; /* interface specific device info */
127 struct class_device *class_dev;
128 };
129 #define to_usb_interface(d) container_of(d, struct usb_interface, dev)
130 #define interface_to_usbdev(intf) \
131 container_of(intf->dev.parent, struct usb_device, dev)
嗬,贴这么长一段,怎么又是注释为主啊?知足吧,Linux代码中注释实在是太少了,等你真的需要认真看某一个模块的时候你就会嫌注释少了.这个结构体是一个贯穿整个U盘驱动程序的,所以虽然我们不用去深入了解,但是需要记住,整个U盘驱动程序在后面任何一处提到的struct usb_interface都是同一个变量,这个变量是在usb core总线扫描的时候就申请好了的.我们只需贯彻鲁迅先生的拿来主义即可,直接用就是了.比如前面说过的storage_probe(struct usb_interface *intf,const struct usb_device_id *id),storage_disconnect(struct usb_interface *intf)这两个函数中的那个参数intf.
而这里130行这个宏-interface_to_usbdev,也会用得着的,顾名思义,就是从一个struct usb_interface转换成一个struct usb_device,我们说过了,有些函数需要的参数就是struct usb_device,而不是usb_interface,所以这种转换是经常会用到的,而这个宏,usb core的设计者们也为我们准备好了,除了感激,我们还能说什么呢?
如果你是急性子,那这时候你一定很想开始看storage_probe函数了,因为整个U盘的工作就是从这里开始的.不过,莎士比亚说过,磨刀不误砍柴功.不妨继续花点时间,至少把四大关键词中最后一个给弄明白了,
前面我们已经了解了device,configuration,interface,还剩最后一个endpoint.USB通信的最基本的形式就是通过endpoint,道上的兄弟管这个叫做端点,一个接口有一个或多个端点,而作为像U盘这样的存储设备吧,它至少有一个控制端点,两个bulk端点.这些端点都是干嘛的?说来话长,真是一言难尽哪.
usb协议里规定了,usb设备有四种通信方式,分别是控制传输,中断传输,批量传输,等时传输.其中,等时传输显然是用于音频和视频一类的设备,这类设备期望能够有个比较稳定的数据流,比如你在网上QQ视频聊天,肯定希望每分钟传输的图像/声音速率是比较稳定的,不能说这一分钟对方看到你在向她向你深情表白,可是下一分钟却看见画面停滞在那里,只能看到你那傻样一动不动,你说这不浪费感情嘛.所以,每一个有良知的男人都应该知道,usb-storage里边肯定不会用到等时传输.因为我们只管copy一个文件,管它第一秒和第二秒的传输有什么区别,只要几十秒内传完了就ok.
相比之下,等时传输是四种传输中最麻烦的,所以,U盘里边用不着,那您就偷着乐去吧.不过我要说,中断传输也用不着,对于U盘来说,的确用不着,虽然说usb mass storage的协议里边有一个叫做CBI的传输协议,CBI就是Control/Bulk/Interrupt,即控制/批量/中断,这三种传输都会用到,但这种传输协议并不适用于U盘,U盘使用的是一个叫做Bulk-Only的传输协议.使用这种协议的设备只有两种传输方式,一种是批量传输,另一种是控制传输,控制传输是任何一种usb设备都必须支持的,它专门用于传输一些控制信息.比如我想查询一下关于这个interface的一些信息,那么就用控制传输,而bulk传输,它就是U盘的主要工作了,读写数据,这种情况就得用bulk传输.具体的传输我们后面再讲.
好了,知道了传输方式,就可以来认识endpoint了.和endpoint齐名的有一个叫做管道,或者有文化的人管这个叫pipe.endpoint就是通信的发送或者接收点,你要发送数据,那你只要把数据发送到正确的端点那里就可以了.之所以U盘有两个bulk端点,是因为端点也是有方向的,一个叫做Bulk in,一个叫做Bulk out,从usb主机到设备称为out,从设备到主机称为in.而管道,实际上只是为了让我们能够找到端点,就相当于我们日常说的邮编地址,比如一个国家,为了通信,我们必须给各个地方取名,完了给各条大大小小的路取名,比如你要揭发你们那里的官员腐败,你要去上访,你从某偏僻的小县城出发,要到北京来上访,那你的这个端点(endpoint)就是北京,而你得知道你来北京的路线,那这个从你们县城到北京的路线就算一条管道.有人好奇的问了,管道应该有两端吧,一个端点是北京,那另一个端点呢?答案是,这条管道有些特殊,就比如上访,我们只需要知道一端是北京,而另一端是哪里无所谓,因为不管你在哪里你都得到北京来上访.没听说过你在山西你可以上访,你要在宁夏还不能上访了,没这事对吧.
严格来说,管道的另一端应该是usb主机,即前面说的那个host,usb协议里边也是这么说的,协议里边说pipes代表着一种能力,怎样一种能力呢,在主机和设备上的端点之间移动数据,听上去挺玄的.因为事实上,usb里边所有的数据传输都是有主机发起的.一切都是以主机为核心,各种设备紧紧围绕在主机周围.所以呢,usb core里边很多函数就是,为了让usb host能够正确的完成数据传输或者说传输调度,就得告诉host这么一个pipe,换言之,它得知道自己这次调度的数据是传送给谁或者从谁那里传输过来.不过有人又要问了,比如说我要从U盘里读一个文件,那我告诉usb host某个端点能有用吗?那个文件又不是存放在一个端点里边,它不该是存放在U盘里边吗?这个就只能在后面的代码里去知道了.实际上端点这东西是一个很虚的东西,它的身上充分体现了我国军事思想中的声东击西的想法,即数据本身并不是在端点里,但是看上去却觉得仿佛在端点里.这一切的谜团,让我们在storage_probe()函数里去慢慢解开吧.
对于整个usb-storage模块,usb_stor_init()是它的开始,然而,对于U盘驱动程序来说,它真正驱使U盘工作却是始于storage_probe().
两条平行线只要相交,就注定开始纠缠一生,不管中间是否短暂分离. usbcore为设备找到了适合她的驱动程序,或者为驱动程序找到了他所支持的设备,但这只是表明双方的第一印象还可以,但彼此是否真的适合对方还需要进一步的了解.毋庸置疑,了解对方的第一步是,知道她有哪些爱好,她的生日,她的星座,喜欢吃什么,而U盘driver则会调用函数storage_probe()去认识对方,她是个什么样的设备,她的生活习惯是?她的联系方式是?这里调用了四个函数get_device_info,get_protocol,get_transport,get_pipes. 当然还有一些别人并不了解的冬冬你也会知道,比如她的三围,这里对应的就是usb_stor_Bulk_man_lun().
整个U盘驱动这部大戏,由storage_probe开始,由storage_disconnect结束.其中,storage_probe这个函数占了相当大的篇幅.我们一段一段来看.这两个函数都来自drivers/usb/storage/usb.c中:
926 /* Probe to see if we can drive a newly-connected USB device */
927 static int storage_probe(struct usb_interface *intf,
928 const struct usb_device_id *id)
929 {
930 struct us_data *us;
931 const int id_index = id - storage_usb_ids;
932 int result;
933
934 US_DEBUGP("USB Mass Storage device detected\n");
935
936 /* Allocate the us_data structure and initialize the mutexes */
937 us = (struct us_data *) kmalloc(sizeof(*us), GFP_KERNEL);
938 if (!us) {
939 printk(KERN_WARNING USB_STORAGE "Out of memory\n");
940 return -ENOMEM;
941 }
942 memset(us, 0, sizeof(struct us_data));
首先先贴出这么几行,两个参数不用多说了,struct usb_interface和struct usb_device_id的这两个指针都是前面介绍过的,来自usb core那一层,我们整个故事里用到的就是这么一个,不是说一会指向你,一会指向他,这两个指针的指向是定下来的.
930行,最重要的一个数据结构终于在这种神不知鬼不觉的地方惊艳亮相了.整个usb-storage模块里边自己定义的数据结构不多,但是us_data算一个.这个数据结构是跟随我们的代码一直走下去的,如影随形,几乎处处都可以看见她的身影.先把它的代码贴出来,来自drivers/usb/storage/usb.h:
105 /* we allocate one of these for every device that we remember */
106 struct us_data {
107 /* The device we're working with
108 * It's important to note:
109 * (o) you must hold dev_semaphore to change pusb_dev
110 */
111 struct semaphore dev_semaphore; /* protect pusb_dev */
112 struct usb_device *pusb_dev; /* this usb_device */
113 struct usb_interface *pusb_intf; /* this interface */
114 struct us_unusual_dev *unusual_dev; /* device-filter entry */
115 unsigned long flags; /* from filter initially */
116 unsigned int send_bulk_pipe; /* cached pipe values */
117 unsigned int recv_bulk_pipe;
118 unsigned int send_ctrl_pipe;
119 unsigned int recv_ctrl_pipe;
120 unsigned int recv_intr_pipe;
121
122 /* information about the device */
123 char vendor[USB_STOR_STRING_LEN];
124 char product[USB_STOR_STRING_LEN];
125 char serial[USB_STOR_STRING_LEN];
126 char *transport_name;
127 char *protocol_name;
128 u8 subclass;
129 u8 protocol;
130 u8 max_lun;
131
132 u8 ifnum; /* interface number */
133 u8 ep_bInterval; /* interrupt interval */
134
135 /* function pointers for this device */
136 trans_cmnd transport; /* transport function */
137 trans_reset transport_reset; /* transport device reset */
138 proto_cmnd proto_handler; /* protocol handler */
139
140 /* SCSI interfaces */
141 struct Scsi_Host *host; /* our dummy host data */
142 struct scsi_cmnd *srb; /* current srb */
143
144 /* thread information */
145 int pid; /* control thread */
146
147 /* control and bulk communications data */
148 struct urb *current_urb; /* USB requests */
149 struct usb_ctrlrequest *cr; /* control requests */
150 struct usb_sg_request current_sg; /* scatter-gather req. */
151 unsigned char *iobuf; /* I/O buffer */
152 dma_addr_t cr_dma; /* buffer DMA addresses */
153 dma_addr_t iobuf_dma;
154
155 /* mutual exclusion and synchronization structures */
156 struct semaphore sema; /* to sleep thread on */
157 struct completion notify; /* thread begin/end */
158 wait_queue_head_t dev_reset_wait; /* wait during reset */
159 wait_queue_head_t scsi_scan_wait; /* wait before scanning */
160 struct completion scsi_scan_done; /* scan thread end */
161
162 /* subdriver information */
163 void *extra; /* Any extra data */
164 extra_data_destructor extra_destructor;/* extra data destructor */
165 };
不难发现,Linux内核中每一个重要的数据结构都很复杂,这体现了内核代码编写者们的一种清高,仿佛不用点复杂的数据结构不足以体现他们是个腕儿.这可就苦了我们这些读代码的了,尤其是中国的学生,毕竟谭浩强的书里边翻多少遍也翻不出这么一变态的数据结构吧.所以,此刻,每一个有志青年都应该倍感责任重大,只有我们国家强大了,我们才能把谭浩强的书籍向全世界推广,从而告诉那些写内核代码的家伙,不要写那么复杂的冬冬,要按照谭浩强的书里的规矩来设计数据结构,来编写代码.这才是造福全人类的做法.不是吗?
先不说这些了,总之,这个令人头疼的数据结构是每一个device都有的,换句话说,我们会为每一个device申请一个us_data,因为这个结构里边的冬冬我们之后一直会用得着的.至于怎么用,每个成员什么意思,以后用上了再细说.930行,struct us_data *us,于是,日后我们会非常频繁的看到us的.另,us什么意思?尼采说:us者,usb storage是也.
937行,就是为us申请内存空间,而938行就是判断内存空间是否申请成功,成功的话us就不会为0,或者说为NULL,如果为NULL那么就是失败了,那么别再浪费表情了,整部戏就这么提前夭折了.在这里需要强调的是,整个内核代码中,像这种判断内存申请是否成功的语句是无处不在,每次有内存申请的语句,其后边一定会跟随一句判断申请成功与否的语句.写过代码的人都该知道,这样做是很有必要的,因为你没有申请到内存,那么继续下去就是没有意义的,除了可能让人见识计算机是如何崩溃之外,没有别的好处.而内存申请不管申请了多大,都有可能失败,写代码的人这样做无非是想告诫我们,我们的计算机并不总像人民币那般坚挺,她很脆弱.当你真正用计算机写代码的时候你就会发现计算机多么的脆弱和无力。
942行,给us初始化为全0.
934行这个US_DEBUGP,是一个宏,来自drivers/usb/storage/debug.h,接下来很多代码中我们也会看到这个宏,她无非就是打印一些调试信息.debug.h中有这么一段,
54 #ifdef CONFIG_USB_STORAGE_DEBUG
55 void usb_stor_show_command(struct scsi_cmnd *srb);
56 void usb_stor_show_sense( unsigned char key,
57 unsigned char asc, unsigned char ascq );
58 #define US_DEBUGP(x...) printk( KERN_DEBUG USB_STORAGE x )
59 #define US_DEBUGPX(x...) printk( x )
60 #define US_DEBUG(x) x
61 #else
62 #define US_DEBUGP(x...)
63 #define US_DEBUGPX(x...)
64 #define US_DEBUG(x)
65 #endif
66
67 #endif
这里一共定义了几个宏,US_DEBUGP,US_DEBUGPX,US_DEBUG,差别不大,只是形式上略有不同罢了.