Vous êtes sur la page 1sur 12

SPOT Hacking

by Alexei Karpenko (natrium42)

Disclaimer
The information provided here might be completely wrong. Use at your own risk.
This site has no affiliation with SPOT, Axonn or Globalstar.

Introduction
SPOT is a nice little satellite transmitter using Globalstar Simplex data (uplink only).
The SPOT tracking service is available for a flat rate. If you were to use a STX2 module
directly (which SPOT is based on), each message would be at a cost. Unfortunately
SPOT suffers from two things:

GPS chipset is pretty poor


Only latitude and longitude are transmitted

By encoding altitude and misc sensor data though lat/lon and by using our own GPS
module we can remove these limitations.

Update (2011-12-04)
Travis Goodspeed has reverse engineered the SPOT Connect and published a great
article of how he accomplished it. What's neat about SPOT Connect is that you can send
positions and short messages via Bluetooth.

1.1 SPOT PCB

Name Pad Direction


Description
SEL0 TP22 Input
SEL0 high, SEL1 low - selects STX2 module
SEL1 TP23 Input
SEL0 low, SEL1 high - selects GPS module
TX TP20 Input
Serial data from microcontroller to selected module
RX TP24 Output Serial data from selected module to microcontroller
Request To Send (from microcontroller to STX2 when it's
RTS TP21 Input
selected)
CTS TP13 Output Clear To Send (from STX2 when it's selected to microcontroller)
VSAT TP25 Power
Connect to V3.3 to turn on STX2 module
V3.3 Power
3.3V from the onboard DC/DC converter
VBAT TP36 Power
Positive battery terminal (3V)
GND TP37 Ground System ground

1.2 Hacking SPOT to control the STX2-based satellite


transmitter directly

First desolder the MSP430F2252 microcontroller using a hot air rework station.
Alternatively you can cut the VCC lines of the microcontroller. We don't want the
microcontroller to interfere with our communications to the STX2.
Now connect VSAT to V3.3 so that the STX2 module receives 3.3V.
Connect SEL0 to V3.3 and SEL1 to GND. This is to select the STX2 module. The
original MSP430 microcontrollers uses those to switch between the STX2 and GPS on a
single UART port.
Connect RX to the RX of your microcontroller and connect the TX to the TX. Also
connect the RTS and CTS lines. Microcontroller should pull RTS low to start
transmission and wait for CTS to be pulled low by the STX2 within 20-30ms.
Use the VBAT battery terminal to supply 3V as provided by original battery. 3.3V also
seems to work without problems. Current seems to be 0.1 mA when module is inactive
and 150 mA for a second or so when transmitting.

2.1 STX2 Protocol


2.1.1 STX2 Message Format
STX2 messages have the same format in either direction:
Preamble
(1 byte)
Preamble
Length
Cmd
Data
CRC

Length Cmd Data


CRC
(1 byte) (1 byte) (variable) (2 bytes)
Fixed pattern 0xAA
Total number of bytes in the serial packet including the preamble and CRC
Command type
Responses to commands carry the same command type as the command that
initiated the answer
Data associated with the command or answer
16 Bit CRC

2.1.2 Available STX2 Commands


Cmd
0x00
0x01
0x03
0x04
0x05

0x06

0x07
0x10
0x11
0xFF

Description
Transmit following data bytes via the air interface.
If number of data bytes > 9, then message is split into multiple messages.
Up to 144 data bytes can be sent via this command.
(Although we must only send messages in SPOT format in our case, see below.)
Request modem's unit ID.
Response contains four data bytes (MSB first) representing unit ID.
Request modem to abort current transmission.
Checks if there is a pending transmission.
Response contains one data byte:
0x00 (no pending transmissions)
0xXX (XX remaining transmission attempts)
Request firmware and interface ID.
Response contains two data bytes: major revision and minor revision
Setup message.
Four deprecated data bytes (don't care)
One byte to specify the RF channel: 00 (A), 01 (B), 02 (C), 03 (D)
One byte to define the number of tries (1-20)
One byte to define the minimum interval between tries (seconds/5)
One byte to define the maximum interval between tries (seconds/5)
One byte to define the transmit power level: 0 (20dBm fixed)
Query setup.
Returns settings specified by above command.
SET/CLR GPS FLAG
OEM command used to set/clear the GPS flag in the on-air message header.
One data byte (0 or 1)
Deprecated, but seems to be sent by SPOT on cold start.
GET GPS FLAG STATUS
Response contains one byte of data representing GPS FLAG.
This value is only used for an answer and corresponds to a negative
acknowledgement.

2.1.3 SPOT Message Format


I have captured three message types: 0x01 (OK), 0x04 (HELP), 0x40 (TRACK). There's
also the SOS message type, which I didn't capture since it should never be sent anyway.
Example:
AA 0E 00 00 3D DD 85 C6 C5 5D 01 00 EC 78
AA
0E
00
3D DD 85
C6 C5 5D
01
EC 78
Response:

preamble
total length of message (14 bytes)
command: transmit message
encoded latitude (MSB - LSB)
encoded longitude (MSB - LSB)
message type: 0x01 (OK), 0x04 (HELP), 0x40 (TRACK)
CRC16

AA 05 00 D9 C4
AA
05
00
D9 C4

preamble
total length of message
acknowledge transmit command
CRC16

2.1.4 Latitude Format


DEGREES_PER_COUNT_LAT = 90.0 / 2^23
decimal_latitude = encoded_latitude * DEGREES_PER_COUNT_LAT
If result is greater than or equal to 90 degrees, 180 must be subtracted.
Example:
encoded_latitude = 0x3DDD85 = 4054405
decimal_latitude = 4054405 * 90.0 / 2^23 = 43.4990
Result is less than 90, so this is correct form.

2.1.4 Longitude Format


DEGREES_PER_COUNT_LONG = 180.0 / 2^23
decimal_longitude = encode_longitude * DEGREES_PER_COUNT_LONG
If result is greater than or equal to 180 degrees, 360 must be subtracted.
Example:
encoded_longitude = 0xC6C55D = 13026653
decimal_longitude = 13026653 * 180.0 / 2^23 = 279.5216
Result is greater than 180, so subtract 360 to get:
decimal_longitude = -80.4784

2.1.5 Calculating CRC16


/
**********************************************************************
*********
* COMPONENT NAME:
* crc16
*
* DESCRIPTION:
* This function computes a 16 bit CRC value for an array of bytes. The
value
* that is returned by this function needs to be inverted before it
gets placed
* into the packet. The CRC goes at the end of the packet, low byte
first.
* For example:
*
* crc = ~crc16(0xFFFF, msgbuf, length);
*
* msgbuf[length] = (uint8_t)(crc & 0xFF);
* msgbuf[length + 1] = (uint8_t)(crc >> 8);
*
* When calling this function to check the validity of a packet
received from

* the STX2, the caller should expect the value 0xF0B8 (#defined as
CRC_OK) to
* be returned if the packet is valid.
*
* INPUTS:
* crc - the value to start computing the CRC with. This allows for
chaining
* together of CRC values computed for multiple arrays of data. The
* initial value should be FFFFh (#defined as CRC_INIT).
* ptr - the pointer to the array of bytes to compute the CRC for
* length - the length of the data array
*
* OUTPUTS:
* returns - the computed 16 bit crc value
**********************************************************************
*********/
uint16_t crc16(uint16_t crc, uint8_t *ptr, int length)
{
auto uint16_t i;
while(length--)
{
crc = crc ^ (uint16_t) *ptr++;
for(i=0;i<8;i++)
{
if(crc & 0x0001)
crc = (crc >> 1) ^ 0x8408;
else
crc >>= 1;
}
}
return crc;
}

2.2 Serial Port


STX2 serial port runs at 9600 baud with CTS and RTS flow control. Microcontroller
should lower RTS and wait for CTS to be lowered by STX2. If this does not occur
within 20-30ms, STX2 is busy and cannot accept any commands.
Once the microcontroller has transmitted the packet, it should return RTS back to high
and STX2 will consequently also return CTS back to high.

3.1 Pictures

3.2 Schematic
This schematic was determined by many hours of probing, tracing and scoping.

3.3 Sending custom data


To transmit custom data like altitude or sensor data, we need a way to encode it as
Lat/Lon and then decode it back to the original data. This is because we do not have
access to raw message on the findmespot site, but only to position. We have 6 bytes to
work with (3 for Lat and 3 for Lon). Through tests, it was determined how the
findmespot servers round off Lat and Lon fields and it turns out that 4 lower bits are
wasted on each field, if we want to ensure that we get the upper bits correctly for every
possible combination. The trick is to set the lower 4 bits to 0111, then the upper 20 bits
are not mangled. This means that we can transfer custom 20 bits with the Lat field and
20 custom bits with the Lon field, for a total of 40 bits (5 bytes). See spot-encode.c and
spot-decode.c below for sample code.

3.4 Sample code


stx2.h - STX2 functions for AVR
stx2.c - STX2 functions for AVR
spot.php - Code to grab XML with positions from SPOT page
spot-encode.c - Code to encode 5 bytes and transmit them to SPOT
spot-decode.c, Makefile.spot-decode - Utility to decode Lat/Lon to 5 original bytes that
were sent

3.5 Captured data


"0:" is data to MCU
"1:" is data from MCU
(1) Initialization
0: $PNMRX600,0,NemeriX NS1030A, SW Release Version 4.0.14_PROD,
Welcome On Board! *01
0:
$GPGGA,095133.000,0000.0000,S,00000.0000,W,0,00,00.0,0.0,M,0.0,M,,*5F
1: AA 0E 06 00 00 00 00 00 03 3C 78 00 32 74
0: AA 05 06 EF A1
0: $PNMRX600,0,NemeriX NS1030A, SW Release Version 4.0.14_PROD,
Welcome On Board! *01
0:
$GPGGA,095144.000,0000.0000,S,00000.0000,W,0,00,00.0,0.0,M,0.0,M,,*5F
0: $GPGSA,A,1,,,,,,,,,,,,,0.0,0.0,0.0*30
1: $PNMRX103,GGA,1,GLL,0,GSA,1,GSV,0,RMC,0,VTG,0,ZDA,0*10
0:
$GPGGA,095144.000,0000.0000,S,00000.0000,W,0,00,00.0,0.0,M,0.0,M,,*5F
0: $GPGSA,A,1,,,,,,,,,,,,,0.0,0.0,0.0*30
0:
$GPGGA,095144.000,0000.0000,S,00000.0000,W,0,00,00.0,0.0,M,0.0,M,,*5F
0: $GPGSA,A,1,,,,,,,,,,,,,0.0,0.0,0.0*30
0:
$GPGGA,095144.000,0000.0000,S,00000.0000,W,0,00,00.0,0.0,M,0.0,M,,*5F
0: $GPGSA,A,1,,,,,,,,,,,,,0.0,0.0,0.0*30
...
This contains setup message:
AA 0E 06 00 00 00 00 00 03 3C 78 00 32 74
AA
0E
06
00 00 00 00
00
03
3C
78
00
32 74

preamble
total length of message (14 bytes)
command: setup message
deprecated
RF channel: A
number of tries: 3
minimum interval between tries: 5 minutes
maximum interval between tries: 10 minutes
power level: 20dBm
CRC16

Response:
AA 05 06 EF A1
AA
05
06
EF A1

preamble
total length of message
acknowledge setup command
CRC16

(2) OK message #1 (after cold start)


0: $GPGGA,033032.172,4329.9448,N,08028.7018,W,1,05,05.0,279.2,M,36.8,M,,*54
0: $GPGSA,A,3,03,20,23,31,32,,,,,,,,14.6,5.0,13.8*3D
0: $GPGGA,033033.172,4329.9448,N,08028.7018,W,1,05,05.0,279.0,M,36.8,M,,*57
0: $GPGSA,A,3,03,20,23,31,32,,,,,,,,14.6,5.0,13.8*3D
0: $GPGGA,033034.172,4329.9433,N,08028.7011,W,1,06,01.6,286.5,M,36.8,M,,*51

1:
0:
1:
0:
1:
0:

AA
AA
AA
AA
AA
AA

0E
05
06
05
0E
05

06
06
10
10
00
00

00
EF
01
58
00
D9

00 00 00 00 03 3C 78 00 32 74
A1
8C D0
D4
3D DD 85 C6 C5 5D 01 00 EC 78
C4

Received message:
Latitude: 43.4990
Longitude: -80.4784
Time: 03/04/2009 03:31:09 (GMT)
(3) OK message #2
0: $GPGGA,041135.846,4329.9453,N,08028.7036,W,1,05,02.0,302.6,M,36.8,M,,*51
0: $GPGSA,A,3,06,16,20,23,31,,,,,,,,2.9,2.0,2.2*3B
0: $GPGGA,041136.845,4329.9449,N,08028.7036,W,1,05,02.0,302.6,M,36.8,M,,*5A
0: $GPGSA,A,3,06,16,20,23,31,,,,,,,,2.9,2.0,2.2*3B
0: $GPGGA,041137.845,4329.9445,N,08028.7034,W,1,06,01.6,302.6,M,36.8,M,,*53
1: AA 0E 06 00 00 00 00 00 03 3C 78 00 32 74
0: AA 05 06 EF A1
1: AA 0E 00 00 3D DD 88 C6 C5 5B 01 00 EA 9B
0: AA 05 00 D9 C4
Received message:
Latitude: 43.4991
Longitude: -80.4784
Time: 03/04/2009 04:12:12 (GMT)
(4) HELP message
0: $GPGGA,035111.934,4329.9459,N,08028.7055,W,1,05,02.1,285.0,M,36.8,M,,*56
0: $GPGSA,A,3,03,06,16,23,31,,,,,,,,4.3,2.1,3.7*33
0: $GPGGA,035112.934,4329.9458,N,08028.7054,W,1,05,02.1,285.0,M,36.8,M,,*55
0: $GPGSA,A,3,03,06,16,23,31,,,,,,,,4.3,2.1,3.7*33
0: $GPGGA,035113.933,4329.9458,N,08028.7055,W,1,05,02.1,285.0,M,36.8,M,,*52
1: AA 0E 06 00 00 00 00 00 01 3C 78 00 44 4D
0: AA 05 06 EF A1
1: AA 0E 00 00 3D DD 89 C6 C5 5A 04 00 A5 BB
0: AA 05 00 D9 C4
Received message:
Latitude: 43.4991
Longitude: -80.4784
Time: 03/04/2009 03:51:49 (GMT)
break, ~5 minutes
0: $PNMRX600,0,NemeriX NS1030A, SW Release Version 4.0.14_PROD,
Welcome On Board! *01
0: $GPGGA,035523.999,4329.9458,N,08028.7055,W,0,00,00.0,285.0,M,36.8,M,,*52
0: $GPGSA,A,1,,,,,,,,,,,,,0.0,0.0,0.0*30
1: $PNMRX103,GGA,1,GLL,0,GSA,1,GSV,0,RMC,0,VTG,0,ZDA,0*10
0: $GPGGA,035523.999,4329.9458,N,08028.7055,W,0,00,00.0,285.0,M,36.8,M,,*52
0: $GPGSA,A,1,,,,,,,,,,,,,0.0,0.0,0.0*30

0: $GPGGA,035523.999,4329.9458,N,08028.7055,W,0,00,00.0,285.0,M,36.8,M,,*52
0: $GPGSA,A,1,,,,,,,,,,,,,0.0,0.0,0.0*30
...
0: $GPGGA,035546.934,4329.9414,N,08028.7028,W,1,05,02.2,292.8,M,36.8,M,,*5E
0: $GPGSA,A,3,03,06,16,23,31,,,,,,,,4.5,2.2,3.9*38
0: $GPGGA,035547.933,4329.9414,N,08028.7029,W,1,05,02.2,292.9,M,36.8,M,,*58
1: AA 0E 00 00 3D DD 83 C6 C5 5C 04 00 72 44
0: AA 05 00 D9 C4
Received message:
Latitude: 43.4990
Longitude: -80.4784
Time: 03/04/2009 03:56:22 (GMT)
(5) TRACK message
0: $GPGGA,035921.905,4329.9279,N,08028.6731,W,1,04,03.5,314.6,M,36.8,M,,*54
0: $GPGSA,A,3,03,06,20,31,,,,,,,,,13.3,3.5,12.9*3A
0: $GPGGA,035922.905,4329.9280,N,08028.6730,W,1,04,03.5,314.4,M,36.8,M,,*52
0: $GPGSA,A,3,03,06,20,31,,,,,,,,,13.3,3.5,12.9*3A
0: $GPGGA,035923.904,4329.9301,N,08028.6749,W,1,05,01.7,324.9,M,36.8,M,,*5B
1: AA 0E 00 00 3D DD 71 C6 C5 72 40 00 A1 BE
0: AA 05 00 D9 C4
Received message:
Latitude: 43.4988
Longitude: -80.4779
Time: 03/04/2009 3:59:59 (GMT)
break, ~8 minutes
0: $PNMRX600,0,NemeriX NS1030A, SW Release Version 4.0.14_PROD,
Welcome On Board! *01
0: $GPGGA,040838.999,4329.9301,N,08028.6749,W,0,00,00.0,324.9,M,36.8,M,,*54
0: $GPGSA,A,1,,,,,,,,,,,,,0.0,0.0,0.0*30
1: $PNMRX103,GGA,1,GLL,0,GSA,1,GSV,0,RMC,0,VTG,0,ZDA,0*10
0: $GPGGA,040838.999,4329.9301,N,08028.6749,W,0,00,00.0,324.9,M,36.8,M,,*54
0: $GPGSA,A,1,,,,,,,,,,,,,0.0,0.0,0.0*30
0: $GPGGA,040838.999,4329.9301,N,08028.6749,W,0,00,00.0,324.9,M,36.8,M,,*54
0: $GPGSA,A,1,,,,,,,,,,,,,0.0,0.0,0.0*30
...
0: $GPGGA,040907.899,4329.9394,N,08028.7013,W,1,04,06.1,304.3,M,36.8,M,,*57
0: $GPGSA,A,3,03,06,16,31,,,,,,,,,9.6,6.1,7.4*39
0: $GPGGA,040908.899,4329.9395,N,08028.7013,W,1,04,06.1,304.3,M,36.8,M,,*59
0: $GPGSA,A,3,03,06,16,31,,,,,,,,,9.6,6.1,7.4*39
0: $GPGGA,040909.899,4329.9396,N,08028.7014,W,1,05,02.5,304.2,M,36.8,M,,*5C
1: AA 0E 00 00 3D DD 80 C6 C5 5D 40 00 D5 33
0: AA 05 00 D9 C4
Received message:

Message lost

Vous aimerez peut-être aussi