Linux – How to Use Kernel Driver Bind/Unbind Interface for USB-HID Devices

developmentdriverskernellinuxusb

First background. I am developing a driver for Logitech game-panel devices. It's a keyboard with a screen on it. The driver is working nicely but by default the device is handled by HID. In order to prevent HID taking over the device before my driver, I can blacklist it in hid-core.c. This works but is not the best solution as I am working with several people and we all have to keep patching our HID module which is becoming a chore, especially as it often involves rebuilding initramfs and such.

I did some research on this problem and I found this mailing list post, which eventually took me to this article on LWN. This describes a mechanism for binding devices to specific drivers at runtime. This seems like exactly what I need.

So, I tried it. I was able to unbind the keyboard from HID. This worked and as expected I could no longer type on it. But when I tried to bind it to our driver I get "error: no such device" and the operation fails.

So my question is: How do I use kernel bind/unbind operations to replicate what happens when you blacklist a HID device in hid-core and supply your own driver? – that is – to replace the need to patch hid-core.c all the time?

The source of our driver is here: https://github.com/ali1234/lg4l

Best Answer

Ok, turns out the answer was staring me in the face.

Firstly, whether using our custom driver, or using the generic one that normally takes over the device, it's still all ultimately controlled by HID, and not USB.

Previously I tried to unbind it from HID, which is not the way to go. HID has sub-drivers, the one that takes over devices that have no specialized driver is called generic-usb. This is what I needed to unbind from, before binding to hid-g19. Also, I needed to use the HID address which looks like "0003:046d:c229.0036" and not the USB address which looks "1-1.1:1.1".

So before rebinding I would see this on dmesg:

generic-usb 0003:046D:C229.0036: input,hiddev0,hidraw4: USB HID v1.11 Keypad [Logitech G19 Gaming Keyboard] on usb-0000:00:13.2-3.2/input1

Then I do:

echo -n "0003:046D:C229.0036" > /sys/bus/hid/drivers/generic-usb/unbind
echo -n "0003:046D:C229.0036" > /sys/bus/hid/drivers/hid-g19/bind

And then I see on dmesg:

hid-g19 0003:046D:C229.0036: input,hiddev0,hidraw4: USB HID v1.11 Keypad [Logitech G19 Gaming Keyboard] on usb-0000:00:13.2-3.2/input1

So like I said, staring me in the face, because the two key pieces of information are the first two things on the line when the device binds...

Related Question