Adding new vendor and product IDs to an existing USB driver on Linux

Jon Kåre Hellan - (email)

Frequently, when a USB device doesn't work out of the box with Linux, it turns out that there already is a driver which can handle the device. All that must be done is to make the driver recognize the device. Unfortunately, until recently, you had to build your own kernel to fix this.

This has now changed. As of kernel version 2.6.21, all USB drivers can be told to recognize an additional device without rebuilding. Support for USB serial drivers was last to come. Other USB drivers have had this capability since 2.6.16.

To tell which kernel version you are running, give this command in a terminal window:
uname -r
My Ubuntu Gutsy answers '2.6.22-14-generic', which is a variant of the 2.6.22 kernel version.

Imagine that you've just unpacked your brand new Yoyodyne USB frobitzer. You've plugged it into your computer, but it didn't work. You have googled, and found that 'foo_driver' is reported to handle an earlier model of the same device.

Give this command in a terminal window:

lsusb
You'll see a number of lines looking more or less like this:
Bus 003 Device 002: ID 34ca:d365 Yoyodyne Electronics Frobitzer
It's easy to tell which line belongs to your device: It disappears when you unplug it. You need the numbers '34ca' and 'd365'. '34ca' is called the vendor ID, and 'd365' the product ID. The kernel uses these two numbers when choosing a driver.

If you see 'command not found' when you give the 'lsusb' command, you have to install the 'usbutils' package.

Here's what you do:
  • Unplug the device. I think this only is necessary if another driver has recognized the device, but is handling it poorly. But it can't hurt in any case.
  • Become root in a terminal window.
  • Give the commands:
    modprobe foo_driver
    echo 34ca d365 > /sys/bus/usb/drivers/foo_driver/new_id
    USB serial drivers are typically used with devices like cell phone cables, cellular modems, bluetooth adapters, etc. If this is a USB serial device, you have to make sure that you're running 2.6.21 or later. The command sequence becomes
    modprobe foo_driver
    echo 34ca d365 > /sys/bus/usb-serial/drivers/foo_driver/new_id
  • Plug in the device.

Replace 'foo_driver' and the IDs with your actual driver, vendor ID and product ID.

What if you have to add two different IDs to the same driver? Then you do it with two echo statements, like this:

echo 34ca d365 > /sys/bus/usb/drivers/foo_driver/new_id
echo 1cc2 5299 > /sys/bus/usb/drivers/foo_driver/new_id
Adding IDs only works if the kernel has been built with CONFIG_HOTPLUG enabled. Almost all current distributions turn this feature on.

Hotplugging with udev

You can create a udev rule to make the device "just work" when it is plugged in. The following hasn't been tested, but should be close:

Create /etc/udev/rules.d/95-foo.rules containing the following:

# Rules for hotplugging Yoyodyne USB frobitzers
SUBSYSTEM=="usb", SYSFS{idVendor}=="34ca", SYSFS{idProduct}=="d365", RUN="/etc/yoyodyne_foo.sh"
# You may need lines like these to create devices with correct groups
# and permissions, and set up symlinks:
# KERNEL=="ttyUSB0", SYMLINK="modem", GROUP="dialout", MODE="0660"
# KERNEL=="ttyUSB1", GROUP="dialout" MODE="0660"
and /etc/yoyodyne_foo.sh as follows:
#!/bin/sh
modprobe foo_driver
echo 34ca d365 > /sys/bus/usb/drivers/foo_driver/new_id
Change these files to suit your situation. And please report bugs.

Thanks

to Andy Hill for this page with info about udev.

to Oliver Neukum and Dominic Curran for helpful comments.