【转】Linux那些事儿之我是U盘(10)我是谁的他?

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

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.