《Linux那些事儿之我是USB》我是U盘(10)我是谁的他?

时间:2021-03-27 14:35:03

probe,disconnect,id_table,这三个元素中首先要登场亮相的是id_table,它是干什么用的呢?

我们说过,一个设备只能绑定一个驱动,但驱动并非只能支持一种设备。道理很简单,比如我有两块U盘,那么我可以一起都插入,但是我只需要加载一个模块,usb-storage。没听说过插入两块U盘就得加载两次驱动程序的,除非这两块U盘本身就得使用不同的驱动程序。也正是因为一个模块可以被多个设备共用,才会有“模块计数”这个说法。

既然一个驱动可以支持多个设备,那么当发现一个设备时,如何知道哪个才是它的驱动呢?这就是id_table的用处,让每一个struct usb_driver准备一张表,里面注明该驱动支持哪些设备,这总可以了吧。如果这个设备属于这张表里的,那么绑定,如果不属于这张表里的,那么不好意思,您请便。

id_table来自struct usb_driver中:

const struct usb_device_id *id_table;

它实际上是一个指针,一个structusb_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:

98 struct usb_device_id {

99    /* whichfields to match against? */

100    __u16          match_flags;

101

102   /* Used for product specificmatches; range is inclusive */

103    __u16          idVendor;

104    __u16          idProduct;

105    __u16          bcdDevice_lo;

106    __u16          bcdDevice_hi;

107

108     /*Used for device class matches */

109    __u8           bDeviceClass;

110     __u8           bDeviceSubClass;

111     __u8           bDeviceProtocol;

112

113   /* Used for interface classmatches */

114    __u8           bInterfaceClass;

115      __u8           bInterfaceSubClass;

116    __u8           bInterfaceProtocol;

117

118     /*not matched against */

119    kernel_ulong_t  driver_info;

120 };

实际上这个结构体对每一个USB设备来说,就相当于是它的身份证,记录了它的一些基本信息。通常我们的身份证上会记录我们的姓名,性别,出生年月,户口地址等,而USB设备也有它需要记录的信息,以区分它和别的USB设备。比如Vendor-厂家,Product-产品,以及其他一些比如产品编号、产品的类别、遵循的协议,这些都会在USB的规范里边找到对应的成员。

于是我们知道,一个usb_driver会把它的id表和每一个USB设备的实际情况进行比较,如果该设备的实际情况和这张表里的某一个id相同,准确地说,只有这许多特征都吻合,才能够把一个USB设备和这个USB驱动进行绑定,这些特征哪怕差一点也不行。

那么USB设备的实际情况是什么时候建立起来的?在介绍.probe指针之前有必要先谈一谈另一个数据结构了,它就是struct usb_device。