How to assign USB driver to device-Collection of common programming errors

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 endpoints, of which storage is one. The kernel will attach to the storage endpoint of the overall device. If the other endpoint 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 endpoints (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 endpoint of your USB device isn’t detected is indicative of lack of support in the kernel. Whatever the case, you can list the device 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. 🙂