34

This question is two-fold:

First, how do you manually detach a driver from a USB device and attach a different one? For example, I have a device that when connected automatically uses the usb-storage driver.

usbview output

Vendor Id: xxxx
Product Id: xxxx
...
    Number of Interfaces: 2
    Interface Number: 0
        Name: usb-storage
        Number of Endpoints: 2
        ...
    Interface Number: 1
        Name: (none)
        Number of Endpoints: 2
        ...

I do not want to use the usb-storage driver, so in my application I use the libusb library to detach the usb-storage driver and then I claim the interface. I then can send data to and from the applications running on my USB device and on my host Linux system.

How do you detach a driver manually outside of an application?


Second, how do I automatically assign the driver to attach on device plugin? I currently have a udev rule setup to set the device permissions automatically:

SUBSYSTEM=="usb", ATTR{idVendor}=="xxxx", MODE="0666"

Can I use udev rules to assign drivers to specific interfaces on the USB device? For example, if I wanted the usbnet module to be used on automatically on interface 0 instead of usb-storage, is that possible in udev?

7
  • 1
    If part of the problem is loading the right module, see Webcam on Angström Dec 5, 2011 at 23:23
  • 1
    Do you need at all the usb-storage module? because if not you can put it in a blacklist and it wouldn't load at all.
    – Hanan
    Dec 6, 2011 at 11:57
  • @Gilles, I am successfully able to load the LKM. My question is how do I manually and automatically attach that to the device?
    – linsek
    Dec 6, 2011 at 15:47
  • @Hanan, currently I have no use for the usb-storage module. I may end up needing to blacklist it to automatically attach the correct module, but first I need to know how to attach the usbnet one.
    – linsek
    Dec 6, 2011 at 15:49
  • 1
    @njozwiak Module usbnet will not automatically load, because it have no information about hardware, which can use it. Try to find proper driver and use, for example, modinfo kalmia. In the alias lines you will see vendor id xxxx and product id yyyy as usb:vxxxxpyyyy. Or you can edit file /lib/modules/kernel_version/modules.usbmap and for your HW you can delete line, where is for you HW module usb-storage or change usbstorage with proper net driver. But after depmod -a this change will go away...
    – Jan Marek
    Jan 12, 2012 at 7:44

1 Answer 1

23

For the first part of the question, I've looked and couldn't find a better way to detach a USB driver than what you're already doing with libusb.

As for the second part of the question, udev can react to driver loading, but not force a specific driver to be assigned to a device.

Every driver in the Linux kernel is responsible for one or more devices. The driver itself chooses what devices it supports. It does this programmatically, i.e. by checking the device's vendor and product ID, or, if those aren't available (e.g. an old device), performing some auto-detection heuristics and sanity checks. Once the driver is confident it's found a device it supports, it attaches itself to it. In short, you often can't force a particular driver to use a particular device. Sometimes, however, a device driver is generous with what it accepts, and a device can work that it doesn't know about. Your mileage will vary! In the past, I've had to manually add weird PCI device/vendor IDs to drivers that should support them, with mixed success and a few amusing kernel crashes.

Now, in the case of modules, there's an extra step. The module loader is woken up by the kernel when a new device is detected. It's passed a ‘modalias’ string, which identifies the device and looks something like this for USB devices:

usb:v046DpC221d0170dc00dsc00dp00ic03isc00ip00

This string contains the device class (usb) and class-specific information (vendor/device/serial number, device class, etc). Each kernel driver contains a line such as:

MODULE_ALIAS("usb:...")

Which must match the usbalias (wildcards are used to match multiple devices). If the modalias matches one that the driver supports, this driver is loaded (or notified of the new device, if it's there already).

You can see the supported devices (by modalias) and their associated modules with

less /lib/modules/`uname -r`/modules.alias

If you grep for the usb-storage device driver, you'll see it has some specific devices it supports by vendor and device ID, and will also attempt to support any device with the right (storage) class, no matter the vendor/device.

You can influence this using userspace mechanisms on your OS (/etc/modprobe.d/ on Debian and friends). You can blacklist modules, or you can specify modules to be loaded by modalias, just like the modules.alias file (and using the same syntax). depmod -a will then regenerate the module loader's patterns.

However, even though you can lead this particular horse to water, but you can't make him drink. If the driver has no support for your device, it should ignore it.

This is the theory in the general case.

In practice, and in the case of USB, I see your device appears to have two interfaces, of which storage is one. The kernel will attach to the storage interface of the overall device. If the other interface has the right class, the usbnet driver could attach to it. Yes, you can have multiple drivers attached to the same physical device, because a USB device exports multiple interfaces (e.g. my Logitech G15 keyboard exports two because it has a keyboard device and an LCD screen, each of which is handled by a separate driver).

The fact that the second interface of your USB device isn't detected is indicative of lack of support in the kernel. Whatever the case, you can list the device interfaces/endpoints in excruciating detail using lsusb -v | less, then scroll down to your particular device (you can limit the output by device:vendor ID or USB path if you're so inclined).

Please note: I'm oversimplifying a bit here with respect to the logical structure of USB devices. Blame the USB consortium. :)

2
  • 4
    There is already static struct usb_device_id id_table [] = { { USB_DEVICE(VENDOR_ID, PRODUCT_ID) }, { }, }; MODULE_DEVICE_TABLE (usb, id_table); in the code, is it redundant with modalias ?
    – Thomas
    Jan 29, 2014 at 22:23
  • In my case those lines are autogenerated by some Makefile magic anywhere within the driver. That's why I added three times the lines for MODULE_ALIAS but it never gets listed. Anyway thanks for the lsusb -v. with that I could check it and find the flaw in my idea. I then grep the source for a known identifier and found the array with the entries that I had to manipulate. Dec 19, 2018 at 15:09

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .