The linux kernel has a facility called “usbmon” which can be used to sniff the USB bus. It’s been in there for ages, and the output is really easy to collect, even from the command line shell. Simply mount debugfs and insmod the usbmon module:
mount -t debugfs none_debugs /sys/kernel/debug modprobe usbmon
Then you can just cat USB traffic like this:
It all comes out in an ASCII dump format which is easily parsed. Every USB bus also has a device file where you can sniff the raw packets straight off the wire. More info in the usbmon documentation.
But while it’s all easily parsed if you need it, there aren’t really any tools around that do it for you. That is… except for libpcap. Libpcap is the power behind the throne of the venerable tcpdump tool. Tcpdump is not much more than a command line parser and pretty-printer of various network protocols. The heavy duty lifting is done by libpcap, not least by providing a cross-platform API for sniffing devices, something that is otherwise non-standard and different on every platform. It’s great, I’ve used it before (in capstats) and it’s very easy to use.
Libpcap on linux supports usbmon sniffing, which means you can use tcpdump to sniff a USB port and write this to a capture file. But best of all: wireshark, the all-singing all-dancing network analyzer that uses tcpdump capture files, has USB support as well.
So this is the result:
The screenshot shows a filter applied to only see device 18 on the sniffed USB bus. That’s an arduino, i.e. an FTDI USB-serial chip. The FTDI chips send status updates to the USB host system every 16ms (!). The status update consists of a two-byte message (described here). This is actually present in every packet coming in from the FTDI chip; status updates just don’t have any other data. So for a clean sniffing session from the arduino, we want to filter out any packets that are < 3 bytes in length.
The end result is serial data which the arduino sent to the host system. The screenshot shows a session on my arduino shell, arsh. This is great stuff – wireshark includes a massive amount of analysis tools and lots of options for filtering and otherwise massaging your captured data.
You need relatively recent versions of libpcap, tcpdump and wireshark for this. I compiled all three of these out of their respective repositories (easy compile all). On my ubuntu system, the libpcap version was particularly old. Tcpdump doesn’t have a pretty-printer for USB data yet, so you can only dump to a capture file for processing by wireshark.