HCI UART sniffer

These last days I have developed a tool to sniff the UART of the Bluetooth module that is located inside a DS4 controller. Credit goes to Frank from eleccelerator for finding the UART, the test points, and the transmission parameters.

The following picture shows the test points:
hci uart test points
The blue wire is Gnd, and the others are Rx & Tx.

Knowing the UART transmission parameters (8N1, 3Mbps), it is possible to sniff the traffic using the Rx lines of two USB to UART adapters. CP2102-based adapters only support baudrates up to 2Mbps, but FT232RL-based adapters support up to 3Mbps.

The following picture shows two FT232RL adapters (one is a duemilanove arduino with the AVR chip removed) connected to a DS4:
ft232rl uarts

I wrote a tool that reads the data coming from the adapters. It translates a byte stream into a packet stream according to the HCI transport specification. It can either write the packets into a capture file that can be opened with wireshark, or write them to its standard output, so that it can feed the standard input of wireshark for a live display.

hci uart wireshark

The only drawback of this method compared to logic probes is that it can’t give precise timestamps, and it can’t guarantee that the packets are in the right order.

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