AutoTuner drops invalid Nordic RF MAC addresses.
[goodfet] / client / goodfet.nrf
1 #!/usr/bin/env python
2
3 #GoodFET SPI Flash Client
4 #by Travis Goodspeed
5
6 import sys;
7 import binascii;
8 import array;
9 import time;
10
11 from GoodFETNRF import GoodFETNRF;
12 from intelhex import IntelHex;
13
14
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",
18           "TX_ADDR",
19           "RX_PW_P0","RX_PW_P1","RX_PW_P2","RX_PW_P3","RX_PW_P4","RX_PW_P5",
20           "FIFO_STATUS","?",
21           "?","?","?","DYNPD","FEATURE","AGC_CONFIG","?","?",
22           "?","?","?","?","?","?","?","?"];
23
24 def printpacket(packet):
25     s="";
26     i=0;
27     for foo in packet:
28         i=i+1;
29         if i>client.packetlen: break;
30         s="%s %02x" % (s,ord(foo));
31     print "%s" % s;
32
33 def printconfig():
34     print "Encoding %s" % client.RF_getenc();
35     print "Freq    %10i MHz" % (client.RF_getfreq()/10**6);
36     print "Rate    %10i kbps" % (client.RF_getrate()/1000);
37     print "PacketLen %02i bytes" % client.RF_getpacketlen();
38     #print "MacLen    %2i bytes" % client.RF_getmaclen();
39     print "SMAC  0x%010x" % client.RF_getsmac();
40     print "TMAC  0x%010x" % client.RF_gettmac();
41
42
43 if(len(sys.argv)==1):
44     print "Usage: %s verb [objects]\n" % sys.argv[0];
45     print "%s info" % sys.argv[0];
46     print "%s test" % sys.argv[0];
47     print "%s regs" % sys.argv[0];
48     print "%s regbits" % sys.argv[0];
49     print "%s pyregs" % sys.argv[0];
50     print "";
51     print "%s sniff\n\tSniffs packets by current config." % sys.argv[0];
52     print "%s sniffob\n\tSniffs OpenBeacon traffic." % sys.argv[0];
53     print "%s snifftp\n\tSniffs Turning Point Clicker traffic." % sys.argv[0];
54     print "%s sniffsf\n\tSniffs SparkFun Dongle traffic." % sys.argv[0];
55     print "";
56     print "%s sniffprom [0xaa|0x55]\n\tSniffs promiscuously for a preamble of 0xAA or 0x55" % sys.argv[0];
57     print "%s autotune\n\tSearches for a valid destination address." % sys.argv[0];
58     print "";
59     print "%s sniffskybrake\n\tSniffs skybrake. [broken?]" % sys.argv[0];
60     print "%s sniffmskb\n\tSniffs MS KB. [broken?]" % sys.argv[0];
61     
62     
63     print "%s hosttp\n\tHosts Turning Point Clicker traffic." % sys.argv[0];
64
65     print "%s carrier [freq]\n\tHolds a carrier on [freq] Hz." % sys.argv[0];
66     sys.exit();
67
68 #Initialize FET and set baud rate
69 client=GoodFETNRF();
70 client.serInit()
71
72 client.NRFsetup();
73
74 if(sys.argv[1]=="info"):
75     printconfig();
76
77 if(sys.argv[1]=="test"):
78     print "Old registers:"
79     printconfig();
80     
81     # Set PWR_UP=1 and PRIM_RX=0 in CONFIG.
82     client.poke(0x00,2);
83     #Delay of 1.5ms by round-trip.
84     
85     print "\n\n";
86     
87     #Try all data rates
88     for foo in [250*10**3,
89                 1*10**6,
90                 2*10**6]:
91         client.RF_setrate(foo);
92         if(client.RF_getrate()!=foo):
93             print "ERROR Rate %i not supported.  Got %i instead." % (foo,
94                                                                      client.RF_getrate());
95     
96     print "\n\n";
97     client.poke(0x0A,0xDEADBEEF,5);
98     #print "SMAC set to %010x" % client.RF_getsmac();
99     if client.RF_getsmac()!=0xdeadbeef:
100         print "ERROR: Failed to set MAC address.";
101     print "Final registers:"
102     printconfig();
103     
104 if(sys.argv[1]=="carrier"):
105     if len(sys.argv)>2:
106         client.RF_setfreq(eval(sys.argv[2]));
107     client.RF_carrier();
108     printconfig();
109     print "\nHolding a carrier wave.";
110     while(1):
111         time.sleep(1);
112 if(sys.argv[1]=="regs"):
113     for r in range(0,0x20):
114         print "r[0x%02x]=0x%010x //%16s " % (r,client.peek(r),regnames[r]);
115 if(sys.argv[1]=="pyregs"):
116     for r in range(0,0x20):
117         print "client.set(0x%02x,0x%010x); #%16s " % (r,client.peek(r),regnames[r]);
118
119 if(sys.argv[1]=="peek"):
120     start=0x0000;
121     if(len(sys.argv)>2):
122         start=int(sys.argv[2],16);
123     stop=start;
124     if(len(sys.argv)>3):
125         stop=int(sys.argv[3],16);
126     print "Peeking from %02x to %02x." % (start,stop);
127     while start<=stop:
128         print "%02x: %010x" % (start,client.peek(start));
129         start=start+1;
130 if(sys.argv[1]=="poke"):
131     start=0x0000;
132     val=0x00;
133     if(len(sys.argv)>2):
134         start=int(sys.argv[2],16);
135     if(len(sys.argv)>3):
136         val=int(sys.argv[3],16);
137     print "Poking %02x to become %010x." % (start,val);
138     
139     client.poke(start,val);
140     print "Poked to %04x" % client.peek(start);
141
142 if(sys.argv[1]=="sniffob"):
143     #Reversal of transmitter code from nRF_CMD.c of OpenBeacon
144     #TODO remove all poke() calls.
145     
146     client.poke(0x00,0x00); #Stop nRF
147     client.poke(0x01,0x00); #Disable Shockburst
148     client.poke(0x02,0x01); #Set RX Pipe 0
149     
150     client.RF_setfreq(2481 * 10**6);
151     client.poke(0x06,0x09); #2MBps, -18dBm in RF_SETUP
152     client.poke(0x07,0x78); #Reset status register
153     
154     #OpenBeacon defines these in little endian as follows.
155     client.RF_setmaclen(5); # SETUP_AW for 5-byte addresses.
156     #0x01, 0x02, 0x03, 0x02, 0x01
157     client.RF_setsmac(0x0102030201);
158     #'O', 'C', 'A', 'E', 'B'
159     client.RF_settmac(0x424541434F);
160     
161     #Set packet length of 16.
162     client.RF_setpacketlen(16);
163     
164     #Power radio, prime for RX, one-byte checksum.
165     client.poke(0x00,0x70|0x03|0x08); #0x08 for one byte, 0x04 for two.
166     
167     print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
168                                            client.RF_getfreq()/10**6);
169     #Now we're ready to get packets.
170     while 1:
171         packet=None;
172         while packet==None:
173             #time.sleep(0.1);
174             packet=client.RF_rxpacket();
175         printpacket(packet);
176         sys.stdout.flush();
177
178 if(sys.argv[1]=="regbits"):
179     print "Scanning registers to determine which bits are valid."
180     regbits=range(0,0x30);
181     for r in range(0,0x30):
182         old=client.peek(r);
183         #Which bits can be set?
184         client.poke(r,0xFF);
185         ones=client.peek(r);
186         #Which bits can be clear?
187         client.poke(r,0x00);
188         zeroes=client.peek(r);
189         regbits[r]=(ones & (~zeroes));
190     for r in range(0,0x30):
191         if regbits[r]!=0:
192             print "r[0x%02x] masked %02x // %s" % (r,regbits[r], regnames[r]);
193 if(sys.argv[1]=="sniffprom"):
194     #Reversal of transmitter code from nRF_CMD.c of OpenBeacon
195     #TODO remove all poke() calls.
196     
197     client.poke(0x00,0x00); #Stop nRF
198     client.poke(0x01,0x00); #Disable Shockburst
199     client.poke(0x02,0x01); #Set RX Pipe 0
200     
201     #client.RF_setfreq(2481 * 10**6);
202     #client.poke(0x06,0x09); #2MBps, -18dBm in RF_SETUP
203     client.poke(0x07,0x78); #Reset status register
204     
205     #OpenBeacon defines these in little endian as follows.
206     client.RF_setmaclen(2); # SETUP_AW for shortest
207     
208     #It's better to have a known fragment, when one is available.
209     #client.RF_setsmac(0x00AA);
210     #client.RF_setsmac(0x0055);
211     
212     #Should end in 55 or AA depending upon the packet.
213     tail=0x55
214     if(len(sys.argv)>2):
215         tail=int(sys.argv[2],16);
216     else:
217         print "Please specify a tail of 0xAA or 0x55.";
218         sys.exit(1);
219     client.RF_setsmac(tail);
220     
221     #Longest length.
222     client.RF_setpacketlen(32);
223     
224     #Power radio, prime for RX, no checksum
225     client.poke(0x00,0x70|0x03); #0x08 for checksum, 0x04 for two.
226     
227     print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
228                                            client.RF_getfreq()/10**6);
229     #Now we're ready to get packets.
230     while 1:
231         packet=None;
232         while packet==None:
233             #time.sleep(0.1);
234             packet=client.RF_rxpacket();
235         printpacket(packet);
236         sys.stdout.flush();
237
238 class AutoTuner():
239     """This guesses addresses by searching through packets."""
240     #packets=[];
241     addresses={};
242     client=None;
243     def init(self,goodfet):
244         """Initializes a link to the GoodFET for autotuning."""
245         self.client=goodfet;
246     def packetaddr(self,packet):
247         """Returns a loaded packet address, including channel and rate."""
248         
249         sync=self.client.RF_getsmac()&0xFF;
250         
251         mac="";
252         #MAC,RF_CH,RATE
253         for i in range(0,5):
254             mac="%s%02x" % (mac,ord(packet[i]));
255         ch=self.client.peek(0x05);
256         rate=self.client.peek(0x06);
257         return "%02x,%s,%02x,%02x" % (
258             sync,mac,ch,rate);
259     def validmac(self,packet):
260         sync=self.client.RF_getsmac()&0xFF;
261         if (ord(packet[0])&0x80)^(sync&0x80):
262             #print "%02x%02x invalid entry." % (sync,ord(packet[0]));
263             return False;
264         return True;
265         
266     def handle(self,packet):
267         """Handles a packet."""
268         #printpacket(packet);
269         if not self.validmac(packet):
270             #print "Dropped packet:";
271             #printpacket(packet);
272             return;
273         addr=self.packetaddr(packet);
274         
275         #Increment the address count.
276         count=0;
277         try:
278             count=self.addresses[addr];
279         except:
280             pass;
281         self.addresses[addr]=count+1;
282         rate=count*1.0/len(self.addresses);
283         if self.addresses[addr]>1 or rate>0.01:
284             print "'%s' looks valid\t%i\t%0.5f" % (
285                 addr,count,rate);
286         return;
287     tunecount=0;
288     def retune(self,freqmod=0x52):
289         """Tunes to another channel or preamble looking for the next packet."""
290         count=self.tunecount+1;
291         self.tunecount=count;
292         
293         #Swap the SYNC value most often.
294         sync=0xAA;
295         if count&1:
296             sync=0x55;
297         self.client.RF_setsmac(sync);
298         count=(count>>1);
299         
300         #Then the data rate.
301         rate=0;
302         
303         #This swaps between 1Mbps and 2Mbps.
304         #TODO add support for 256kbps, if anyone uses it.
305         if count&1:
306             rate=rate|0x08;
307         #print "Setting rate to 0x%02x" % rate;
308         if(rate==0x20):
309             rate=0x08;
310         self.client.poke(0x06,rate);
311         count=(count>>2);
312         
313         #Grab two packets to clear buffers.
314         #Should retune only after a few packets to reduce this delay.
315         packet=client.RF_rxpacket();
316         packet=client.RF_rxpacket();
317         return;
318         
319         
320 if(sys.argv[1]=="autotune"):
321     #Reversal of transmitter code from nRF_CMD.c of OpenBeacon
322     #TODO remove all poke() calls.
323     guesser=AutoTuner();
324     guesser.init(client);
325     
326     client.poke(0x00,0x00); #Stop nRF
327     client.poke(0x01,0x00); #Disable Shockburst
328     client.poke(0x02,0x01); #Set RX Pipe 0
329     
330     #client.RF_setfreq(2481 * 10**6);
331     #client.poke(0x06,0x09); #2MBps, -18dBm in RF_SETUP
332     client.poke(0x07,0x78); #Reset status register
333     
334     #OpenBeacon defines these in little endian as follows.
335     client.RF_setmaclen(2); # SETUP_AW for shortest
336     
337     #This is determined by the MAC, which we don't yet know.
338     #AutoTuner() takes care of finding it.
339     #client.RF_setsmac(0x00AA);
340     #client.RF_setsmac(0x0055);
341     
342     #Longest length.
343     client.RF_setpacketlen(32);
344     
345     #Power radio, prime for RX, no checksum
346     client.poke(0x00,0x70|0x03); #0x08 for checksum, 0x04 for two.
347     
348     print "Autotuning as %010x on %i MHz" % (client.RF_getsmac(),
349                                            client.RF_getfreq()/10**6);
350     print "sync,mac,r5,r6";
351     #Now we're ready to get packets.
352     while 1:
353         for foo in range(1,10):
354             packet=None;
355             while packet==None:
356                 packet=client.RF_rxpacket();
357             guesser.handle(packet);
358             guesser.retune();
359         sys.stdout.flush();
360
361 if(sys.argv[1]=="sniffmskb"):
362     #MSWK 3000 v2.0
363     #TODO remove all poke() calls.
364     
365     client.poke(0x00,0x00); #Stop nRF
366     client.poke(0x01,0x00); #Disable Shockburst
367     client.poke(0x02,0x01); #Set RX Pipe 0
368     
369     client.poke(0x06,0x09); #2MBps, -18dBm in RF_SETUP
370     client.poke(0x07,0x78); #Reset status register
371     
372     #This is the address of a specific keyboard.
373     #Other keyboards will be different.
374     
375     
376     client.RF_setmaclen(2);
377     
378     #Known pairs.  The channel and the low address bytes must match.
379     #client.RF_setfreq((2400+0x13) * 10**6);
380     #client.RF_setsmac(0x0c00a3598cd);
381     
382     client.RF_setfreq((2400+0x15) * 10**6);
383     client.RF_setsmac( 0x0c10446facd);
384     
385     #Mac packet length, illegally 0-length address field.
386     client.RF_setpacketlen(32);
387     
388     #Power radio, prime for RX, no checksum
389     client.poke(0x00,0x70|0x03); #0x08 for checksum, 0x04 for two.
390     
391     print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
392                                            client.RF_getfreq()/10**6);
393     #Now we're ready to get packets.
394     while 1:
395         packet=None;
396         while packet==None:
397             #time.sleep(0.1);
398             packet=client.RF_rxpacket();
399         printpacket(packet);
400         sys.stdout.flush();
401
402
403
404 if(sys.argv[1]=="sniffskybrake"):
405     #Reversal of transmitter code from nRF_CMD.c of OpenBeacon
406     #TODO remove all poke() calls.
407     
408     client.poke(0x00,0x00); #Stop nRF
409     client.poke(0x01,0x00); #Disable Shockburst
410     client.poke(0x02,0x01); #Set RX Pipe 0
411     
412     client.RF_setfreq(2439 * 10**6);
413     client.poke(0x06,0x00); #1MBps
414     client.poke(0x07,0x78); #Reset status register
415     
416     #OpenBeacon defines these in little endian as follows.
417     client.RF_setmaclen(2); # SETUP_AW for 3-byte addresses.
418     #0x01, 0x02, 0x03, 0x02, 0x01
419     
420     client.RF_setsmac(0x070700d2c4); #reversed
421     
422     #client.RF_setsmac(0xd2c4);
423     #client.RF_setsmac(0);
424     
425     #Mac packet length, illegally 0-length address field.
426     client.RF_setpacketlen(32);
427     
428     #Power radio, prime for RX, one-byte checksum.
429     client.poke(0x00,0x70|0x03); #0x08 for one byte, 0x04 for two.
430     
431     print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
432                                            client.RF_getfreq()/10**6);
433     print "%i byte mac match." % client.RF_getmaclen();
434     #Now we're ready to get packets.
435     while 1:
436         packet=None;
437         while packet==None:
438             #time.sleep(0.1);
439             packet=client.RF_rxpacket();
440         printpacket(packet);
441         sys.stdout.flush();
442
443 if(sys.argv[1]=="sniffsf"):
444     #Reversal of transmitter code from nRF_CMD.c of OpenBeacon
445     #TODO remove all poke() calls.
446     
447     client.poke(0x00,0x00); #Stop nRF
448     client.poke(0x01,0x00); #Disable Shockburst
449     client.poke(0x02,0x01); #Set RX Pipe 0
450     
451     client.RF_setfreq(2402 * 10**6);
452     client.poke(0x06,0x07); #1Mbps
453     client.poke(0x07,0x78); #Reset status register
454     
455     #OpenBeacon defines these in little endian as follows.
456     client.RF_setmaclen(5); # SETUP_AW for 5-byte addresses.
457     client.RF_setsmac(0xe7e7e7e7e7);
458     client.RF_settmac(0xe7e7e7e7e7);
459     
460     #Set packet length of 16.
461     client.RF_setpacketlen(4);
462     
463     #Power radio, prime for RX, one-byte checksum.
464     client.poke(0x00,0x70|0x03|0x08); #0x08 for one byte, 0x04 for two.
465     
466     print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
467                                            client.RF_getfreq()/10**6);
468     #Now we're ready to get packets.
469     while 1:
470         packet=None;
471         while packet==None:
472             #time.sleep(0.1);
473             packet=client.RF_rxpacket();
474         printpacket(packet);
475         sys.stdout.flush();
476
477 if(sys.argv[1]=="snifftp"):
478     client.poke(0x00,0x00); #Stop nRF
479     client.poke(0x01,0x00); #Disable Shockburst
480     client.poke(0x02,0x01); #Set RX Pipe 0
481     
482     client.RF_setfreq((2400+0x29) * 10**6);
483     client.poke(0x06,0x00); #1Mbps
484     client.poke(0x07,0x78); #Reset status register
485     
486     client.RF_setmaclen(3); # SETUP_AW for 3-byte addresses.
487     client.RF_setsmac(0x123456);
488     client.RF_setpacketlen(4);
489     
490     #Power radio, prime for RX, two-byte checksum.
491     client.poke(0x00,0x70|0x03|0x04|0x08);
492     
493     print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
494                                            client.RF_getfreq()/10**6);
495     #Now we're ready to get packets.
496     while 1:
497         packet=None;
498         while packet==None:
499             #time.sleep(0.1);
500             packet=client.RF_rxpacket();
501         printpacket(packet);
502         sys.stdout.flush();
503
504 if(sys.argv[1]=="hosttp"):
505     client.poke(0x00,0x00); #Stop nRF
506     client.poke(0x01,0x00); #Disable Shockburst
507     client.poke(0x02,0x01); #Set RX Pipe 0
508     
509     chan=0x29;
510
511     client.RF_setfreq((2400+chan) * 10**6);
512     client.poke(0x06,0x00); #1Mbps
513     client.poke(0x07,0x78); #Reset status register
514     
515     client.RF_setmaclen(3); # SETUP_AW for 3-byte addresses.
516     client.RF_setsmac(0x123456);
517     client.RF_setpacketlen(4);
518     
519     #Power radio, prime for RX, two-byte checksum.
520     client.poke(0x00,0x70|0x03|0x04|0x08);
521     
522     print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
523                                            client.RF_getfreq()/10**6);
524     #Now we're ready to get packets.
525     while 1:
526         packet=None;
527         while packet==None:
528             packet=client.RF_rxpacket();
529         mac=((ord(packet[0])<<16)+
530              (ord(packet[1])<<8)+
531              ord(packet[2]));
532         key=packet[3];
533         print "%c from %06x" % (key,mac);
534         sys.stdout.flush();
535
536 if(sys.argv[1]=="sniff"):
537     #client.poke(0x00,0x00); #Stop nRF
538     client.poke(0x07,0x78); #Reset status register
539     
540     #Power radio, prime for RX, checksum.
541     client.poke(0x00,0x70|0x03|0x08);
542     
543     print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
544                                            client.RF_getfreq()/10**6);
545     #Now we're ready to get packets.
546     
547     while 1:
548         packet=None;
549         while packet==None:
550             #time.sleep(0.1);
551             packet=client.RF_rxpacket();
552         printpacket(packet);
553         sys.stdout.flush();
554 if(sys.argv[1]=="explore"):
555     #client.poke(0x00,0x00); #Stop nRF
556     client.poke(0x07,0x78); #Reset status register
557     
558     #Power radio, prime for RX, no checksum.
559     client.poke(0x00,0x70|0x03);
560     
561     #Set packet length of 32.
562     #Without checksums, extra data will mix in.
563     client.RF_setpacketlen(32);
564     client.RF_setmaclen(3); # shortest address length
565     
566     #Now we're ready to get packets.
567     for smac in [0x0102030201, 0]:
568         client.RF_setsmac(smac);
569         for chan in range(0,0x80):
570             client.RF_setfreq((2400+chan) * 10**6);
571             time.sleep(1);
572             packet=client.RF_rxpacket();
573             if packet!=None:
574                 print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
575                                                         client.RF_getfreq()/10**6);
576                 printpacket(packet);
577                 sys.stdout.flush();