将 HID 设备驱动程序替换为自定义驱动程序

将 HID 设备驱动程序替换为自定义驱动程序

我正在寻找一种将键盘内核模块替换为自定义模块的方法。我有一套用于此目的的 Logitech MK710 键盘 + 鼠标,以及带有这 2 个接口的 USB 接收器。自动的,这个USB接收器是默认管理的usbusbhid或者logitech-hidpp-device模块,有一些信息(注:1-2是接收器设备):

ubuntu@ubuntu-VirtualBox:/sys/bus/usb/devices/1-2$ tree | grep driver
│   ├── driver -> ../../../../../../bus/usb/drivers/usbhid
│   ├── driver -> ../../../../../../bus/usb/drivers/usbhid
│   │   │   ├── driver -> ../../../../../../../../bus/hid/drivers/logitech-hidpp-device
│   │   │   ├── driver -> ../../../../../../../../bus/hid/drivers/logitech-hidpp-device
│   │   ├── driver -> ../../../../../../../bus/hid/drivers/logitech-djreceiver
│   ├── driver -> ../../../../../../bus/usb/drivers/usbhid
├── driver -> ../../../../../bus/usb/drivers/usb

我想要实现的是编写一个适当的模块,该模块将由内核选择,而不是那些默认驱动程序。我认为这是编写适当的模块别名的问题,但我不确定,因为还没有任何效果。我已经尝试过的事情是:

  • 将我的模块放入/lib/modules/$(uname -r)/kernel/drivers目录中(我在其中创建了自己的custom子目录并将 .ko 文件放在那里)

  • 在模块 C 代码中使用正确的别名,我尝试了下面列出的所有选项(注意:USB_VENDOR_IDUSB_PRODUCT_ID是我使用的宏,它们的值已针对我的特定设备正确设置):

    static struct hid_device_id mod_table [] = {
        { HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, USB_VENDOR_ID, USB_PRODUCT_ID) },
        { }                      /* Terminating entry */
    };
    MODULE_DEVICE_TABLE(hid, mod_table);
    

或者

static struct hid_device_id mod_table [] = {
    { HID_USB_DEVICE(USB_VENDOR_ID, USB_PRODUCT_ID) },
    { }                      /* Terminating entry */
};
MODULE_DEVICE_TABLE(hid, mod_table);

static struct usb_device_id mod_table [] = {
    { USB_DEVICE(USB_VENDOR_ID, USB_PRODUCT_ID) },
    { }                      /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, mod_table);
  • 从目录中删除原始(默认)HID 驱动程序/lib/modules/$(uname -r)/kernel/drivers(我在顶部指定的 3 个)。

然而内核仍然选择加载原始模块而不是我自己的模块。我什至确保只有我的驱动程序的别名指定了供应商和产品 ID(在modules.alias文件中检查),但没有任何效果。仅当我决定通过libusb库(使用libusb_detach_kernel_driver函数)手动从用户空间分离内核驱动程序并重新加载我自己的自定义模块时,该模块才开始工作 - 只有那时内核才会将设备与我的驱动程序关联起来,但这只是到下次启动为止。我想让它永久化,甚至是自动的。我希望整个概念是可以理解的并且不是太混乱。提前致谢。

答案1

您很可能被 initramfs 绊倒了:安装当前内核时,原始 HID 驱动程序模块的副本已存储在其中,如果您在添加模块时没有重新生成 initramfs,则您的自定义驱动程序模块将不会被在那里。

在启动时,当系统仍在 initramfs 上运行并且尚未挂载真正的根文件系统时,USB 支持模块是最先加载的。所以系统仍在寻找并加载原始usbhid+logitech-hidpp-device模块组合。

您似乎使用的是 Ubuntu,因此 Debian 风格的sudo update-initramfs -u命令应该足以使用当前的模块集和其他配置文件重建当前内核版本的 initramfs。

相关内容