December 1, 2008

USB devices and linux

It was/is time to delve into the details of USB programming. I have notions of doing some unusual things with a USB to parallel printer cable (which can be purchased in a suposedly bidirectional flavor for about $10.00 these days). Given the fact that computers these days lack the good old 25 pin parallel port we all knew and loved, this might be a nice way to support some legacy devices (and I don't mean printers either).

Here are some useful links:

There is even a downloadable book by Detlef Fliegl on programming linux USB device drivers, which I have a copy of right here.

USB basics

USB is built as a tree hierarchy. The root of the tree is the virtual root hub in your computer. There can certainly be more than one "controller" (root hub) in a given computer. Additional hubs can be connected to a root. There are two "versions" of USB, version 1.1 and version 2.0. Version 1.1 supported 2 speeds (low speed at 1.5 Mbit/second and full speed at 12 Mbit/second). Version 2.0 adds high speed (at 480 Mbit/second). USB 2.0 and high speed make things like external hard drives and video cameras practical. Up to 127 devices are supported on a hub.

USB on my system

Some preliminary poking around on my system yields the following:
ls -l | grep usb
 crw-rw----  1 root root   249,   1 Nov 19 14:59 usbdev1.1_ep00
 crw-rw----  1 root root   249,   0 Nov 19 14:59 usbdev1.1_ep81
 crw-rw----  1 root root   249,   3 Nov 19 14:59 usbdev2.1_ep00
 crw-rw----  1 root root   249,   2 Nov 19 14:59 usbdev2.1_ep81
 crw-rw----  1 root root   249,   5 Nov 19 14:59 usbdev2.2_ep00
 crw-rw----  1 root root   249,   4 Nov 19 14:59 usbdev2.2_ep81
 crw-rw----  1 root root   251,   0 Nov 19 14:59 usbmon0
 crw-rw----  1 root root   251,   1 Nov 19 14:59 usbmon1
 crw-rw----  1 root root   251,   2 Nov 19 14:59 usbmon2
lspci | grep USB
 00:02.0 USB Controller: nVidia Corporation CK804 USB Controller (rev a2)
 00:02.1 USB Controller: nVidia Corporation CK804 USB Controller (rev a3)
lspci -vv yields:
00:02.0 USB Controller: nVidia Corporation CK804 USB Controller (rev a2) (prog-if 10 [OHCI])
	Subsystem: ASUSTeK Computer Inc. K8N4-E or A8N-E Mainboard
	Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
	Status: Cap+ 66MHz+ UDF- FastB2B+ ParErr- DEVSEL=fast >TAbort- SERR- 
	Kernel driver in use: ohci_hcd
	Kernel modules: ohci-hcd

00:02.1 USB Controller: nVidia Corporation CK804 USB Controller (rev a3) (prog-if 20 [EHCI])
	Subsystem: ASUSTeK Computer Inc. K8N4-E or A8N-E Mainboard
	Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
	Status: Cap+ 66MHz+ UDF- FastB2B+ ParErr- DEVSEL=fast >TAbort- SERR- 
	Kernel driver in use: ehci_hcd
	Kernel modules: ehci-hcd
I don't have this all figured out, but as near as I can tell, my motherboard (an ASUS A8N-E) has two usb controllers, but only the first is actually connected to connectors or headers. This has been confirmed by experiment by plugging usb devices into every possible place. There are 4 usb connectors on the back, and 3 headers (one of which I connect to my front panel USB) on the motherboard. No matter which of the headers I use, lsusb only ever shows devices on Bus 002:
lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 012: ID 067b:2305 Prolific Technology, Inc. PL2305 Parallel Port
Bus 002 Device 002: ID 046d:c00e Logitech, Inc. M-BJ58/M-BJ69 Optical Wheel Mouse
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub

USB parallel ports

My first project (and the impetus for all this) is to use an inexpensive little USB to parallel converter to read a few bits from an old device we used to use with an honest to goodness parallel port. As you may well know, these have all but disappeared from modern desktop computers. (In fact there is a new breed of desktop computer that boasts of being "legacy free", which means no serial ports, parallel ports, floppy, ISA bus and so forth.)

See my notes on USB parallel devices for more information.

Udev, modules, kernel drivers and all that jazz

For better or for worse (mostly better) the whole business of USB device drivers is tightly intertwined with the way the linux kernel handles removable devices. The udev system handles dynamic (yet persistent) naming of devices, as well as providing hooks to user space actions when devices come and go. Device drivers are dynamically loaded (but apparently not unloaded) when removable devices are plugged in. See this discussion of udev and modules for more information.
Have any comments? Questions? Drop me a line!

Adventures in Computing / tom@mmto.org