BlinkUp Protocol Reversing

Written 2018-04-06

Tags:Toymail Modem WiFi ElectricImp 

ElectricImp's BlinkUp protocol is an optical modulation protocol designed for low-speed data transfer using mobile phone displays or LEDs as transmitters. Since the transmitter runs on my phone, we can begin to reverse engineer the protocol strictly from the smali assembly extracted from the APK file.

To start, smali/com/electricimp/blinkup/BlinkupPacket.java's createFromIntent() shows there are currently four different packet types sent over BlinkUp, with (packet type numbers used):

For each packet type, the packet coder is told the packet size, contents, then told the packet is complete, at which point a 16 bit CRC is appended to the packet.

Packet Bitstream Structure

TypeBytesValue
Preamble80b10101010
Size1various
DataNvarious
Checksum2CRC-16

Packet Header

The packet header is quite simple, a preamble of 8 times the byte 85. In binary, this creates an alternating pattern of ones and zeros. Usually, in modem design, a preamble such as this allows the receiver to notice that data is incoming, and to synchronize its receive clock with the transmitted clock. Next, the header byte 42(0b00101010) comes. At this point, the CRC accumulator is zeroed out. Finally, the packet length is appended, updating the CRC.

Packet Payload

This varies with the packet type, but starts with a 1 byte indication of the packet type, followed by a UTF8 string ending with a NULL terminator. For packets without a string argument, the payload is simply the packet type byte followed directly by a NULL terminator. Multiple strings can be encoded in a simple integer-to-string dictionary by appending more packet type, string pairs. Perhaps packet type is not the best descriptor, perhaps string type?

CRC

Luckily, the implementation uses a CRC table. This means we can take the lazy path to fingerprinting it by searching github for the strings of numbers we find in the CRC table until we find an identical table in somebody else's source code. In this case, the CRC is a CRC-16, The poly is 0x8005 (x^16 + x^15 + x^2 + 1)

Encoding options

No protocol would be complete without a bunch of random cruft tacked on over time as the details of whatever mobile phone you used change.

Baud Rate

There are options for encoding the bitstream at both half and two thirds speeds, I suspect to deal with faster and faster mobile phone displays.

Binary vs Trinary Encoding

In the simple case, bits are encoded with a black screen meaning zero, and a white screen meaning one.

But another option is the ability to encode in tri-level flashes. In this case, bit 0 is presented as black followed by grey, and bit 1 is presented as black followed by white.