A12 : Handling USB HID devices

Overview

Some remote devices are treated like general keyboards by the kernel. Without patched kernel drivers such a device can only be used by the devinput lirc driver. The typical symptom is dmesg lines like these in

[178998.885410] usb 1-1: new low-speed USB device number 3 using xhci_hcd
[178999.061504] usb 1-1: New USB device found, idVendor=0471, idProduct=20cc
[178999.061517] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[178999.061526] usb 1-1: Product: MCE USB IR Receiver- Spinel plus
[178999.061533] usb 1-1: Manufacturer: PHILIPS
[178999.064751] usb 1-1: ep 0x81 - rounding interval to 64 microframes, ep desc says 80 microframes
[178999.137558] hid-generic 0003:0471:20CC.0003: input,hiddev0,hidraw2: USB
    HID v1.00 Keyboard [PHILIPS MCE USB IR Receiver- Spinel plus] on usb-0000:00:14.0-1/input0

The important one is the last hid-generic... which basically says that the HID driver has claimed the device, making it impossible for the usual remote driver (mceusb in this case) to use it.

As long as the HID driver manages the device it can only be used as a regular keyboard. If you want to use another driver e. g., due to need of blasting (transmitting) you must first disable the HID driver and bind another low-level driver to it. This only works occasionally, if you can find another kernel driver which can handle the remote. Thus, the rest of this appendix is more or less obsolete unless you are about to actually patch an existing kernel driver.

Disabling the HID driver

Disabling the HID driver can be done in many ways including reloading the kernel modules in a different order, using a usbhid quirk or using xorg.conf. Here we will focus on unbinding using the kernel userspace unbind interface described in this article, this HOWTO. and some kernel docs

The basic idea is to unbind the usbhid driver using a udev rule. Such a rule could be defined as

    SUBSYSTEM=="usb", ATTRS{idVendor}=="0471", ATTRS{idProduct}=="20cc", \
        MODE="0660", GROUP="lirc",
        RUN="/bin/sh -c 'echo -n $kernel:1.0 > /sys/bus/usb/drivers/usbhid/unbind'"

The ATTRS{idVendor} and ATTRS{idProduct} could be obtained from the dmesg output when inserting the device, see example above or using lsusb(1). This rule not only unbinds the usbhid driver, at also allows member of the lirc group to access the device.

Check the results by listing the driver directory.

Bind the new driver.

First, check the driver directory for attached devices:

    $ tree /sys/bus/usb/drivers/usbhid/
    /sys/bus/usb/drivers/usbhid/
    ├── 1-1.1:1.0 -> ../../../../devices/pci0000:00/0000:00:1c.4/0000:0b:00.0/usb1/1-1/1-1.1/1-1.1:1.0
    ├── 1-1.2:1.0 -> ../../../../devices/pci0000:00/0000:00:1c.4/0000:0b:00.0/usb1/1-1/1-1.2/1-1.2:1.0
    ├── 1-1.3:1.0 -> ../../../../devices/pci0000:00/0000:00:1c.4/0000:0b:00.0/usb1/1-1/1-1.3/1-1.3:1.0
    ├── bind
    ├── module -> ../../../../module/usbhid
    ├── new_id
    ├── remove_id
    ├── uevent
    └── unbind

Doing this with the device inserted and removed will reveal the entry created when the device is inserted. Here it is 1-1.1:1.0

You can manually unbind the device from the usbhid driver by using:

	# echo  1-1.1:1.0 > /sys/bus/usb/drivers/usbhid/unbind

If there is another driver like mceusb which supports the device you can bind it to the same device using

	# echo  1-1.1:1.0 > /sys/bus/usb/drivers/mceusb/bind

An alternative is to just reload the driver using modprobe.

If you have reason to believe that the driver works with the capture device although the driver does not recognize it you can do something like

	# echo  "0471 20cc" > /sys/bus/usb/drivers/mceusb/new_id

Here, 0471 and 20cc is the vendor and product id from dmesg. Beware: this might very well halt your system!

This text only defines the outlines. Refer to the references for details.