3 #GoodFET SPI Flash Client
11 from GoodFETNRF import GoodFETNRF;
12 from intelhex import IntelHex;
15 regnames=["CONFIG","EN_AA","EN_RXADDR","SETUP_AW","SETUP_RET",
16 "RF_CH","RF_SETUP","STATUS","OBSERVE_TX","RPD",
17 "RX_ADDR_P0","RX_ADDR_P1","RX_ADDR_P2","RX_ADDR_P3","RX_ADDR_P4","RX_ADDR_P5",
19 "RX_PW_P0","RX_PW_P1","RX_PW_P2","RX_PW_P3","RX_PW_P4","RX_PW_P5",
21 "?","?","?","DYNPD","FEATURE","AGC_CONFIG","?","?",
22 "?","?","?","?","?","?","?","?"];
24 def printpacket(packet):
29 if i>client.packetlen: break;
30 s="%s %02x" % (s,ord(foo));
36 def printmspacket(packet,offset=1):
37 """Decodes a Microsoft keyboard packet and maintains the typed strings."""
38 global mskbstring, oldseq;
39 keyword=client.RF_getsmac();
40 #print "keyword=%010x" % key;
43 for foo in range(0,5):
44 key.append(keyword&0xFF);
46 #print "Keybyte %02x" % key[foo];
52 ct.append(ord(foo)^key[(i+offset)%5]);
53 s="%s %02x" % (s,ord(foo)^key[(i+offset)%5]);
56 s="%s %02x" % (s,ord(foo));
58 #Uncomment this to print the raw packet, kinda noisy.
63 if ct[0]==0x0a and ct[1]==0x78 and seq!=oldseq:
65 #TODO replace this with a dictionary, and support modifiers.
67 #Key up event, not worth logging.
69 elif ct[9]>=4 and ct[9]<0x1E:
70 letter=ct[9]+ord('A')-4;
71 elif ct[9]>=0x1E and ct[9]<0x27:
72 letter=ct[9]+ord('1')-0x1E;
91 print "Unknown character 0x%02x." % ct[9];
94 mskbstring="%s%c" % (mskbstring,letter);
95 print "# %s" % mskbstring
97 print "Encoding %s" % client.RF_getenc();
98 print "Freq %10i MHz" % (client.RF_getfreq()/10**6);
99 print "Rate %10i kbps" % (client.RF_getrate()/1000);
100 print "PacketLen %02i bytes" % client.RF_getpacketlen();
101 #print "MacLen %2i bytes" % client.RF_getmaclen();
102 print "SMAC 0x%010x" % client.RF_getsmac();
103 print "TMAC 0x%010x" % client.RF_gettmac();
106 if(len(sys.argv)==1):
107 print "Usage: %s verb [objects]\n" % sys.argv[0];
108 print "%s info" % sys.argv[0];
109 print "%s test" % sys.argv[0];
110 print "%s regs" % sys.argv[0];
111 print "%s regbits" % sys.argv[0];
112 print "%s pyregs" % sys.argv[0];
114 print "%s tune aa|55,mac,r5,r6\n\tTunes to a configuration." % sys.argv[0];
115 print "%s sniff\n\tSniffs packets by current config." % sys.argv[0];
116 print "%s sniffob\n\tSniffs OpenBeacon traffic." % sys.argv[0];
117 print "%s snifftp\n\tSniffs Turning Point Clicker traffic." % sys.argv[0];
118 print "%s sniffsf\n\tSniffs SparkFun Dongle traffic." % sys.argv[0];
119 print "%s sniffmskb\n\tSniffs Microsoft Keyboard traffic." % sys.argv[0];
121 print "%s sniffmacs \n\tSniffs for MAC addresses on the present channel." % sys.argv[0];
122 print "%s sniffprom [0xaa|0x55]\n\tSniffs promiscuously for a preamble of 0xAA or 0x55" % sys.argv[0];
123 print "%s autotune\n\tSearches for a valid destination address." % sys.argv[0];
125 print "%s carrier [freq]\n\tHolds a carrier on [freq] Hz." % sys.argv[0];
128 #Initialize FET and set baud rate
134 if(sys.argv[1]=="info"):
137 if(sys.argv[1]=="test"):
138 print "Old registers:"
141 # Set PWR_UP=1 and PRIM_RX=0 in CONFIG.
143 #Delay of 1.5ms by round-trip.
148 for foo in [250*10**3,
151 client.RF_setrate(foo);
152 if(client.RF_getrate()!=foo):
153 print "ERROR Rate %i not supported. Got %i instead." % (foo,
154 client.RF_getrate());
157 client.poke(0x0A,0xDEADBEEF,5);
158 #print "SMAC set to %010x" % client.RF_getsmac();
159 if client.RF_getsmac()!=0xdeadbeef:
160 print "ERROR: Failed to set MAC address.";
161 print "Final registers:"
164 if(sys.argv[1]=="carrier"):
166 client.RF_setfreq(eval(sys.argv[2]));
169 print "\nHolding a carrier wave.";
173 if(sys.argv[1]=="tune"):
175 client.tune(sys.argv[2]);
177 print "Specify a tuning, such as 'aa,c78c65805e,14,09'";
178 if(sys.argv[1]=="regs"):
179 for r in range(0,0x20):
180 print "r[0x%02x]=0x%010x //%16s " % (r,client.peek(r),regnames[r]);
181 if(sys.argv[1]=="pyregs"):
182 for r in range(0,0x20):
183 print "client.set(0x%02x,0x%010x); #%16s " % (r,client.peek(r),regnames[r]);
185 if(sys.argv[1]=="peek"):
188 start=int(sys.argv[2],16);
191 stop=int(sys.argv[3],16);
192 print "Peeking from %02x to %02x." % (start,stop);
194 print "%02x: %010x" % (start,client.peek(start));
196 if(sys.argv[1]=="poke"):
200 start=int(sys.argv[2],16);
202 val=int(sys.argv[3],16);
203 print "Poking %02x to become %010x." % (start,val);
205 client.poke(start,val);
206 print "Poked to %04x" % client.peek(start);
208 if(sys.argv[1]=="sniffob"):
209 #Reversal of transmitter code from nRF_CMD.c of OpenBeacon
210 #TODO remove all poke() calls.
212 client.poke(0x00,0x00); #Stop nRF
213 client.poke(0x01,0x00); #Disable Shockburst
214 client.poke(0x02,0x01); #Set RX Pipe 0
216 client.RF_setfreq(2481 * 10**6);
217 client.poke(0x06,0x09); #2MBps, -18dBm in RF_SETUP
218 client.poke(0x07,0x78); #Reset status register
220 #OpenBeacon defines these in little endian as follows.
221 client.RF_setmaclen(5); # SETUP_AW for 5-byte addresses.
222 #0x01, 0x02, 0x03, 0x02, 0x01
223 client.RF_setsmac(0x0102030201);
224 #'O', 'C', 'A', 'E', 'B'
225 client.RF_settmac(0x424541434F);
227 #Set packet length of 16.
228 client.RF_setpacketlen(16);
230 #Power radio, prime for RX, one-byte checksum.
231 client.poke(0x00,0x70|0x03|0x08); #0x08 for one byte, 0x04 for two.
233 print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
234 client.RF_getfreq()/10**6);
235 #Now we're ready to get packets.
240 packet=client.RF_rxpacket();
244 if(sys.argv[1]=="regbits"):
245 print "Scanning registers to determine which bits are valid."
246 regbits=range(0,0x30);
247 for r in range(0,0x30):
249 #Which bits can be set?
252 #Which bits can be clear?
254 zeroes=client.peek(r);
255 regbits[r]=(ones & (~zeroes));
256 for r in range(0,0x30):
258 print "r[0x%02x] masked %02x // %s" % (r,regbits[r], regnames[r]);
259 if(sys.argv[1]=="sniffprom"):
260 #Reversal of transmitter code from nRF_CMD.c of OpenBeacon
261 #TODO remove all poke() calls.
263 client.poke(0x00,0x00); #Stop nRF
264 client.poke(0x01,0x00); #Disable Shockburst
265 client.poke(0x02,0x01); #Set RX Pipe 0
267 #client.RF_setfreq(2481 * 10**6);
268 #client.poke(0x06,0x09); #2MBps, -18dBm in RF_SETUP
269 client.poke(0x07,0x78); #Reset status register
271 #OpenBeacon defines these in little endian as follows.
272 client.RF_setmaclen(2); # SETUP_AW for shortest
274 #It's better to have a known fragment, when one is available.
275 #client.RF_setsmac(0x00AA);
276 #client.RF_setsmac(0x0055);
278 #Should end in 55 or AA depending upon the packet.
281 tail=int(sys.argv[2],16);
283 print "Please specify a tail of 0xAA or 0x55.";
285 client.RF_setsmac(tail);
288 client.RF_setpacketlen(32);
290 #Power radio, prime for RX, no checksum
291 client.poke(0x00,0x70|0x03); #0x08 for checksum, 0x04 for two.
293 print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
294 client.RF_getfreq()/10**6);
295 #Now we're ready to get packets.
300 packet=client.RF_rxpacket();
305 """This guesses addresses by searching through packets."""
309 #Limits on search space, because you usually know what you're looking for.
313 startch=0; #Useful for forcing an early match.
314 def init(self,goodfet,
315 rate=True,chan=True,sync=True):
316 """Initializes a link to the GoodFET for autotuning."""
322 client.poke(0x00,0x00); #Stop nRF
323 client.poke(0x01,0x00); #Disable Shockburst
324 client.poke(0x02,0x01); #Set RX Pipe 0
327 client.poke(0x1C,0x00);
328 client.poke(0x1D,0x00);
330 client.RF_setmaclen(2); # SETUP_AW for shortest
333 #client.RF_setsmac(0x00AA);
334 #client.RF_setsmac(0x0055);
336 client.poke(0x00,0x70|0x03); #prime radio.
339 def packetaddr(self,packet,justmac=False):
340 """Returns a loaded packet address, including channel and rate."""
342 sync=self.client.RF_getsmac()&0xFF;
347 mac="%s%02x" % (mac,ord(packet[i]));
350 ch=self.client.peek(0x05);
351 rate=self.client.peek(0x06);
352 return "%02x,%s,%02x,%02x" % (
354 def validmac(self,packet):
355 sync=self.client.RF_getsmac()&0xFF;
356 mac=self.packetaddr(packet,justmac=True);
357 if (ord(packet[0])&0x80)^(sync&0x80):
358 #print "%02x%02x invalid entry." % (sync,ord(packet[0]));
359 #This is a special kind of failure. Freq is probably right, but MAC is wrong.
361 if mac=='5555555555' or mac=='aaaaaaaaaa' or mac=='0000000000':
365 def handle(self,packet):
366 """Handles a packet."""
367 #printpacket(packet);
369 if not self.validmac(packet):
370 #print "Dropped packet from %s" % self.packetaddr(packet,justmac=True);
371 #printpacket(packet);
374 addr=self.packetaddr(packet);
376 #Increment the address count.
379 count=self.addresses[addr];
382 self.addresses[addr]=count+1;
383 rate=count*1.0/len(self.addresses);
384 if self.addresses[addr]>1 or rate>0.01:
385 print "'%s' looks valid\t%i\t%0.5f" % (
389 def selftune(self,threshold=2,forever=False,
391 """Tunes to the first strong signal.
392 It's important that this not get triggered by false positives."""
396 start=time.mktime(time.localtime());
398 while (time.mktime(time.localtime())-start) < delay:
401 packet=client.RF_rxpacket();
402 addr=guesser.handle(packet);
404 count=self.addresses[addr];
407 if count>threshold and forever==False:
414 """Tunes to another channel or preamble looking for the next packet."""
415 count=self.tunecount;
416 self.tunecount=count+1;
418 #Swap the SYNC value most often.
423 self.client.RF_setsmac(sync);
430 #This swaps between 1Mbps and 2Mbps.
431 #TODO add support for 256kbps, if anyone uses it.
434 #print "Setting rate to 0x%02x" % rate;
437 self.client.poke(0x06,rate);
441 self.client.poke(0x05,
442 (count+self.startch)&0x7f);
443 print "Tuned to %i MHz" % (
444 self.client.RF_getfreq()
446 #Grab two packets to clear buffers.
447 #Should retune only after a few packets to reduce this delay.
448 packet=client.RF_rxpacket();
449 packet=client.RF_rxpacket();
453 if(sys.argv[1]=="autotune"):
454 #Reversal of transmitter code from nRF_CMD.c of OpenBeacon
455 #TODO remove all poke() calls.
457 guesser.init(client,rate=True,sync=True,chan=True);
460 #client.RF_setfreq(2481 * 10**6);
461 client.poke(0x06,0x09); #2MBps, -18dBm in RF_SETUP
462 client.poke(0x07,0x78); #Reset status register
464 #This is determined by the MAC, which we don't yet know.
467 client.RF_setpacketlen(32);
469 #Power radio, prime for RX, no checksum
470 client.poke(0x00,0x70|0x03); #0x08 for checksum, 0x04 for two.
472 print "Autotuning on %i MHz" % (
473 client.RF_getfreq()/10**6);
474 print "sync,mac,r5,r6";
475 #Now we're ready to get packets.
476 guesser.selftune(threshold=2,
479 if(sys.argv[1]=="sniffmacs"):
480 #Reversal of transmitter code from nRF_CMD.c of OpenBeacon
481 #TODO remove all poke() calls.
483 guesser.init(client,rate=False,sync=True,chan=False);
486 client.RF_setpacketlen(32);
488 #Power radio, prime for RX, no checksum
489 client.poke(0x00,0x70|0x03); #0x08 for checksum, 0x04 for two.
491 print "Holding autotune on %i MHz" % (
492 client.RF_getfreq()/10**6);
493 print "sync,mac,r5,r6";
494 #Now we're ready to get packets.
495 guesser.selftune(threshold=2,
498 if(sys.argv[1]=="sniffmskb"):
500 #TODO remove all poke() calls.
502 client.poke(0x00,0x00); #Stop nRF
503 client.poke(0x01,0x00); #Disable Shockburst
504 client.poke(0x02,0x01); #Set RX Pipe 0
506 client.poke(0x06,0x09); #2MBps, -18dBm in RF_SETUP
507 client.poke(0x07,0x78); #Reset status register
509 #This is the address of a specific keyboard.
510 #Other keyboards will be different.
512 client.RF_setmaclen(5);
514 #Known pairs. The channel and the low address bytes must match.
515 #client.RF_setfreq((2400+0x13) * 10**6);
516 #client.RF_setsmac(0xc00a3598cd);
518 #client.RF_setfreq((2400+0x15) * 10**6);
519 #client.RF_setsmac(0xc10446facd);
521 #Mac packet length, illegally 0-length address field.
522 client.RF_setpacketlen(16);
526 client.tune(sys.argv[2]);
529 print "Searching for a keyboard.";
532 guesser.init(client, rate=False, sync=True, chan=True);
533 guesser.selftune(threshold=4,forever=False,
536 client.poke(0x00,0x00); #Stop nRF
537 client.poke(0x01,0x00); #Disable Shockburst
538 client.poke(0x02,0x01); #Set RX Pipe 0
539 client.RF_setmaclen(5);
541 #Finally, dynamic payload lengths need to be enabled.
542 #client.poke(0x01,0x01);
543 client.poke(0x1C,0x01);
544 client.poke(0x1D,0x06);
546 client.poke(0x00,0x70|0x03); #prime radio.
547 print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
548 client.RF_getfreq()/10**6);
549 #Now we're ready to get packets.
554 packet=client.RF_rxpacket();
556 printmspacket(packet);
559 if(sys.argv[1]=="sniffant"):
560 #Prototyped on Garmin device.
561 #Channel hopping is pretty damned fast, hard to follow.
562 #This doesn't really work yet, still experimenting.
564 #Might be more effective to sniff knowing the MFG ID and Dev. ID,
565 #as these predict a lot of the MAC address.
567 client.poke(0x00,0x00); #Stop nRF
568 client.poke(0x01,0x00); #Disable Shockburst
569 client.poke(0x02,0x01); #Set RX Pipe 0
571 client.poke(0x05,57); #broadcast-only channel
572 client.poke(0x06,0x00); #1MBps
573 client.poke(0x07,0x78); #Reset status register
575 #Is this appropriate? Might be 3.
576 client.RF_setmaclen(5);
579 #Mac packet length, illegally 0-length address field.
580 client.RF_setpacketlen(16);
583 client.tune(sys.argv[2]);
586 print "Searching for ANT+.";
589 guesser.init(client, rate=False, sync=True, chan=True);
590 guesser.selftune(threshold=2,forever=False,
593 client.poke(0x00,0x00); #Stop nRF
594 client.poke(0x01,0x00); #Disable Shockburst
595 client.poke(0x02,0x01); #Set RX Pipe 0
596 client.RF_setmaclen(5);
599 client.poke(0x00,0x70|0x03); #prime radio.
600 print "Dumping ANT as %010x on %i MHz" % (client.RF_getsmac(),
601 client.RF_getfreq()/10**6);
602 #Now we're ready to get packets.
607 packet=client.RF_rxpacket();
615 if(sys.argv[1]=="sniffsf"):
616 #Reversal of transmitter code from nRF_CMD.c of OpenBeacon
617 #TODO remove all poke() calls.
619 client.poke(0x00,0x00); #Stop nRF
620 client.poke(0x01,0x00); #Disable Shockburst
621 client.poke(0x02,0x01); #Set RX Pipe 0
623 client.RF_setfreq(2402 * 10**6);
624 client.poke(0x06,0x07); #1Mbps
625 client.poke(0x07,0x78); #Reset status register
627 #OpenBeacon defines these in little endian as follows.
628 client.RF_setmaclen(5); # SETUP_AW for 5-byte addresses.
629 client.RF_setsmac(0xe7e7e7e7e7);
630 client.RF_settmac(0xe7e7e7e7e7);
632 #Set packet length of 16.
633 client.RF_setpacketlen(4);
635 #Power radio, prime for RX, one-byte checksum.
636 client.poke(0x00,0x70|0x03|0x08); #0x08 for one byte, 0x04 for two.
638 print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
639 client.RF_getfreq()/10**6);
640 #Now we're ready to get packets.
645 packet=client.RF_rxpacket();
649 if(sys.argv[1]=="snifftp"):
650 client.poke(0x00,0x00); #Stop nRF
651 client.poke(0x01,0x00); #Disable Shockburst
652 client.poke(0x02,0x01); #Set RX Pipe 0
655 client.poke(0x1C,0x00);
656 client.poke(0x1D,0x00);
658 client.RF_setfreq((2400+0x29) * 10**6);
659 client.poke(0x06,0x00); #1Mbps
660 client.poke(0x07,0x78); #Reset status register
662 client.RF_setmaclen(3); # SETUP_AW for 3-byte addresses.
663 client.RF_setsmac(0x123456);
664 client.RF_setpacketlen(4);
666 #Power radio, prime for RX, two-byte checksum.
667 client.poke(0x00,0x70|0x03|0x04|0x08);
669 print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
670 client.RF_getfreq()/10**6);
671 #Now we're ready to get packets.
676 packet=client.RF_rxpacket();
681 if(sys.argv[1]=="sniff"):
683 print "Set MAC to %s" % sys.argv[2];
684 client.tune(sys.argv[2]);
685 client.RF_setmaclen(5);
687 #client.poke(0x00,0x00); #Stop nRF
688 client.poke(0x07,0x78); #Reset status register
690 #Power radio, prime for RX, no checksum.
691 client.poke(0x00,0x70|0x03);
693 client.RF_setpacketlen(32);
695 #client.RF_setmaclen(3); # SETUP_AW for shortest
697 print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
698 client.RF_getfreq()/10**6);
699 #Now we're ready to get packets.
705 packet=client.RF_rxpacket();
708 if(sys.argv[1]=="explore"):
709 #client.poke(0x00,0x00); #Stop nRF
710 client.poke(0x07,0x78); #Reset status register
712 #Power radio, prime for RX, no checksum.
713 client.poke(0x00,0x70|0x03);
715 #Set packet length of 32.
716 #Without checksums, extra data will mix in.
717 client.RF_setpacketlen(32);
718 client.RF_setmaclen(3); # shortest address length
720 #Now we're ready to get packets.
721 for smac in [0x0102030201, 0]:
722 client.RF_setsmac(smac);
723 for chan in range(0,0x80):
724 client.RF_setfreq((2400+chan) * 10**6);
726 packet=client.RF_rxpacket();
728 print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
729 client.RF_getfreq()/10**6);