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. :)
udev
adds some environment variables to the partition node (leaf node) including partition entry flags for MBR table. Bootable partition should have ID_PART_ENTRY_FLAGS=0x80
.
Try this rule and you gonna see all environment variables (source: Pass ATTR{idVendor} as argument in udev script):
KERNEL="sd[a-z][1-9]", RUN+="/bin/sh -c 'echo == >> /home/username/Desktop/usb-storage.txt; env >> /home/username/Desktop/usb-storage.txt'"
A rule that works for me in Ubuntu 14.04:
ACTION=="add", KERNEL=="sd[a-z][1-9]", ENV{ID_PART_ENTRY_FLAGS}=="0x80", RUN+="/bin/sh -c 'echo 0 > /sys%p/../../../../../../../authorized'"
Best Answer
I don't believe that you can accomplish this with dumb devices as mentioned in @meuh comment here.. With devices that actually communicate
udevadm monitor
works fine. Here's an example of plugging and unplugging an android phone (powered on):A flash drive produces similar but much more verbose results. If you wanted to make use of this information to trigger some action, you could redirect the output to a file and use
tail
to monitor the file for new activity.Tests with an android phone (turned off, but charging) indicated no change whatsoever in
lsusb -v |grep Power
output which IMHO confirms that dumb devices that just draw or supply power can't be detected.Another simple way to detect devices that aren't dumb is to store baseline information and compare current info to that. There are numerous ways to do this. One simple alternative to
udevadm
mentioned above that leaps to mind is to simply collect baseline data for the system without the device to be detected plugged in. For example: Collect baseline data:lsusb > baseline.txt
Check current data and compare:This will compare the current USB connections to the baseline once every second.
If your script updates your baseline data upon detection you will also be able to detect device removal by this method.