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