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));
35 def printmspacket(packet,offset=1):
36 """Decodes a Microsoft keyboard packet and maintains the typed strings."""
38 keyword=client.RF_getsmac();
39 #print "keyword=%010x" % key;
42 for foo in range(0,5):
43 key.append(keyword&0xFF);
45 #print "Keybyte %02x" % key[foo];
51 ct.append(ord(foo)^key[(i+offset)%5]);
52 s="%s %02x" % (s,ord(foo)^key[(i+offset)%5]);
55 s="%s %02x" % (s,ord(foo));
57 #Uncomment this to print the raw packet, kinda noisy.
61 if ct[0]==0x0a and ct[1]==0x78:
62 #TODO replace this with a dictionary, and support modifiers.
64 #Key up event, not worth logging.
66 elif ct[9]>=4 and ct[9]<0x1E:
67 letter=ct[9]+ord('A')-4;
68 elif ct[9]>=0x1E and ct[9]<0x27:
69 letter=ct[9]+ord('1')-0x1E;
88 print "Unknown character 0x%02x." % ct[9];
91 mskbstring="%s%c" % (mskbstring,letter);
92 print "# %s" % mskbstring
94 print "Encoding %s" % client.RF_getenc();
95 print "Freq %10i MHz" % (client.RF_getfreq()/10**6);
96 print "Rate %10i kbps" % (client.RF_getrate()/1000);
97 print "PacketLen %02i bytes" % client.RF_getpacketlen();
98 #print "MacLen %2i bytes" % client.RF_getmaclen();
99 print "SMAC 0x%010x" % client.RF_getsmac();
100 print "TMAC 0x%010x" % client.RF_gettmac();
103 if(len(sys.argv)==1):
104 print "Usage: %s verb [objects]\n" % sys.argv[0];
105 print "%s info" % sys.argv[0];
106 print "%s test" % sys.argv[0];
107 print "%s regs" % sys.argv[0];
108 print "%s regbits" % sys.argv[0];
109 print "%s pyregs" % sys.argv[0];
111 print "%s tune aa|55,mac,r5,r6\n\tTunes to a configuration." % sys.argv[0];
112 print "%s sniff\n\tSniffs packets by current config." % sys.argv[0];
113 print "%s sniffob\n\tSniffs OpenBeacon traffic." % sys.argv[0];
114 print "%s snifftp\n\tSniffs Turning Point Clicker traffic." % sys.argv[0];
115 print "%s sniffsf\n\tSniffs SparkFun Dongle traffic." % sys.argv[0];
117 print "%s sniffmacs \n\tSniffs for MAC addresses on the present channel." % sys.argv[0];
118 print "%s sniffprom [0xaa|0x55]\n\tSniffs promiscuously for a preamble of 0xAA or 0x55" % sys.argv[0];
119 print "%s autotune\n\tSearches for a valid destination address." % sys.argv[0];
121 print "%s sniffskybrake\n\tSniffs skybrake. [broken?]" % sys.argv[0];
122 print "%s sniffmskb\n\tSniffs MS KB. [broken?]" % sys.argv[0];
124 print "%s hosttp\n\tHosts Turning Point Clicker traffic." % sys.argv[0];
126 print "%s carrier [freq]\n\tHolds a carrier on [freq] Hz." % sys.argv[0];
129 #Initialize FET and set baud rate
135 if(sys.argv[1]=="info"):
138 if(sys.argv[1]=="test"):
139 print "Old registers:"
142 # Set PWR_UP=1 and PRIM_RX=0 in CONFIG.
144 #Delay of 1.5ms by round-trip.
149 for foo in [250*10**3,
152 client.RF_setrate(foo);
153 if(client.RF_getrate()!=foo):
154 print "ERROR Rate %i not supported. Got %i instead." % (foo,
155 client.RF_getrate());
158 client.poke(0x0A,0xDEADBEEF,5);
159 #print "SMAC set to %010x" % client.RF_getsmac();
160 if client.RF_getsmac()!=0xdeadbeef:
161 print "ERROR: Failed to set MAC address.";
162 print "Final registers:"
165 if(sys.argv[1]=="carrier"):
167 client.RF_setfreq(eval(sys.argv[2]));
170 print "\nHolding a carrier wave.";
174 if(sys.argv[1]=="tune"):
176 client.tune(sys.argv[2]);
178 print "Specify a tuning, such as 'aa,c78c65805e,14,09'";
179 if(sys.argv[1]=="regs"):
180 for r in range(0,0x20):
181 print "r[0x%02x]=0x%010x //%16s " % (r,client.peek(r),regnames[r]);
182 if(sys.argv[1]=="pyregs"):
183 for r in range(0,0x20):
184 print "client.set(0x%02x,0x%010x); #%16s " % (r,client.peek(r),regnames[r]);
186 if(sys.argv[1]=="peek"):
189 start=int(sys.argv[2],16);
192 stop=int(sys.argv[3],16);
193 print "Peeking from %02x to %02x." % (start,stop);
195 print "%02x: %010x" % (start,client.peek(start));
197 if(sys.argv[1]=="poke"):
201 start=int(sys.argv[2],16);
203 val=int(sys.argv[3],16);
204 print "Poking %02x to become %010x." % (start,val);
206 client.poke(start,val);
207 print "Poked to %04x" % client.peek(start);
209 if(sys.argv[1]=="sniffob"):
210 #Reversal of transmitter code from nRF_CMD.c of OpenBeacon
211 #TODO remove all poke() calls.
213 client.poke(0x00,0x00); #Stop nRF
214 client.poke(0x01,0x00); #Disable Shockburst
215 client.poke(0x02,0x01); #Set RX Pipe 0
217 client.RF_setfreq(2481 * 10**6);
218 client.poke(0x06,0x09); #2MBps, -18dBm in RF_SETUP
219 client.poke(0x07,0x78); #Reset status register
221 #OpenBeacon defines these in little endian as follows.
222 client.RF_setmaclen(5); # SETUP_AW for 5-byte addresses.
223 #0x01, 0x02, 0x03, 0x02, 0x01
224 client.RF_setsmac(0x0102030201);
225 #'O', 'C', 'A', 'E', 'B'
226 client.RF_settmac(0x424541434F);
228 #Set packet length of 16.
229 client.RF_setpacketlen(16);
231 #Power radio, prime for RX, one-byte checksum.
232 client.poke(0x00,0x70|0x03|0x08); #0x08 for one byte, 0x04 for two.
234 print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
235 client.RF_getfreq()/10**6);
236 #Now we're ready to get packets.
241 packet=client.RF_rxpacket();
245 if(sys.argv[1]=="regbits"):
246 print "Scanning registers to determine which bits are valid."
247 regbits=range(0,0x30);
248 for r in range(0,0x30):
250 #Which bits can be set?
253 #Which bits can be clear?
255 zeroes=client.peek(r);
256 regbits[r]=(ones & (~zeroes));
257 for r in range(0,0x30):
259 print "r[0x%02x] masked %02x // %s" % (r,regbits[r], regnames[r]);
260 if(sys.argv[1]=="sniffprom"):
261 #Reversal of transmitter code from nRF_CMD.c of OpenBeacon
262 #TODO remove all poke() calls.
264 client.poke(0x00,0x00); #Stop nRF
265 client.poke(0x01,0x00); #Disable Shockburst
266 client.poke(0x02,0x01); #Set RX Pipe 0
268 #client.RF_setfreq(2481 * 10**6);
269 #client.poke(0x06,0x09); #2MBps, -18dBm in RF_SETUP
270 client.poke(0x07,0x78); #Reset status register
272 #OpenBeacon defines these in little endian as follows.
273 client.RF_setmaclen(2); # SETUP_AW for shortest
275 #It's better to have a known fragment, when one is available.
276 #client.RF_setsmac(0x00AA);
277 #client.RF_setsmac(0x0055);
279 #Should end in 55 or AA depending upon the packet.
282 tail=int(sys.argv[2],16);
284 print "Please specify a tail of 0xAA or 0x55.";
286 client.RF_setsmac(tail);
289 client.RF_setpacketlen(32);
291 #Power radio, prime for RX, no checksum
292 client.poke(0x00,0x70|0x03); #0x08 for checksum, 0x04 for two.
294 print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
295 client.RF_getfreq()/10**6);
296 #Now we're ready to get packets.
301 packet=client.RF_rxpacket();
306 """This guesses addresses by searching through packets."""
310 #Limits on search space, because you usually know what you're looking for.
314 startch=0; #Useful for forcing an early match.
315 def init(self,goodfet,
316 rate=True,chan=True,sync=True):
317 """Initializes a link to the GoodFET for autotuning."""
323 client.poke(0x00,0x00); #Stop nRF
324 client.poke(0x01,0x00); #Disable Shockburst
325 client.poke(0x02,0x01); #Set RX Pipe 0
328 client.poke(0x1C,0x00);
329 client.poke(0x1D,0x00);
331 client.RF_setmaclen(2); # SETUP_AW for shortest
334 #client.RF_setsmac(0x00AA);
335 #client.RF_setsmac(0x0055);
337 client.poke(0x00,0x70|0x03); #prime radio.
340 def packetaddr(self,packet,justmac=False):
341 """Returns a loaded packet address, including channel and rate."""
343 sync=self.client.RF_getsmac()&0xFF;
348 mac="%s%02x" % (mac,ord(packet[i]));
351 ch=self.client.peek(0x05);
352 rate=self.client.peek(0x06);
353 return "%02x,%s,%02x,%02x" % (
355 def validmac(self,packet):
356 sync=self.client.RF_getsmac()&0xFF;
357 mac=self.packetaddr(packet,justmac=True);
358 if (ord(packet[0])&0x80)^(sync&0x80):
359 #print "%02x%02x invalid entry." % (sync,ord(packet[0]));
360 #This is a special kind of failure. Freq is probably right, but MAC is wrong.
362 if mac=='5555555555' or mac=='aaaaaaaaaa' or mac=='0000000000':
366 def handle(self,packet):
367 """Handles a packet."""
368 #printpacket(packet);
370 if not self.validmac(packet):
371 #print "Dropped packet from %s" % self.packetaddr(packet,justmac=True);
372 #printpacket(packet);
375 addr=self.packetaddr(packet);
377 #Increment the address count.
380 count=self.addresses[addr];
383 self.addresses[addr]=count+1;
384 rate=count*1.0/len(self.addresses);
385 if self.addresses[addr]>1 or rate>0.01:
386 print "'%s' looks valid\t%i\t%0.5f" % (
390 def selftune(self,threshold=2,forever=False,
392 """Tunes to the first strong signal.
393 It's important that this not get triggered by false positives."""
397 start=time.mktime(time.localtime());
399 while (time.mktime(time.localtime())-start) < delay:
402 packet=client.RF_rxpacket();
403 addr=guesser.handle(packet);
405 count=self.addresses[addr];
408 if count>threshold and forever==False:
415 """Tunes to another channel or preamble looking for the next packet."""
416 count=self.tunecount;
417 self.tunecount=count+1;
419 #Swap the SYNC value most often.
424 self.client.RF_setsmac(sync);
431 #This swaps between 1Mbps and 2Mbps.
432 #TODO add support for 256kbps, if anyone uses it.
435 #print "Setting rate to 0x%02x" % rate;
438 self.client.poke(0x06,rate);
442 self.client.poke(0x05,
443 (count+self.startch)&0x7f);
444 print "Tuned to %i MHz" % (
445 self.client.RF_getfreq()
447 #Grab two packets to clear buffers.
448 #Should retune only after a few packets to reduce this delay.
449 packet=client.RF_rxpacket();
450 packet=client.RF_rxpacket();
454 if(sys.argv[1]=="autotune"):
455 #Reversal of transmitter code from nRF_CMD.c of OpenBeacon
456 #TODO remove all poke() calls.
458 guesser.init(client,rate=True,sync=True,chan=True);
461 #client.RF_setfreq(2481 * 10**6);
462 client.poke(0x06,0x09); #2MBps, -18dBm in RF_SETUP
463 client.poke(0x07,0x78); #Reset status register
465 #This is determined by the MAC, which we don't yet know.
468 client.RF_setpacketlen(32);
470 #Power radio, prime for RX, no checksum
471 client.poke(0x00,0x70|0x03); #0x08 for checksum, 0x04 for two.
473 print "Autotuning on %i MHz" % (
474 client.RF_getfreq()/10**6);
475 print "sync,mac,r5,r6";
476 #Now we're ready to get packets.
477 guesser.selftune(threshold=2,
480 if(sys.argv[1]=="sniffmacs"):
481 #Reversal of transmitter code from nRF_CMD.c of OpenBeacon
482 #TODO remove all poke() calls.
484 guesser.init(client,rate=False,sync=True,chan=False);
487 client.RF_setpacketlen(32);
489 #Power radio, prime for RX, no checksum
490 client.poke(0x00,0x70|0x03); #0x08 for checksum, 0x04 for two.
492 print "Holding autotune on %i MHz" % (
493 client.RF_getfreq()/10**6);
494 print "sync,mac,r5,r6";
495 #Now we're ready to get packets.
496 guesser.selftune(threshold=2,
499 if(sys.argv[1]=="sniffmskb"):
501 #TODO remove all poke() calls.
503 client.poke(0x00,0x00); #Stop nRF
504 client.poke(0x01,0x00); #Disable Shockburst
505 client.poke(0x02,0x01); #Set RX Pipe 0
507 client.poke(0x06,0x09); #2MBps, -18dBm in RF_SETUP
508 client.poke(0x07,0x78); #Reset status register
510 #This is the address of a specific keyboard.
511 #Other keyboards will be different.
513 client.RF_setmaclen(5);
515 #Known pairs. The channel and the low address bytes must match.
516 #client.RF_setfreq((2400+0x13) * 10**6);
517 #client.RF_setsmac(0xc00a3598cd);
519 #client.RF_setfreq((2400+0x15) * 10**6);
520 #client.RF_setsmac(0xc10446facd);
522 #Mac packet length, illegally 0-length address field.
523 client.RF_setpacketlen(16);
527 client.tune(sys.argv[2]);
530 print "Searching for a keyboard.";
533 guesser.init(client, rate=False, sync=True, chan=True);
534 guesser.selftune(threshold=4,forever=False,
537 client.poke(0x00,0x00); #Stop nRF
538 client.poke(0x01,0x00); #Disable Shockburst
539 client.poke(0x02,0x01); #Set RX Pipe 0
540 client.RF_setmaclen(5);
542 #Finally, dynamic payload lengths need to be enabled.
543 #client.poke(0x01,0x01);
544 client.poke(0x1C,0x01);
545 client.poke(0x1D,0x06);
547 client.poke(0x00,0x70|0x03); #prime radio.
548 print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
549 client.RF_getfreq()/10**6);
550 #Now we're ready to get packets.
555 packet=client.RF_rxpacket();
557 printmspacket(packet);
560 if(sys.argv[1]=="sniffant"):
561 #Prototyped on Garmin device.
562 #Channel hopping is pretty damned fast, hard to follow.
563 #This doesn't really work yet, still experimenting.
565 #Might be more effective to sniff knowing the MFG ID and Dev. ID,
566 #as these predict a lot of the MAC address.
568 client.poke(0x00,0x00); #Stop nRF
569 client.poke(0x01,0x00); #Disable Shockburst
570 client.poke(0x02,0x01); #Set RX Pipe 0
572 client.poke(0x05,57); #broadcast-only channel
573 client.poke(0x06,0x00); #1MBps
574 client.poke(0x07,0x78); #Reset status register
576 #Is this appropriate? Might be 3.
577 client.RF_setmaclen(5);
580 #Mac packet length, illegally 0-length address field.
581 client.RF_setpacketlen(16);
584 client.tune(sys.argv[2]);
587 print "Searching for ANT+.";
590 guesser.init(client, rate=False, sync=True, chan=True);
591 guesser.selftune(threshold=2,forever=False,
594 client.poke(0x00,0x00); #Stop nRF
595 client.poke(0x01,0x00); #Disable Shockburst
596 client.poke(0x02,0x01); #Set RX Pipe 0
597 client.RF_setmaclen(5);
600 client.poke(0x00,0x70|0x03); #prime radio.
601 print "Dumping ANT as %010x on %i MHz" % (client.RF_getsmac(),
602 client.RF_getfreq()/10**6);
603 #Now we're ready to get packets.
608 packet=client.RF_rxpacket();
615 if(sys.argv[1]=="sniffskybrake"):
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(2439 * 10**6);
624 client.poke(0x06,0x00); #1MBps
625 client.poke(0x07,0x78); #Reset status register
627 #OpenBeacon defines these in little endian as follows.
628 client.RF_setmaclen(2); # SETUP_AW for 3-byte addresses.
629 #0x01, 0x02, 0x03, 0x02, 0x01
631 client.RF_setsmac(0x070700d2c4); #reversed
633 #client.RF_setsmac(0xd2c4);
634 #client.RF_setsmac(0);
636 #Mac packet length, illegally 0-length address field.
637 client.RF_setpacketlen(32);
639 #Power radio, prime for RX, one-byte checksum.
640 client.poke(0x00,0x70|0x03); #0x08 for one byte, 0x04 for two.
642 print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
643 client.RF_getfreq()/10**6);
644 print "%i byte mac match." % client.RF_getmaclen();
645 #Now we're ready to get packets.
650 packet=client.RF_rxpacket();
654 if(sys.argv[1]=="sniffsf"):
655 #Reversal of transmitter code from nRF_CMD.c of OpenBeacon
656 #TODO remove all poke() calls.
658 client.poke(0x00,0x00); #Stop nRF
659 client.poke(0x01,0x00); #Disable Shockburst
660 client.poke(0x02,0x01); #Set RX Pipe 0
662 client.RF_setfreq(2402 * 10**6);
663 client.poke(0x06,0x07); #1Mbps
664 client.poke(0x07,0x78); #Reset status register
666 #OpenBeacon defines these in little endian as follows.
667 client.RF_setmaclen(5); # SETUP_AW for 5-byte addresses.
668 client.RF_setsmac(0xe7e7e7e7e7);
669 client.RF_settmac(0xe7e7e7e7e7);
671 #Set packet length of 16.
672 client.RF_setpacketlen(4);
674 #Power radio, prime for RX, one-byte checksum.
675 client.poke(0x00,0x70|0x03|0x08); #0x08 for one byte, 0x04 for two.
677 print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
678 client.RF_getfreq()/10**6);
679 #Now we're ready to get packets.
684 packet=client.RF_rxpacket();
688 if(sys.argv[1]=="snifftp"):
689 client.poke(0x00,0x00); #Stop nRF
690 client.poke(0x01,0x00); #Disable Shockburst
691 client.poke(0x02,0x01); #Set RX Pipe 0
694 client.poke(0x1C,0x00);
695 client.poke(0x1D,0x00);
697 client.RF_setfreq((2400+0x29) * 10**6);
698 client.poke(0x06,0x00); #1Mbps
699 client.poke(0x07,0x78); #Reset status register
701 client.RF_setmaclen(3); # SETUP_AW for 3-byte addresses.
702 client.RF_setsmac(0x123456);
703 client.RF_setpacketlen(4);
705 #Power radio, prime for RX, two-byte checksum.
706 client.poke(0x00,0x70|0x03|0x04|0x08);
708 print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
709 client.RF_getfreq()/10**6);
710 #Now we're ready to get packets.
715 packet=client.RF_rxpacket();
719 if(sys.argv[1]=="hosttp"):
720 client.poke(0x00,0x00); #Stop nRF
721 client.poke(0x01,0x00); #Disable Shockburst
722 client.poke(0x02,0x01); #Set RX Pipe 0
726 client.RF_setfreq((2400+chan) * 10**6);
727 client.poke(0x06,0x00); #1Mbps
728 client.poke(0x07,0x78); #Reset status register
730 client.RF_setmaclen(3); # SETUP_AW for 3-byte addresses.
731 client.RF_setsmac(0x123456);
732 client.RF_setpacketlen(4);
734 #Power radio, prime for RX, two-byte checksum.
735 client.poke(0x00,0x70|0x03|0x04|0x08);
737 print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
738 client.RF_getfreq()/10**6);
739 #Now we're ready to get packets.
743 packet=client.RF_rxpacket();
744 mac=((ord(packet[0])<<16)+
748 print "%c from %06x" % (key,mac);
751 if(sys.argv[1]=="sniff"):
753 print "Set MAC to %s" % sys.argv[2];
754 client.tune(sys.argv[2]);
755 client.RF_setmaclen(5);
757 #client.poke(0x00,0x00); #Stop nRF
758 client.poke(0x07,0x78); #Reset status register
760 #Power radio, prime for RX, no checksum.
761 client.poke(0x00,0x70|0x03);
763 client.RF_setpacketlen(32);
765 #client.RF_setmaclen(3); # SETUP_AW for shortest
767 print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
768 client.RF_getfreq()/10**6);
769 #Now we're ready to get packets.
775 packet=client.RF_rxpacket();
778 if(sys.argv[1]=="explore"):
779 #client.poke(0x00,0x00); #Stop nRF
780 client.poke(0x07,0x78); #Reset status register
782 #Power radio, prime for RX, no checksum.
783 client.poke(0x00,0x70|0x03);
785 #Set packet length of 32.
786 #Without checksums, extra data will mix in.
787 client.RF_setpacketlen(32);
788 client.RF_setmaclen(3); # shortest address length
790 #Now we're ready to get packets.
791 for smac in [0x0102030201, 0]:
792 client.RF_setsmac(smac);
793 for chan in range(0,0x80):
794 client.RF_setfreq((2400+chan) * 10**6);
796 packet=client.RF_rxpacket();
798 print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
799 client.RF_getfreq()/10**6);