UPDATE: code posted below
Nike+iPod is a very interesting piece of hardware for all kinds of reasons, not the least of which is that it as actually useful. It works by wirelessly transmitting data from a sensor (that is stored in your shoe) to a receiver that is either externally connected to your iPod or to the receiver that is integrated into the bluetooth chip in the iPhone (3GS and 4 only). Some work has been done by others to try and figure out what data is sent by the sensor. This previous work can be seen here: 1, 2, and 3. As you can see, none of them really got far. They all failed to decode packet payload (which happens to be encrypted), they all failed to receive said data without using the stock receiver, and they all fail to understand the data. They only got as far as figuring out that there are 4 bits in there that are unique per sensor. Needless to say that this left me quite unsatisfied. I took a few days to figure out how it all works, and I am happy to say that I’ve decoded the entire packet payload successfully.
Curiously those 4 bytes that everyone used for identifying the sensor uniquely are in fact NOT unique. If a tag’s serial number is “4A123456VSX”, then from those 4 bytes you can only define SOME of the digits of this serial number, not all. In fact for that particular tag, with just those 4 bytes you’d only get “_A123456___”.
Hardware of the Nike+iPod sensor is quite interesting. I knew it used a nRF2402[Product page] to transmit the data. It’s a 2.4 GHz transmitter using GFSK modulation supporting 250Kbps or 1Mbps operation. It features a FIFO, and automatic packet assembly. That includes appending a “TO” address to the packet, sending a preamble byte, sending packet data, and sending a CRC as neeed. It is quite configurable. Channel is set in 1MHz increments, CRC choices are 0,8, or 16 bits. “TO” address can be anywhere from 0 to 5 bytes in 1 byte increments. This is a lot of options, and I had no time to guess what they chose. I opened to foot sensor and sniffed the configuration bytes sent to the nRF chip using a logic analizer. nRF2402 takes 2 configuration bytes on startup. Those bytes were: 0xE7 0x99. This tells us quite a lot. It tells us that the channel used is channel number 25, transmit power is set to maximum (1mW), data rate is 250 kbps, and 16-bit CRC is used. It also tells us some non-surprising things: ShockBurst is used, preamble is used. I also sniffed a lot of data frames here, and noticed that they all begin with the byte 0x0D. This may seem irrelevant now, but that will pass quickly. The packets are also 28 bytes long. Add in the 2 bytes of address and 2 bytes of CRC for the total RF payload of 32 bytes. One extra byte is sent for preamble. The TO address used in each message is “0xC2 0xBD”.
Recieving the data without the Nike+ receiver is difficult, which is why all other projects used said receiver. I had no desire to buy this receiver, and I am stubburn, so I looked for other ways. Nordic Semiconductor makes many other chips, and I happened to have one (nRF24L01+[Product Page]) around, on a breakout board from Sparkfun. This chip uses the same band, same modulation, same packet assembler/disassembler, and is by the same manufacturer – by all rules of logic it should be as good a receiver as anything. We hit the first snag as we read the datasheet and see that we need to use at least 3 address bytes to receive data. Well, this dashes our hopes, doesn’t it? Nah.
If you read carefully through all Nordic datasheets, you’ll see that the data length is never sent for these chips while using ShockBurst – both sides simply know it. Furthermore, the CRC is calculated over ADDR + DATA together, so realistically 2 bytes of address + 28 bytes of data is the same as 3 bytes of address + 27 bytes of data. This is where knowing that each packet begins with 0x0D helps. We tell our nRF24L01+ to receive on channel 25, expect 250 kbps, look for data length 27, 16-bit crc, and TO field of “0xC2 0xBD 0x0D”. Let’s turn it on and see what happens…. It works. We start getting packets: one a second. AWESOME! The sensor sends one packet every second as long as you walk or run, and for 10 seconds after you stop walking or running.
Data dumping is the next step for data analysis. I used a PIC16F688 I had lying around to drive the nRF chip and a Saleae Logic device to capture the data that I had the PIC pump out a bit-bannged SPI bus. Here‘s some data I’ve dumped. These are all, of course, missing the leading 0x0D byte since it’s used as address by the packet handler in my nRF24L01+. So where do we go from here? First off we can, as everyone else had, notice that bytes 0,1,2,3,4,5 are the same for all packets. In fact for all sensors first two bytes are “0x0D 0x01”. this means that bytes 2,3,4,5 are the four “uniquie bytes” that everyone figured were the device serial number. Byte 6 seems to almost always be 0xAx where x keeps incrementing. The rest of the packet looks like random garbage.
Read more: Nike+iPod reverse engineering (protocol too)