Could you recommend a way to figure out which driver is being used for a USB device. Sort of a usb equivalent of lspci -k command.
4 Answers
Finding the Kernel Driver(s)
The victim device
$ lsusb Bus 010 Device 002: ID 046d:c01e Logitech, Inc. MX518 Optical Mouse Bus 010 Device 003: ID 051d:0002 American Power Conversion Uninterruptible Power Supply We're going to try to find out what driver is used for the APC UPS. Note that there are two answers to this question: The driver that the kernel would use, and the driver that is currently in use. Userspace can instruct the kernel to use a different driver (and in the case of my APC UPS, nut has).
Method 1: Using usbutils (easy)
The usbutils package (on Debian, at least) includes a script called usb-devices. If you run it, it outputs information about the devices on the system, including which driver is used:
$ usb-devices ⋮ T: Bus=10 Lev=01 Prnt=01 Port=01 Cnt=02 Dev#= 3 Spd=1.5 MxCh= 0 D: Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 P: Vendor=051d ProdID=0002 Rev=01.06 S: Manufacturer=American Power Conversion S: Product=Back-UPS RS 1500 FW:8.g9 .D USB FW:g9 S: SerialNumber=XXXXXXXXXXXX C: #Ifs= 1 Cfg#= 1 Atr=a0 MxPwr=24mA I: If#= 0 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=00 Prot=00 Driver=usbfs ⋮ Note that this lists the current driver, not the default one. There isn't a way to find the default one.
Method 2: Using debugfs (requires root)
If you have debugfs mounted, the kernel maintains a file in the same format as usb-devices prints out at /sys/kernel/debug/usb/devices; you can view with less, etc. Note that debugfs interfaces are not stable, so different kernel versions may print in a different format, or be missing the file entirely.
Once again, this only shows the current driver, not the default.
Method 3: Using only basic utilities to read /sys directly (best for scripting or recovery)
You can get the information out of /sys, thought its more painful than lspci. These /sys interfaces should be reasonably stable, so if you're writing a shell script, this is probably how you want to do it.
Initially, lsusb seems to count devices from 1, /sys from 0. So 10-2 is a good guess for where to find the APC UPS lsusb gives as bus 10, device 3. Unfortunately, over time that mapping breaks down—sysfs re-uses numbers even when device numbers aren't. The devnum file's contents will match the device number given by lsusb, so you can do something like this:
$ grep -l '^3$' /sys/bus/usb/devices/10-*/devnum # the ^ and $ to prevent also matching 13, 31, etc. /sys/bus/usb/devices/10-2/devnum So, in this case, it's definitely 10-2.
$ cd /sys/bus/usb/devices/10-2 $ ls 10-2:1.0 bDeviceClass bMaxPower descriptors ep_00 maxchild remove urbnum authorized bDeviceProtocol bNumConfigurations dev idProduct power serial version avoid_reset_quirk bDeviceSubClass bNumInterfaces devnum idVendor product speed bcdDevice bmAttributes busnum devpath ltm_capable quirks subsystem bConfigurationValue bMaxPacketSize0 configuration driver manufacturer removable uevent We can be sure this is the right device by cating a few of the files:
$ cat idVendor idProduct manufacturer product 051d 0002 American Power Conversion Back-UPS RS 1500 FW:8.g9 .D USB FW:g9 If you look in 10-2:1.0 (:1 is the "configuration", .0 the interface—a single USB device can do multiple things, and have multiple drivers; lsusb -v will show these), there is a modalias file and a driver symlink:
$ cat 10-2\:1.0/modalias usb:v051Dp0002d0106dc00dsc00dp00ic03isc00ip00in00 $ readlink driver ../../../../../../bus/usb/drivers/usbfs So, the current driver is usbfs. You can find the default driver by asking modinfo about the modalias:
$ /sbin/modinfo `cat 10-2\:1.0/modalias` filename: /lib/modules/3.6-trunk-amd64/kernel/drivers/hid/usbhid/usbhid.ko license: GPL description: USB HID core driver author: Jiri Kosina author: Vojtech Pavlik author: Andreas Gal alias: usb:v*p*d*dc*dsc*dp*ic03isc*ip*in* depends: hid,usbcore intree: Y vermagic: 3.6-trunk-amd64 SMP mod_unload modversions parm: mousepoll:Polling interval of mice (uint) parm: ignoreled:Autosuspend with active leds (uint) parm: quirks:Add/modify USB HID quirks by specifying quirks=vendorID:productID:quirks where vendorID, productID, and quirks are all in 0x-prefixed hex (array of charp) So, the APC UPS defaults to the hid driver, which is indeed correct. And its currently using usbfs, which is correct since nut's usbhid-ups is monitoring it.
What about userspace (usbfs) drivers?
When the driver is usbfs, it basically means a userspace (non-kernel) program is functioning as the driver. Finding which program it is requires root (unless the program is running as your user) and is fairly easy: whichever program has the device file open.
We know that our "victim" device is bus 10, device 3. So the device file is /dev/bus/usb/010/003 (at least on a modern Debian), and lsof provides the answer:
# lsof /dev/bus/usb/010/003 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME usbhid-up 4951 nut 4u CHR 189,1154 0t0 8332 /dev/bus/usb/010/003 And indeed, its usbhid-ups as expected (lsof truncated the command name to make the layout fit, if you need the full name, you can use ps 4951 to get it, or probably some lsof output formatting options).
- 1I'm definitely gonna loose in my ever going debate with my friend of Windows vs Linux with this one :) . Will give it a few days to see if a simpler solution pops out. Thanks for the effort.TheMeaningfulEngineer– TheMeaningfulEngineer2013-01-02 13:37:18 +00:00Commented Jan 2, 2013 at 13:37
- @Alan OK, I've found two more ways, one of them is quite simple. Also, I've clarified which of two possible answers to "which driver?" each method provides.derobert– derobert2013-01-02 15:48:51 +00:00Commented Jan 2, 2013 at 15:48
- I don't think your claim about locating the device in
/sys/bus/usb/devicesis correct. I have a device on bus 1 thatusb-devicessays is device 12, but there's no/sys/bus/usb/devices/1-11on my system.Cerin– Cerin2015-04-15 19:44:35 +00:00Commented Apr 15, 2015 at 19:44 - @Cerin indeed it isn't. I'll put in a better one. Thank you.derobert– derobert2015-04-16 16:04:06 +00:00Commented Apr 16, 2015 at 16:04
- 1Amazing response. Thanks a lot for posting this. It was very helpful!Andrés Mejía– Andrés Mejía2021-04-04 20:24:00 +00:00Commented Apr 4, 2021 at 20:24
lsusb itself can get you good results. For compact output I use lsusb -t, where -t shows the devices as a tree; this format reports the driver as well.
Example output:
$ lsusb -t /: Bus 04.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/2p, 5000M /: Bus 03.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/2p, 480M /: Bus 02.Port 1: Dev 1, Class=root_hub, Driver=ehci-pci/3p, 480M |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/8p, 480M ... If no driver is used, the line will look like this (the device in my example is a camera for which I did remove the driver from the kernel):
|__ Port 6: Dev 4, If 1, Class=Video, Driver=, 480M Besides what derobert wrote, I find myself using
lsusb -t
Which will print a tree with various info about connected devices including an helpful « Driver » part.
and
dmesg | grep driver
which will list you the drivers of the latest plugged-in devices.
The pros is that these two commands come installed with all distributions.
One can also use lshw which will enumerate the devices on all buses including USB, PCI, etc so you can see which driver it uses and its associated IDs:
sudo lshw