MODULE_DEVICE_TABLE

一般用在热插拔的设备驱动中

pci_device_idPCI设备类型标识符。在include/linux/mod_devicetable.h头文件中定义。

// include/linux/mod_devicetable.h
struct pci_device_id {
        __u32 vendor, device;           /* Vendor and device ID or PCI_ANY_ID*/
        __u32 subvendor, subdevice;     /* Subsystem ID's or PCI_ANY_ID */
        __u32 class, class_mask;        /* (class,subclass,prog-if) triplet */
        kernel_ulong_t driver_data;     /* Data private to the driver */
};

PCI设备的vendordeviceclass的值都是预先定义好的,通过这些参数可以唯一确定设备厂商和设备类型。这些PCI设备的标准值在include/linux/pci_ids.h头文件中定义。

pci_device_id需要导出到用户空间,使模块装载系统装载模块时知道什么模块对应什么硬件设备。宏MODULE_DEVICE_TABLE()完成该工作。

设备id一般用数组形式。如:

static struct pci_device_id rtl8139_pci_tbl[] = {
        {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
        ....
};
MODULE_DEVICE_TABLE(pci, rtl8139_pci_tbl);

static struct pci_device_id e1000_pci_tbl[] = {
    { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x1000) },
    { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x1001) },
    {0,}
};
MODULE_DEVICE_TABLE(pci, e1000_pci_tbl); 

该宏生成一个名为__mod_pci_device_table的局部变量,该变量指向第二个参数

内核构建时,depmod程序会在所有模块中搜索符号__mod_pci_device_table,把数据(设备列表)从模块中抽出,添加到映射文件/lib/modules/KERNEL_VERSION/modules.pcimap中,当depmod结束之后,所有的PCI设备连同他们的模块名字都被该文件列出。当内核告知热插拔系统一个新的PCI设备被发现时,热插拔系统使用modules.pcimap文件来找寻恰当的驱动程序。

MODULE_DEVICE_TABLE的第一个参数是设备的类型,如果是USB设备,那自然是usb(如果是PCI设备,那将是pci,这两个子系统用同一个宏来注册所支持的设备)。后面一个参数是设备表,这个设备表的最后一个元素的,用于标识结束

例:假如代码定义了USB_SKEL_VENDOR_ID0xfff0USB_SKEL_PRODUCT_ID0xfff0,也就是说,当有一个设备接到集线器时,usb子系统就会检查这个设备的 vendor IDproduct ID,如果他们的值是0xfff0时,那么子系统就会调用这个模块作为设备的驱动。

http://www.ibm.com/developerworks/cn/linux/l-usb/index2.html

当usb设备插入时,为了使linux-hotplug(Linux中PCIUSB设备热插拔支持)系统自动装载驱动程序,你需要创建一个MODULE_DEVICE_TABLE。代码如下(这个模块仅支持某一特定设备):

// drivers/usb/usb-skeleton.c
/* table of devices that work with this driver */
static struct usb_device_id skel_table [] = {
    { USB_DEVICE(USB_SKEL_VENDOR_ID,
      USB_SKEL_PRODUCT_ID) },
    { }                      /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, skel_table);

USB_DEVICE宏利用厂商ID产品ID为我们提供了一个设备的唯一标识。当系统插入一个ID匹配USB设备USB总线时,驱动会在USB core中注册。驱动程序中probe 函数也就会被调用。usb_device 结构指针、接口号和接口ID都会被传递到函数中。

static void * skel_probe(struct usb_device *dev,
        unsigned int ifnum, const struct usb_device_id *id)

驱动程序需要确认插入的设备是否可以被接受,如果不接受,或者在初始化的过程中发生任何错误,probe函数返回一个NULL值。否则返回一个含有设备驱动程序状态的指针。通过这个指针,就可以访问所有结构中的回调函数。

例如

static const struct x86_cpu_id vmx_cpu_id[] = {
    X86_FEATURE_MATCH(X86_FEATURE_VMX),
    {}
};
MODULE_DEVICE_TABLE(x86cpu, vmx_cpu_id);

参考

https://www.cnblogs.com/ancongliang/p/7838469.html

http://www.ibm.com/developerworks/cn/linux/l-usb/index2.html

你可能感兴趣的:(MODULE_DEVICE_TABLE)