usbmon truncation

related: embedded , usb , linux , kernel

My coworker, Eric, is extending a USB peripheral we developed for a customer.  It was working with two USB endpoints, and he is adding a third.  Unreasonable complications abounded.

The USB protocol involves the OS sending a bunch of information requests to the device during initialization to determine what it is, how many endpoints it has, etc.  Late in the initialization, Linux is asking our device for its endpoint descriptors.  With two endpoints the response ended up being 32 bytes.  With the third endpoint added, that response should be 39 bytes.

We watch what the device is doing using the usbmon kernel module, and analyze the traffic dump with VMware’s VUSB Analyzer.  Before the addition, the packet was 32 bytes (correct).  After the addition, the packet was 32 bytes.  Incorrect!

Eight hours down the drain tracking this one down.  We obviously thought it was a software bug.  Until, late in the day, Eric discovered that Linux could actually see the third endpoint.  That wouldn’t be possible if the descriptor packet was incomplete.

So I started investigating VUSB Analyzer’s source to see why it’s truncating to 32 bytes.  It turns out, it isn’t.  The USB debug driver, usbmon, truncates the ‘u’ format devices to 32 bytes by default!

It turns out this can be set with an ioctl.  Which doesn’t work too well with cat, our information-gatherer of choice.

But there’s a nice guy at Red Hat who makes a proper usbmon command-line utility that supports all of its various ioctl options.  Using his ‘usbmon’ tool, you can get a nice, untruncated output with:

./usbmon -i <USB bus> -fu -s 100