0658f58fb1ab93961b8a4e934fe827b9b58cdf22
[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
34 mskbstring="";
35 def printmspacket(packet,offset=1):
36     """Decodes a Microsoft keyboard packet and maintains the typed strings."""
37     global mskbstring;
38     keyword=client.RF_getsmac();
39     #print "keyword=%010x" % key;
40     key=[];
41     ct=[];
42     for foo in range(0,5):
43         key.append(keyword&0xFF);
44         keyword=(keyword>>8);
45         #print "Keybyte %02x" % key[foo];
46     i=0;
47     s="";
48     
49     for foo in packet:
50         if i>=4:
51             ct.append(ord(foo)^key[(i+offset)%5]);
52             s="%s %02x" % (s,ord(foo)^key[(i+offset)%5]);
53         else:
54             ct.append(ord(foo));
55             s="%s %02x" % (s,ord(foo));
56         i=i+1;
57     #Uncomment this to print the raw packet, kinda noisy.
58     #print "%s" % (s);
59     
60     letter=None;
61     if ct[0]==0x0a and ct[1]==0x78:
62         #TODO replace this with a dictionary, and support modifiers.
63         if ct[9]==0:
64             #Key up event, not worth logging.
65             pass;
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;
70         elif ct[9]==0x27:
71             letter=ord('0');
72         elif ct[9]==0x29:
73             #escape
74             letter=ord('e');
75         elif ct[9]==0x2d:
76             letter=ord('-');
77         elif ct[9]==0x2e:
78             letter=ord('=');
79         elif ct[9]==0x35:
80             letter=ord('`');
81         elif ct[9]==0x2C:
82             letter=ord('_');
83         elif ct[9]==0x34:
84             letter=ord('\'');
85         elif ct[9]==0x36:
86             letter=ord(',');
87         else:
88             print "Unknown character 0x%02x." % ct[9];
89             letter=ord('?');
90     if letter!=None:
91         mskbstring="%s%c" % (mskbstring,letter);
92         print "# %s" % mskbstring
93 def printconfig():
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();
101
102
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];
110     print "";
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];
116     print "";
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];
120     print "";
121     print "%s sniffskybrake\n\tSniffs skybrake. [broken?]" % sys.argv[0];
122     print "%s sniffmskb\n\tSniffs MS KB. [broken?]" % sys.argv[0];
123     
124     print "%s hosttp\n\tHosts Turning Point Clicker traffic." % sys.argv[0];
125
126     print "%s carrier [freq]\n\tHolds a carrier on [freq] Hz." % sys.argv[0];
127     sys.exit();
128
129 #Initialize FET and set baud rate
130 client=GoodFETNRF();
131 client.serInit()
132
133 client.NRFsetup();
134
135 if(sys.argv[1]=="info"):
136     printconfig();
137
138 if(sys.argv[1]=="test"):
139     print "Old registers:"
140     printconfig();
141     
142     # Set PWR_UP=1 and PRIM_RX=0 in CONFIG.
143     client.poke(0x00,2);
144     #Delay of 1.5ms by round-trip.
145     
146     print "\n\n";
147     
148     #Try all data rates
149     for foo in [250*10**3,
150                 1*10**6,
151                 2*10**6]:
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());
156     
157     print "\n\n";
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:"
163     printconfig();
164
165 if(sys.argv[1]=="carrier"):
166     if len(sys.argv)>2:
167         client.RF_setfreq(eval(sys.argv[2]));
168     client.RF_carrier();
169     printconfig();
170     print "\nHolding a carrier wave.";
171     while(1):
172         time.sleep(1);
173
174 if(sys.argv[1]=="tune"):
175     if len(sys.argv)>2:
176         client.tune(sys.argv[2]);
177     else:
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]);
185
186 if(sys.argv[1]=="peek"):
187     start=0x0000;
188     if(len(sys.argv)>2):
189         start=int(sys.argv[2],16);
190     stop=start;
191     if(len(sys.argv)>3):
192         stop=int(sys.argv[3],16);
193     print "Peeking from %02x to %02x." % (start,stop);
194     while start<=stop:
195         print "%02x: %010x" % (start,client.peek(start));
196         start=start+1;
197 if(sys.argv[1]=="poke"):
198     start=0x0000;
199     val=0x00;
200     if(len(sys.argv)>2):
201         start=int(sys.argv[2],16);
202     if(len(sys.argv)>3):
203         val=int(sys.argv[3],16);
204     print "Poking %02x to become %010x." % (start,val);
205     
206     client.poke(start,val);
207     print "Poked to %04x" % client.peek(start);
208
209 if(sys.argv[1]=="sniffob"):
210     #Reversal of transmitter code from nRF_CMD.c of OpenBeacon
211     #TODO remove all poke() calls.
212     
213     client.poke(0x00,0x00); #Stop nRF
214     client.poke(0x01,0x00); #Disable Shockburst
215     client.poke(0x02,0x01); #Set RX Pipe 0
216     
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
220     
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);
227     
228     #Set packet length of 16.
229     client.RF_setpacketlen(16);
230     
231     #Power radio, prime for RX, one-byte checksum.
232     client.poke(0x00,0x70|0x03|0x08); #0x08 for one byte, 0x04 for two.
233     
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.
237     while 1:
238         packet=None;
239         while packet==None:
240             #time.sleep(0.1);
241             packet=client.RF_rxpacket();
242         printpacket(packet);
243         sys.stdout.flush();
244
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):
249         old=client.peek(r);
250         #Which bits can be set?
251         client.poke(r,0xFF);
252         ones=client.peek(r);
253         #Which bits can be clear?
254         client.poke(r,0x00);
255         zeroes=client.peek(r);
256         regbits[r]=(ones & (~zeroes));
257     for r in range(0,0x30):
258         if regbits[r]!=0:
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.
263     
264     client.poke(0x00,0x00); #Stop nRF
265     client.poke(0x01,0x00); #Disable Shockburst
266     client.poke(0x02,0x01); #Set RX Pipe 0
267     
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
271     
272     #OpenBeacon defines these in little endian as follows.
273     client.RF_setmaclen(2); # SETUP_AW for shortest
274     
275     #It's better to have a known fragment, when one is available.
276     #client.RF_setsmac(0x00AA);
277     #client.RF_setsmac(0x0055);
278     
279     #Should end in 55 or AA depending upon the packet.
280     tail=0x55
281     if(len(sys.argv)>2):
282         tail=int(sys.argv[2],16);
283     else:
284         print "Please specify a tail of 0xAA or 0x55.";
285         sys.exit(1);
286     client.RF_setsmac(tail);
287     
288     #Longest length.
289     client.RF_setpacketlen(32);
290     
291     #Power radio, prime for RX, no checksum
292     client.poke(0x00,0x70|0x03); #0x08 for checksum, 0x04 for two.
293     
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.
297     while 1:
298         packet=None;
299         while packet==None:
300             #time.sleep(0.1);
301             packet=client.RF_rxpacket();
302         printpacket(packet);
303         sys.stdout.flush();
304
305 class AutoTuner():
306     """This guesses addresses by searching through packets."""
307     addresses={};
308     client=None;
309     
310     #Limits on search space, because you usually know what you're looking for.
311     rate=False;
312     chan=False;
313     sync=False;
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."""
318         self.client=goodfet;
319         self.rate=rate;
320         self.chan=chan;
321         self.sync=sync;
322         
323         client.poke(0x00,0x00); #Stop nRF
324         client.poke(0x01,0x00); #Disable Shockburst
325         client.poke(0x02,0x01); #Set RX Pipe 0
326         
327         #Disable shockburst.
328         client.poke(0x1C,0x00);
329         client.poke(0x1D,0x00);
330         
331         client.RF_setmaclen(2); # SETUP_AW for shortest
332         
333         #historic
334         #client.RF_setsmac(0x00AA);
335         #client.RF_setsmac(0x0055);
336         
337         client.poke(0x00,0x70|0x03); #prime radio.
338         
339         return;
340     def packetaddr(self,packet,justmac=False):
341         """Returns a loaded packet address, including channel and rate."""
342         
343         sync=self.client.RF_getsmac()&0xFF;
344         
345         mac="";
346         #MAC,RF_CH,RATE
347         for i in range(0,5):
348             mac="%s%02x" % (mac,ord(packet[i]));
349         if justmac:
350             return mac;
351         ch=self.client.peek(0x05);
352         rate=self.client.peek(0x06);
353         return "%02x,%s,%02x,%02x" % (
354             sync,mac,ch,rate);
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.
361             return False;
362         if mac=='5555555555' or mac=='aaaaaaaaaa' or mac=='0000000000':
363             return False;
364         return True;
365         
366     def handle(self,packet):
367         """Handles a packet."""
368         #printpacket(packet);
369         
370         if not self.validmac(packet):
371             #print "Dropped packet from %s" % self.packetaddr(packet,justmac=True);
372             #printpacket(packet);
373             return;
374         
375         addr=self.packetaddr(packet);
376         
377         #Increment the address count.
378         count=0;
379         try:
380             count=self.addresses[addr];
381         except:
382             pass;
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" % (
387                 addr,count,rate);
388         return addr;
389     tunecount=0;
390     def selftune(self,threshold=2,forever=False,
391                  delay=5.0):
392         """Tunes to the first strong signal.
393         It's important that this not get triggered by false positives."""
394         
395         while 1:
396             self.retune();
397             start=time.mktime(time.localtime());
398             sys.stdout.flush();
399             while (time.mktime(time.localtime())-start) < delay:
400                 packet=None;
401                 while packet==None:
402                     packet=client.RF_rxpacket();
403                 addr=guesser.handle(packet);
404                 try:
405                     count=self.addresses[addr];
406                 except:
407                     count=0;
408                 if count>threshold and forever==False:
409                     #Tune it in here?
410                     client.tune(addr);
411                     return addr;
412             
413         
414     def retune(self):
415         """Tunes to another channel or preamble looking for the next packet."""
416         count=self.tunecount;
417         self.tunecount=count+1;
418         
419         #Swap the SYNC value most often.
420         if self.sync:
421             sync=0x00AA;
422             if count&1:
423                 sync=0x0055;
424             self.client.RF_setsmac(sync);
425             count=(count>>1);
426         
427         if self.rate:
428             #Then the data rate.
429             rate=0;
430             
431             #This swaps between 1Mbps and 2Mbps.
432             #TODO add support for 256kbps, if anyone uses it.
433             if count&1:
434                 rate=rate|0x08;
435             #print "Setting rate to 0x%02x" % rate;
436             if(rate==0x20):
437                 rate=0x08;
438             self.client.poke(0x06,rate);
439             count=(count>>1);
440         
441         if self.chan:
442             self.client.poke(0x05,
443                              (count+self.startch)&0x7f);
444             print "Tuned to %i MHz" % (
445                 self.client.RF_getfreq()
446                 /(10**6));
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();
451         return;
452         
453         
454 if(sys.argv[1]=="autotune"):
455     #Reversal of transmitter code from nRF_CMD.c of OpenBeacon
456     #TODO remove all poke() calls.
457     guesser=AutoTuner();
458     guesser.init(client,rate=True,sync=True,chan=True);
459     
460     
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
464     
465     #This is determined by the MAC, which we don't yet know.
466     
467     #Longest length.
468     client.RF_setpacketlen(32);
469     
470     #Power radio, prime for RX, no checksum
471     client.poke(0x00,0x70|0x03); #0x08 for checksum, 0x04 for two.
472     
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,
478                      forever=True);
479
480 if(sys.argv[1]=="sniffmacs"):
481     #Reversal of transmitter code from nRF_CMD.c of OpenBeacon
482     #TODO remove all poke() calls.
483     guesser=AutoTuner();
484     guesser.init(client,rate=False,sync=True,chan=False);
485     
486     #Longest length.
487     client.RF_setpacketlen(32);
488     
489     #Power radio, prime for RX, no checksum
490     client.poke(0x00,0x70|0x03); #0x08 for checksum, 0x04 for two.
491     
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,
497                      forever=True);
498
499 if(sys.argv[1]=="sniffmskb"):
500     #MSWK 3000 v2.0
501     #TODO remove all poke() calls.
502     
503     client.poke(0x00,0x00); #Stop nRF
504     client.poke(0x01,0x00); #Disable Shockburst
505     client.poke(0x02,0x01); #Set RX Pipe 0
506     
507     client.poke(0x06,0x09); #2MBps, -18dBm in RF_SETUP
508     client.poke(0x07,0x78); #Reset status register
509     
510     #This is the address of a specific keyboard.
511     #Other keyboards will be different.
512     
513     client.RF_setmaclen(5);
514     
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);
518     
519     #client.RF_setfreq((2400+0x15) * 10**6);
520     #client.RF_setsmac(0xc10446facd);
521     
522     #Mac packet length, illegally 0-length address field.
523     client.RF_setpacketlen(16);
524     
525     #aa,c00a3598cd,13,09
526     if len(sys.argv)>2:
527         client.tune(sys.argv[2]);
528     else:
529         
530         print "Searching for a keyboard.";
531         
532         guesser=AutoTuner();
533         guesser.init(client, rate=False, sync=True, chan=True);
534         guesser.selftune(threshold=4,forever=False,
535                          delay=10.0);
536     
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);
541     
542     #Finally, dynamic payload lengths need to be enabled.
543     #client.poke(0x01,0x01);
544     client.poke(0x1C,0x01);
545     client.poke(0x1D,0x06);
546     
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.
551     while 1:
552         packet=None;
553         while packet==None:
554             #time.sleep(1);
555             packet=client.RF_rxpacket();
556             #print ".";
557         printmspacket(packet);
558         sys.stdout.flush();
559
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.
564     
565     #Might be more effective to sniff knowing the MFG ID and Dev. ID,
566     #as these predict a lot of the MAC address.
567     
568     client.poke(0x00,0x00); #Stop nRF
569     client.poke(0x01,0x00); #Disable Shockburst
570     client.poke(0x02,0x01); #Set RX Pipe 0
571     
572     client.poke(0x05,57); #broadcast-only channel
573     client.poke(0x06,0x00); #1MBps
574     client.poke(0x07,0x78); #Reset status register
575     
576     #Is this appropriate?  Might be 3.
577     client.RF_setmaclen(5);
578     
579     
580     #Mac packet length, illegally 0-length address field.
581     client.RF_setpacketlen(16);
582     
583     if len(sys.argv)>2:
584         client.tune(sys.argv[2]);
585     else:
586         
587         print "Searching for ANT+.";
588         
589         guesser=AutoTuner();
590         guesser.init(client, rate=False, sync=True, chan=True);
591         guesser.selftune(threshold=2,forever=False,
592                          delay=9.0);
593     
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);
598     
599     
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.
604     while 1:
605         packet=None;
606         while packet==None:
607             #time.sleep(1);
608             packet=client.RF_rxpacket();
609             #print ".";
610         printpacket(packet);
611         sys.stdout.flush();
612
613
614
615 if(sys.argv[1]=="sniffskybrake"):
616     #Reversal of transmitter code from nRF_CMD.c of OpenBeacon
617     #TODO remove all poke() calls.
618     
619     client.poke(0x00,0x00); #Stop nRF
620     client.poke(0x01,0x00); #Disable Shockburst
621     client.poke(0x02,0x01); #Set RX Pipe 0
622     
623     client.RF_setfreq(2439 * 10**6);
624     client.poke(0x06,0x00); #1MBps
625     client.poke(0x07,0x78); #Reset status register
626     
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
630     
631     client.RF_setsmac(0x070700d2c4); #reversed
632     
633     #client.RF_setsmac(0xd2c4);
634     #client.RF_setsmac(0);
635     
636     #Mac packet length, illegally 0-length address field.
637     client.RF_setpacketlen(32);
638     
639     #Power radio, prime for RX, one-byte checksum.
640     client.poke(0x00,0x70|0x03); #0x08 for one byte, 0x04 for two.
641     
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.
646     while 1:
647         packet=None;
648         while packet==None:
649             #time.sleep(0.1);
650             packet=client.RF_rxpacket();
651         printpacket(packet);
652         sys.stdout.flush();
653
654 if(sys.argv[1]=="sniffsf"):
655     #Reversal of transmitter code from nRF_CMD.c of OpenBeacon
656     #TODO remove all poke() calls.
657     
658     client.poke(0x00,0x00); #Stop nRF
659     client.poke(0x01,0x00); #Disable Shockburst
660     client.poke(0x02,0x01); #Set RX Pipe 0
661     
662     client.RF_setfreq(2402 * 10**6);
663     client.poke(0x06,0x07); #1Mbps
664     client.poke(0x07,0x78); #Reset status register
665     
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);
670     
671     #Set packet length of 16.
672     client.RF_setpacketlen(4);
673     
674     #Power radio, prime for RX, one-byte checksum.
675     client.poke(0x00,0x70|0x03|0x08); #0x08 for one byte, 0x04 for two.
676     
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.
680     while 1:
681         packet=None;
682         while packet==None:
683             #time.sleep(0.1);
684             packet=client.RF_rxpacket();
685         printpacket(packet);
686         sys.stdout.flush();
687
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
692     
693     #Disable shockburst.
694     client.poke(0x1C,0x00);
695     client.poke(0x1D,0x00);
696     
697     client.RF_setfreq((2400+0x29) * 10**6);
698     client.poke(0x06,0x00); #1Mbps
699     client.poke(0x07,0x78); #Reset status register
700     
701     client.RF_setmaclen(3); # SETUP_AW for 3-byte addresses.
702     client.RF_setsmac(0x123456);
703     client.RF_setpacketlen(4);
704     
705     #Power radio, prime for RX, two-byte checksum.
706     client.poke(0x00,0x70|0x03|0x04|0x08);
707     
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.
711     while 1:
712         packet=None;
713         while packet==None:
714             #time.sleep(0.1);
715             packet=client.RF_rxpacket();
716         printpacket(packet);
717         sys.stdout.flush();
718
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
723     
724     chan=0x29;
725
726     client.RF_setfreq((2400+chan) * 10**6);
727     client.poke(0x06,0x00); #1Mbps
728     client.poke(0x07,0x78); #Reset status register
729     
730     client.RF_setmaclen(3); # SETUP_AW for 3-byte addresses.
731     client.RF_setsmac(0x123456);
732     client.RF_setpacketlen(4);
733     
734     #Power radio, prime for RX, two-byte checksum.
735     client.poke(0x00,0x70|0x03|0x04|0x08);
736     
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.
740     while 1:
741         packet=None;
742         while packet==None:
743             packet=client.RF_rxpacket();
744         mac=((ord(packet[0])<<16)+
745              (ord(packet[1])<<8)+
746              ord(packet[2]));
747         key=packet[3];
748         print "%c from %06x" % (key,mac);
749         sys.stdout.flush();
750
751 if(sys.argv[1]=="sniff"):
752     if len(sys.argv)>2:
753         print "Set MAC to %s" % sys.argv[2];
754         client.tune(sys.argv[2]);
755         client.RF_setmaclen(5);
756         
757     #client.poke(0x00,0x00); #Stop nRF
758     client.poke(0x07,0x78); #Reset status register
759     
760     #Power radio, prime for RX, no checksum.
761     client.poke(0x00,0x70|0x03);
762     #Mac packet length.
763     client.RF_setpacketlen(32);
764     #Mac length, reduced
765     #client.RF_setmaclen(3); # SETUP_AW for shortest
766     
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.
770     
771     while 1:
772         packet=None;
773         while packet==None:
774             #time.sleep(0.1);
775             packet=client.RF_rxpacket();
776         printpacket(packet);
777         sys.stdout.flush();
778 if(sys.argv[1]=="explore"):
779     #client.poke(0x00,0x00); #Stop nRF
780     client.poke(0x07,0x78); #Reset status register
781     
782     #Power radio, prime for RX, no checksum.
783     client.poke(0x00,0x70|0x03);
784     
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
789     
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);
795             time.sleep(1);
796             packet=client.RF_rxpacket();
797             if packet!=None:
798                 print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
799                                                         client.RF_getfreq()/10**6);
800                 printpacket(packet);
801                 sys.stdout.flush();