I'm looking for a way to replace my keyboard kernel module to a custom one. I have a Logitech MK710 keyboard + mouse set for this purpose, with a USB receiver with those 2 interfaces. Automatically, this USB receiver is managed by default usb
, usbhid
or logitech-hidpp-device
modules, there is some information (note: 1-2
is the receiver device):
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
What I want to achieve is write a proper module which would be chosen by a kernel instead of those default drivers. I think it's a matter of writing a proper module alias, but I'm not sure because nothing worked yet. Things I already tried are:
put my module inside
/lib/modules/$(uname -r)/kernel/drivers
directory (I created my owncustom
subdir inside and put the .ko file there)use a proper alias in the module C code, I tried all options listed below (note:
USB_VENDOR_ID
andUSB_PRODUCT_ID
are macros used by me and their values are set properly for my specific device):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);
or
static struct hid_device_id mod_table [] = {
{ HID_USB_DEVICE(USB_VENDOR_ID, USB_PRODUCT_ID) },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(hid, mod_table);
and
static struct usb_device_id mod_table [] = {
{ USB_DEVICE(USB_VENDOR_ID, USB_PRODUCT_ID) },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, mod_table);
- remove original (default) HID drivers from
/lib/modules/$(uname -r)/kernel/drivers
directory (those 3 I specified at the top).
Yet still kernel chooses to load original modules instead of my own. I even made sure that only my driver's alias specifies the vendor and product IDs (checking it in modules.alias
file), but nothing works. The module starts to work only when I decide to detach the kernel drivers manually from user space by libusb
library (using libusb_detach_kernel_driver
function) and reload my own custom module - only then the kernel associates the device with my driver, but that's only till the next boot. I'd like to make it permanent, or even automatic. I hope the whole concept is understandable and is not too big of a mess. Thanks in advance.