Linux-Kernel

如何在連接的 USB 設備上傳入我的自定義驅動程序模組?

  • August 25, 2018

我正在為 LED 徽章編寫一個簡單的小型驅動模組。我遵循了一些教程和參考資料來完成這項工作。所有這些似乎都暗示在插入設備時會自動載入模組。但是,當我執行usb-devices相應的設備時,有 driver Driver=usbfs

我有另一個終端在進行後續操作dmesg,它絕不會吐出我的任何調試消息。當我嘗試連接和斷開連接時,會出現以下情況:

[36078.726962] usb 1-2: USB disconnect, device number 24
[36080.925619] usb 1-2: new full-speed USB device number 25 using xhci_hcd
[36081.067062] usb 1-2: New USB device found, idVendor=0483, idProduct=5750
[36081.067067] usb 1-2: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[36081.067071] usb 1-2: Product: CHW20160112 HID
[36081.067075] usb 1-2: Manufacturer: Chuanghongweitech1
[36081.068695] input: Chuanghongweitech1 CHW20160112 HID as /devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.0/0003:0483:5750.0018/input/input40
[36081.069072] hid-generic 0003:0483:5750.0018: input,hidraw2: USB HID v1.10 Device [Chuanghongweitech1 CHW20160112 HID] on usb-0000:00:14.0-2/input0

如果我向日誌發出帶有此輸出的sudo insmod ledbadge_drv.kormmod用於解除安裝),我的模組會解除安裝/載入:

[36216.554620] ledbadge:, Unloading module. Handler: ledbadge_exit
[36216.554620] ledbadge:, Attempting to deregister USB device.
[36216.554621] usbcore: deregistering interface driver ledbadge
[36216.554647] ledbadge:, Leaving module!
[36217.632615] ledbadge:, Loading module. Handler: ledbadge_init
[36217.632616] ledbadge:, Attempting to register USB device.
[36217.632636] usbcore: registered new interface driver ledbadge

該模組的程式碼如下:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/usb.h> 



#define LEDBADGE_VENDOR_ID  0x0483
#define LEDBADGE_PRODUCT_ID 0x5750
#define LEDBADGE_MOD_NAME   "ledbadge"
#define LEDBADGE_DRV_NAME   "ledbadge"


/************* usb operations *************/

/* 
   ledbadge_probe

       called when plugging the USB device */


static int ledbadge_probe(struct usb_interface *interface, const struct usb_device_id *id)
{   
   printk(KERN_NOTICE "Led Badge driver (%04X: %04X) plugged \n", id->idVendor, id->idProduct);
   return 0;
}


/* 
   ledbadge_disconnect

       called when unplugging the USB device */

static void ledbadge_disconnect(struct usb_interface *interface) 
{
   printk(KERN_NOTICE "%s:, ledbage USB device removed", LEDBADGE_DRV_NAME);
}




/************* usb driver *************/

// information required to recognize the device

static struct usb_device_id ledbadge_table [] = {
   {USB_DEVICE(LEDBADGE_VENDOR_ID, LEDBADGE_PRODUCT_ID)},
   { }, // terminating entry
};
MODULE_DEVICE_TABLE(usb, ledbadge_table);


static struct usb_driver ledbadge_driver = {
   .name = LEDBADGE_DRV_NAME,
   .id_table = ledbadge_table,
   .probe = ledbadge_probe,
   .disconnect = ledbadge_disconnect,
};








/************** module definition **************/

/* ledbadge_init

       caled on module loading */

static int __init ledbadge_init(void) 
{
   int ret = -1; 

   printk(KERN_NOTICE "%s:, Loading module. Handler: %s",
            LEDBADGE_MOD_NAME, __FUNCTION__); 

   printk(KERN_NOTICE "%s:, Attempting to register USB device.", LEDBADGE_MOD_NAME); 

   // attempt to register usb device
   ret = usb_register(&ledbadge_driver);

   // log dmesg of status
   if(ret == 0) printk(KERN_NOTICE "%s:, Device registered!", LEDBADGE_MOD_NAME);
   else         printk(KERN_ERR    "%s:, Device registration failed > %d", LEDBADGE_MOD_NAME, ret);

   return ret; 
}

/* ledbadge_exit

       caled on module unloading */

static void __exit ledbadge_exit(void) 
{
   printk(KERN_NOTICE "%s:, Unloading module. Handler: %s",
            LEDBADGE_MOD_NAME, __FUNCTION__); 

   printk(KERN_NOTICE "%s:, Attempting to deregister USB device.", LEDBADGE_MOD_NAME); 

   // attempt to deregister usb device
   usb_deregister(&ledbadge_driver);

   // log dmesg of status
   printk(KERN_NOTICE "%s:, Leaving module!", LEDBADGE_MOD_NAME);
}

module_init(ledbadge_init);
module_exit(ledbadge_exit); 

MODULE_LICENSE("GPL"); 

您是否將模組放在/lib/modules/<your kernel version>目錄樹中並在depmod此之後執行?

如果是這樣,那麼在/lib/modules/<your kernel version>/modules.alias文件中應該是這樣的一行:

alias usb:v0483p5750d*dc*dsc*dp*ic*isc*ip*in* ledbadge

當核心看到一個新的 USB 設備時,它會讀取其供應商和產品 ID 以及許多其他屬性,並將它們用作系統創建的模組別名的組件,如上所示。然後核心modprobe使用該別名執行命令(實際機制在 Linux 2.6 及更高版本的歷史中有所不同)。如果modprobe找到與其匹配的別名定義,則載入該別名定義中列出的模組。

我認為匹配以這樣一種方式發生,即最具體的匹配將獲勝。目前看起來hid-generic模組可能會勝過您的模組(假設您depmod在安裝模組後執行),因此您的 ledbadge 設備可能是 USB HID 類設備。因此,您可能還需要/改為聲明 USB HID 設備別名。像這樣的東西:

static const struct hid_device_id ledbadge_hid_table[] = {
       {HID_USB_DEVICE(LEDBADGE_VENDOR_ID,LEDBADGE_PRODUCT_ID)},
       { } // terminating entry
};

MODULE_DEVICE_TABLE(hid, ledbadge_hid_table);

文件中的結果行modules.alias應如下所示:

alias hid:b0003g*v00000483p00005750 ledbadge

引用自:https://unix.stackexchange.com/questions/440263