Reverse Engineering Creative Sound Blaster E1

The Creative Sound Blaster E1 is a USB DAC and headphone amplifier. Additionally, it has a built-in microphone, and has two seperate headphone jacks, one of which can be used as a microphone input instead, if it is set as such in Creative’s software. Naturally, their proprietary program only works on Windows, so it is stuck in the default mode (both jacks serve as headphone ports). Let’s fix that.

Reverse engineering something like this is in principle fairly simple: run their software under Windows and use Wireshark to see what commands it is sending to the USB device. Then figure out which are relevant, and send the same commands under Linux.

So I booted my Windows VM, let it install updates for a while, and installed Creative’s software. I started Wireshark, monitering USB, and attached the USB device to the VM in VirtualBox.

Flipping the setting in Creative’s software, it seems to send multiple requests, mixed into the flood of commands generally going back and forth between the host and device. The USB HID GET_REPORT and SET_REPORT requests stand out. I’m not really too familiar with the details of the USB protocol, but the SET_REPORT command seems to be the more interesting one, since we’re trying to set the device’s mode.

Looking at packets sent to the E1 in Wireshark

Switching the mode produces five SET_REPORT requests; after testing, it seems only the first is needed. It might be interesting to dig deeper into Creative’s protocol in the future though.

What is the easiest way to deal with USB HID reports from user space under Linux? It turns out linux provides a special kind of block device at /dev/hidraw* to easily interface with such things.

echo -n -e '\x02\x02' > /dev/hidraw0 # Sets port to microphone mode
echo -n -e '\x02\x00' > /dev/hidraw0 # Sets port back to extra headphone

The above commands require root, and hidraw0 should be replaced with the correct device on your system. But after testing this, it works!

Now perhaps I should see if this can be nicely integrated into the kernel driver…

Edit: Support is now in the mainline Linux kernel, in commit 388fdb8.