Reverse engineering a Windows USB driver

For a while, I was really into reverse-engineering USB drivers. Don’t ask why. The heart wants what the heart wants. I didn’t finish this “hairball” post, but it has some info in it that still might be good.

I recently stumbled across this post and it inspired me. I decided to try to reverse engineer the USB protocol for my Omron pedometer, which can upload your step data, but only to a Windows computer.

There are two parts to writing a Linux driver for a new USB device: reverse-engineering the USB protocol, and writing the Linux program.

Reverse-engineering the USB protocol

Typically your problem is that a device only runs under Windows. Like it or not, that means that you’re going to need something that runs Windows. It can be a Windows computer, or you can get fancy and run Windows as a “guest” operating system using something like VMWare to do virtualization. That is, you’d install Linux, then install VMWare, then install Windows to run under VMWare. But let’s start simple.

Step 0. Find the Vendor ID and Product ID of your device

Every USB device should have a Vendor ID plus a Product ID (sometimes called a device ID) that identifies it. You’ll need to discover this information before you can talk to the device. I plugged my Omron pedometer into a linux machine and typed “lsusb”. You’ll get a lot of information back. I saw a line like

Bus 002 Device 018: ID 0590:0028 Omron Corp.

That tells me that the vendorid is hexadecimal value 0x0590 (which is 1424 in decimal) and the productid is hex value 0x0028 (which is 40 in decimal). For other operating systems, this post tells you how to find your vendor id and product id under Mac and Windows. For Windows XP, it looks like you can run “msinfo32.exe” and then look under “Components” and then “USB” and look for “VID_” (vendor id) and “PID_” (product id).

1) The simple approach: a dedicated Windows computer

In the beginning, it’s easiest to just use a Windows computer and run some software to sniff on the USB packets as they go back and forth. The wild part is that the best open-source/free program I found is five years old (SnoopyPro). It still worked fine on Windows XP though. SnoopyPro is the program you want. There’s a whole long history of how it forked from USBSnoopy (evidently also called “sniff-bin“), and there’s another program called sniffusb which is related but different (I think both sniffusb and SnoopyPro are forks off of the original USBSnoopy/sniff-bin program). It’s all very confusing. I went with SnoopyPro and it worked fine for me.

Further reading on SnoopyPro and related USB sniffer programs:
Some documentation on how to use SnoopyPro
If you’re willing to shell out for a book, it looks like USB Complete, now in its third edition, is one of the best. – mentions all the different sniffers – talks about how to convert SnoopyPro (and SniffUsb) logs/traces into hexadecimal data.

Are there other options? Sure. USB Monitor from HHD Software is $85 and runs on Windows. Or you could spend $850-950 to buy a hardware USB protocol analyzer. Since I have only a casual interest, that’s a bit steep for me.

One last option is to run Windows as a virtual “guest” on a Linux system running something like VMWare. VMWare can let programs interact with USB devices. As the virtual version Windows interacts with the USB device, the Linux computer gets to see everything that happens, because it sits between Windows and the USB device. In fact, Eric Preston presented a method that could log all the the output of the Linux usbmon program as binary data. Eric changed usbmon to use relayfs so that large amounts of data could be quickly relayed from kernel space to user space, then wrote a user space program to dump that binary data to disk. Eric also wrote a dissector for ethereal so that he could view the USB data in real-time. Unfortunately the PDF of his slide presentation have disappeared from where they used to be. In fact, all of appears to be gone now. :(

By the way, Ethereal is now known as Wireshark, and it is a protocol analyzer that runs on many platforms and apparently supports USB traces. It looks like Wireshark has supported USB since version 0.99.4:

Wireshark now supports USB as a media type. If you’re running a Linux distribution with version 2.6.11 of the kernel or greater and you have the usbmon module enabled and you have a recent CVS version of libpcap (post-0.9.5) installed you can also do live captures. More details can be found at the USB capture setup page on the wiki.

Follow the link in the quote to find Wireshark’s USB wiki page.

On Ubuntu 7.10 (Gutsy Gibbon), I was able to do these commands:

sudo mount -t debugfs none_debugs /sys/kernel/debug
sudo modprobe usbmon
ls /sys/kernel/debug/usbmon
0s 0t 0u 1s 1t 1u 2s 2t 2u

General USB Reading:
USB in a NutShell is a pretty good overview of how USB communication goes.
This Java and USB tutorial starts with a good overview of USB.
This USB and Linux tutorial starts to get into the nitty gritty of USB on Linux.