A Beagleboard xM-based USB sniffer

I bought a Beagleboard xM more than 2 years ago, as I wanted to make it work as a USB sniffer, based on the work of Nicolas Boichat. But at this time I didn’t manage to make it work, as my knowledge on embedded systems was quite limited.

I have lately been working back on this, and last week during a hacking session in my local hackerspace (Hacknowledge, Rennes, France), I finally managed to make it work 🙂 It produces capture files that can be opened with Wireshark!

The following picture shows my beagleboard xM sniffing USB traffic between my Xbox 360 and a controller:

My beagleboard xM working as a USB sniffer.

Instructions are available in my git repository.

Serial port data glitch / corruption

Lately, I ran into a very bad issue running GIMX-serial in Linux.
The problem was, I was getting controller state corruption as soon as I was moving the mouse.

To investigate this issue, I just used usbmon to see the bytes sent to the usb to serial converter.

$ lsusb
/* The usb to serial converter is on bus 4. */
Bus 004 Device 001: ID 10c4:ea60 Cygnal Integrated Products, Inc. CP210x Composite Device

$ sudo cat /sys/kernel/debug/usb/usbmon/4u
/* serial port init */
f1c44200 682372285 S Co:2:005:0 s 41 00 0001 0000 0000 0
f1c44200 682372453 C Co:2:005:0 0 0
f1c67d80 682372497 S Bi:2:005:1 -115 256 <
f1c44200 682372506 S Ci:2:005:0 s c1 02 0000 0000 0002 2 <
f1c44200 682372774 C Ci:2:005:0 0 2 = 0700
f1c44200 682372815 S Ci:2:005:0 s c1 04 0000 0000 0002 2 <
f1c44200 682372945 C Ci:2:005:0 0 2 = 0008
f1c44200 682373010 S Ci:2:005:0 s c1 14 0000 0000 0010 16 <
f1c44200 682373188 C Ci:2:005:0 0 16 = 00000000 00000000 00000000 00000000
f1c44200 682373216 S Co:2:005:0 s 41 07 0303 0000 0000 0
f1c44200 682373312 C Co:2:005:0 0 0
/* 12 bytes = first controller data = sticks centered & buttons released */
f1c67e80 682375905 S Bo:2:005:1 -115 12 = ff7fff7f ff7fff7f 08000000
f1c67e80 682376695 C Bo:2:005:1 0 12 >
...
/* mouse movement starts */
f1c67e80 686006276 S Bo:2:005:1 -115 12 = ff7fff7f 059fff7f 08000000
f1c67e80 686006444 C Bo:2:005:1 0 12 >
...
/* This is the issue: 6+2+5=13 bytes are transferred (instead of 12) */
f1c67e80 686066821 S Bo:2:005:1 -115 6 = ff7fff7f d6c0
f1c67f00 686066840 S Bo:2:005:1 -115 2 = 0d0a
f1c67e80 686066937 C Bo:2:005:1 0 6 >
f1c67e80 686066943 S Bo:2:005:1 -115 5 = 51080000 00
f1c67f00 686066959 C Bo:2:005:1 0 2 >
f1c67e80 686067058 C Bo:2:005:1 0 5 >
...
/* Same issue again */
f1c67e80 686082954 S Bo:2:005:1 -115 4 = ff7fff7f
f1c67f00 686082976 S Bo:2:005:1 -115 2 = 0d0a
f1c67e80 686083063 C Bo:2:005:1 0 4 >
f1c67e80 686083068 S Bo:2:005:1 -115 7 = b5e45c08 000000
f1c67f00 686083086 C Bo:2:005:1 0 2 >
f1c67e80 686083182 C Bo:2:005:1 0 7 >
...
/* Same issue again */
f1c67e80 686123366 S Bo:2:005:1 -115 4 = ff7fff7f
f1c67f00 686123389 S Bo:2:005:1 -115 2 = 0d0a
f1c67e80 686123442 C Bo:2:005:1 0 4 >
f1c67e80 686123447 S Bo:2:005:1 -115 7 = b93c3b08 000000
f1c67f00 686123467 C Bo:2:005:1 0 2 >
f1c67e80 686123561 C Bo:2:005:1 0 7 >

I asked google about these specific 0x0a and 0x0d bytes, and found the explanation. The problem is due to a setting of the serial port that maps NL (newline = 0x0a) to CR-NL (carriage return=0x0d + newline = 0x0a).

Why didn’t I get the issue earlier? I recently had a problem with brltty taking control over my serial port. It appears brltty changed the default port settings. Future GIMX versions will disable output processing. A work around for current GIMX release v0.23 is to run the following command in a terminal:

$ stty -opost -F /dev/ttyUSB0

Another post about latency

My previous work on that subject

I already worked on measuring how much latency the sixaxis emulator is adding compared to a real sixaxis. I did that using a microphone, measuring the overall response time for a gunshot.

Assuming we have:
R=C+G
R=overall response time
C=controller latency
G=game latency

For the real sixaxis:
R1=C1+G
For the sixaxis emulator:
R2=C2+G

Assuming G is constant:
R2-R1=C2-C1

To estimate the controller latency difference, which is C2-C1, I just had to subtract the overall response time.
The result was about 15ms, which is not that bad compared to the overall response time (>100ms) and the human response time (>100ms).

A way to estimate the latency of the sixaxis emulator

The basic idea is to measure the time between a usb packet coming from the mouse (or any other usb controller) and a packet sent to the usb bt dongle.

For ex, the time between the usb packet for a left clic and the usb packet that sends the R1 button press (via the bluetooth dongle).

A great tool provided with the Linux kernel is usbmon, which allows to sniff the usb traffic. It’s possible to use it with wireshark (with root user rights), but it’s better to play in a terminal to automate extraction of valuable information.

The usbmon documentation is available there: link.

First of all, what the lsusb output says:

matlo@matlo-hcpc:~/hack/test$ lsusb
Bus 004 Device 002: ID 050d:0200 Belkin Components
Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 003 Device 009: ID 054c:0268 Sony Corp. Batoh Device
Bus 003 Device 008: ID 0a12:0001 Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode)
Bus 003 Device 006: ID 054c:0268 Sony Corp. Batoh Device
Bus 003 Device 005: ID 046d:c041 Logitech, Inc. G5 Laser Mouse
Bus 003 Device 003: ID 046d:c517 Logitech, Inc. LX710 Cordless Desktop Laser
Bus 003 Device 002: ID 058f:9254 Alcor Micro Corp. Hub
Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 002 Device 003: ID 046d:0809 Logitech, Inc. Webcam Pro 9000
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

What is useful there is the bus and device ids. The G5 mouse is device 5 on usb bus 3, and the bt dongle is device 8 on usb bus 3.

To start the capture:

matlo@matlo-hcpc:~/hack/test$ sudo cat /sys/kernel/debug/usb/usbmon/0u > test

Generate left clics into the sixaxis emulator, and stop the capture (ctrl+c).

Then, to display the mouse packets:

matlo@matlo-hcpc:~/hack/test$ cat test.txt | grep “3:005”

And for the bt dongle packets:

matlo@matlo-hcpc:~/hack/test$ cat test.txt | grep “3:008”

Both these commands may give a huge amount of data.

To only display packets that correspond to left clicks:

matlo@matlo-hcpc:~/hack/test$ cat test.txt | grep “3:005:1 0:1 10 = 01000000 00000000 0000”
f6747a40 967102843 C Ii:3:005:1 0:1 10 = 01000000 00000000 0000
f6747a40 968852805 C Ii:3:005:1 0:1 10 = 01000000 00000000 0000
f6747a40 970341772 C Ii:3:005:1 0:1 10 = 01000000 00000000 0000
f6747a40 971609742 C Ii:3:005:1 0:1 10 = 01000000 00000000 0000
f6747a40 972760716 C Ii:3:005:1 0:1 10 = 01000000 00000000 0000

To only display packets that correspond to R1 button presses:

matlo@matlo-hcpc:~/hack/test$ cat test.txt | grep “3:008:2 -115 58 = 2b203600 32004300 a1010000 08000080 80808000 00000000 00000000 0000ff00”
f32e2640 967105205 S Bo:3:008:2 -115 58 = 2b203600 32004300 a1010000 08000080 80808000 00000000 00000000 0000ff00
f32e2640 968861926 S Bo:3:008:2 -115 58 = 2b203600 32004300 a1010000 08000080 80808000 00000000 00000000 0000ff00
f32e2640 970345964 S Bo:3:008:2 -115 58 = 2b203600 32004300 a1010000 08000080 80808000 00000000 00000000 0000ff00
f3a904c0 971618231 S Bo:3:008:2 -115 58 = 2b203600 32004300 a1010000 08000080 80808000 00000000 00000000 0000ff00
f3a90ac0 972769407 S Bo:3:008:2 -115 58 = 2b203600 32004300 a1010000 08000080 80808000 00000000 00000000 0000ff00

What is to be extracted from this is the timestamp in microseconds, which is the second column.

matlo@matlo-hcpc:~/hack/test$ cat test.txt | grep “3:005:1 0:1 10 = 01000000 00000000 0000” | awk ‘{ print $2 }’
967102843
968852805
970341772
971609742
972760716

matlo@matlo-hcpc:~/hack/test$ cat test.txt | grep “3:008:2 -115 58 = 2b203600 32004300 a1010000 08000080 80808000 00000000 00000000 0000ff00” | awk ‘{ print $2}’
967105205
968861926
970345964
971618231
972769407

Then, it’s easy to copy-paste this data into a spreadsheet, compute the difference, compute the average, and the standard deviation.

For this example (with 5 more samples), it gives a 7.6ms average difference, with a 2.9ms standard deviation. The max difference is about 12ms.

It has to be reminded that the event polling period is 10ms (equal to the sixaxis report period), so that the maximum latency added by the event polling is 10ms, and the average is 5ms. Thus, the processing time is in average 7.6-5=2.6ms. It has to be noticed that I’m using a Linux kernel with realtime/low latency capabilities.

It’s also possible that there is some more latency added by the usb stack and the bt dongle, but it’s probably less than the 7.6ms processing time.

Conclusion:

– it’s probably not possible to have a lower response time with a sixaxis emulation (bt or usb)
– to lower the controller latency, the only potential way is to use a usb device to usb device controller (a custom usb link between the PC and the PS3), with a report period lower than 10ms

Thanks to that work I found a latency issue (about 50ms) that only impacts left and right mouse clics. The work-around -I’m not joking!- is to press the middle button after the mouse is plugged to the PC (see next post).