68d402d6f2491a6b8fb184b9100d23cec80adf65
[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         if ct[9]==0:
63             #Key up event, not worth logging.
64             pass;
65         elif ct[9]>=4 and ct[9]<0x1E:
66             letter=ct[9]+ord('A')-4;
67         elif ct[9]>=0x1E and ct[9]<0x27:
68             letter=ct[9]+ord('1')-0x1E;
69         elif ct[9]==0x27:
70             letter=ord('0');
71         elif ct[9]==0x29:
72             #escape
73             letter=ord('e');
74         elif ct[9]==0x2d:
75             letter=ord('-');
76         elif ct[9]==0x2e:
77             letter=ord('=');
78         elif ct[9]==0x35:
79             letter=ord('`');
80         elif ct[9]==0x2C:
81             letter=ord('_');
82         else:
83             print "Unknown character 0x%02x." % ct[9];
84     if letter!=None:
85         mskbstring="%s%c" % (mskbstring,letter);
86         print "# %s" % mskbstring
87 def printconfig():
88     print "Encoding %s" % client.RF_getenc();
89     print "Freq    %10i MHz" % (client.RF_getfreq()/10**6);
90     print "Rate    %10i kbps" % (client.RF_getrate()/1000);
91     print "PacketLen %02i bytes" % client.RF_getpacketlen();
92     #print "MacLen    %2i bytes" % client.RF_getmaclen();
93     print "SMAC  0x%010x" % client.RF_getsmac();
94     print "TMAC  0x%010x" % client.RF_gettmac();
95
96
97 if(len(sys.argv)==1):
98     print "Usage: %s verb [objects]\n" % sys.argv[0];
99     print "%s info" % sys.argv[0];
100     print "%s test" % sys.argv[0];
101     print "%s regs" % sys.argv[0];
102     print "%s regbits" % sys.argv[0];
103     print "%s pyregs" % sys.argv[0];
104     print "";
105     print "%s tune aa|55,mac,r5,r6\n\tTunes to a configuration." % sys.argv[0];
106     print "%s sniff\n\tSniffs packets by current config." % sys.argv[0];
107     print "%s sniffob\n\tSniffs OpenBeacon traffic." % sys.argv[0];
108     print "%s snifftp\n\tSniffs Turning Point Clicker traffic." % sys.argv[0];
109     print "%s sniffsf\n\tSniffs SparkFun Dongle traffic." % sys.argv[0];
110     print "";
111     print "%s sniffmacs \n\tSniffs for MAC addresses on the present channel." % sys.argv[0];
112     print "%s sniffprom [0xaa|0x55]\n\tSniffs promiscuously for a preamble of 0xAA or 0x55" % sys.argv[0];
113     print "%s autotune\n\tSearches for a valid destination address." % sys.argv[0];
114     print "";
115     print "%s sniffskybrake\n\tSniffs skybrake. [broken?]" % sys.argv[0];
116     print "%s sniffmskb\n\tSniffs MS KB. [broken?]" % sys.argv[0];
117     
118     print "%s hosttp\n\tHosts Turning Point Clicker traffic." % sys.argv[0];
119
120     print "%s carrier [freq]\n\tHolds a carrier on [freq] Hz." % sys.argv[0];
121     sys.exit();
122
123 #Initialize FET and set baud rate
124 client=GoodFETNRF();
125 client.serInit()
126
127 client.NRFsetup();
128
129 if(sys.argv[1]=="info"):
130     printconfig();
131
132 if(sys.argv[1]=="test"):
133     print "Old registers:"
134     printconfig();
135     
136     # Set PWR_UP=1 and PRIM_RX=0 in CONFIG.
137     client.poke(0x00,2);
138     #Delay of 1.5ms by round-trip.
139     
140     print "\n\n";
141     
142     #Try all data rates
143     for foo in [250*10**3,
144                 1*10**6,
145                 2*10**6]:
146         client.RF_setrate(foo);
147         if(client.RF_getrate()!=foo):
148             print "ERROR Rate %i not supported.  Got %i instead." % (foo,
149                                                                      client.RF_getrate());
150     
151     print "\n\n";
152     client.poke(0x0A,0xDEADBEEF,5);
153     #print "SMAC set to %010x" % client.RF_getsmac();
154     if client.RF_getsmac()!=0xdeadbeef:
155         print "ERROR: Failed to set MAC address.";
156     print "Final registers:"
157     printconfig();
158
159 if(sys.argv[1]=="carrier"):
160     if len(sys.argv)>2:
161         client.RF_setfreq(eval(sys.argv[2]));
162     client.RF_carrier();
163     printconfig();
164     print "\nHolding a carrier wave.";
165     while(1):
166         time.sleep(1);
167
168 if(sys.argv[1]=="tune"):
169     if len(sys.argv)>2:
170         client.tune(sys.argv[2]);
171     else:
172         print "Specify a tuning, such as 'aa,c78c65805e,14,09'";
173 if(sys.argv[1]=="regs"):
174     for r in range(0,0x20):
175         print "r[0x%02x]=0x%010x //%16s " % (r,client.peek(r),regnames[r]);
176 if(sys.argv[1]=="pyregs"):
177     for r in range(0,0x20):
178         print "client.set(0x%02x,0x%010x); #%16s " % (r,client.peek(r),regnames[r]);
179
180 if(sys.argv[1]=="peek"):
181     start=0x0000;
182     if(len(sys.argv)>2):
183         start=int(sys.argv[2],16);
184     stop=start;
185     if(len(sys.argv)>3):
186         stop=int(sys.argv[3],16);
187     print "Peeking from %02x to %02x." % (start,stop);
188     while start<=stop:
189         print "%02x: %010x" % (start,client.peek(start));
190         start=start+1;
191 if(sys.argv[1]=="poke"):
192     start=0x0000;
193     val=0x00;
194     if(len(sys.argv)>2):
195         start=int(sys.argv[2],16);
196     if(len(sys.argv)>3):
197         val=int(sys.argv[3],16);
198     print "Poking %02x to become %010x." % (start,val);
199     
200     client.poke(start,val);
201     print "Poked to %04x" % client.peek(start);
202
203 if(sys.argv[1]=="sniffob"):
204     #Reversal of transmitter code from nRF_CMD.c of OpenBeacon
205     #TODO remove all poke() calls.
206     
207     client.poke(0x00,0x00); #Stop nRF
208     client.poke(0x01,0x00); #Disable Shockburst
209     client.poke(0x02,0x01); #Set RX Pipe 0
210     
211     client.RF_setfreq(2481 * 10**6);
212     client.poke(0x06,0x09); #2MBps, -18dBm in RF_SETUP
213     client.poke(0x07,0x78); #Reset status register
214     
215     #OpenBeacon defines these in little endian as follows.
216     client.RF_setmaclen(5); # SETUP_AW for 5-byte addresses.
217     #0x01, 0x02, 0x03, 0x02, 0x01
218     client.RF_setsmac(0x0102030201);
219     #'O', 'C', 'A', 'E', 'B'
220     client.RF_settmac(0x424541434F);
221     
222     #Set packet length of 16.
223     client.RF_setpacketlen(16);
224     
225     #Power radio, prime for RX, one-byte checksum.
226     client.poke(0x00,0x70|0x03|0x08); #0x08 for one byte, 0x04 for two.
227     
228     print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
229                                            client.RF_getfreq()/10**6);
230     #Now we're ready to get packets.
231     while 1:
232         packet=None;
233         while packet==None:
234             #time.sleep(0.1);
235             packet=client.RF_rxpacket();
236         printpacket(packet);
237         sys.stdout.flush();
238
239 if(sys.argv[1]=="regbits"):
240     print "Scanning registers to determine which bits are valid."
241     regbits=range(0,0x30);
242     for r in range(0,0x30):
243         old=client.peek(r);
244         #Which bits can be set?
245         client.poke(r,0xFF);
246         ones=client.peek(r);
247         #Which bits can be clear?
248         client.poke(r,0x00);
249         zeroes=client.peek(r);
250         regbits[r]=(ones & (~zeroes));
251     for r in range(0,0x30):
252         if regbits[r]!=0:
253             print "r[0x%02x] masked %02x // %s" % (r,regbits[r], regnames[r]);
254 if(sys.argv[1]=="sniffprom"):
255     #Reversal of transmitter code from nRF_CMD.c of OpenBeacon
256     #TODO remove all poke() calls.
257     
258     client.poke(0x00,0x00); #Stop nRF
259     client.poke(0x01,0x00); #Disable Shockburst
260     client.poke(0x02,0x01); #Set RX Pipe 0
261     
262     #client.RF_setfreq(2481 * 10**6);
263     #client.poke(0x06,0x09); #2MBps, -18dBm in RF_SETUP
264     client.poke(0x07,0x78); #Reset status register
265     
266     #OpenBeacon defines these in little endian as follows.
267     client.RF_setmaclen(2); # SETUP_AW for shortest
268     
269     #It's better to have a known fragment, when one is available.
270     #client.RF_setsmac(0x00AA);
271     #client.RF_setsmac(0x0055);
272     
273     #Should end in 55 or AA depending upon the packet.
274     tail=0x55
275     if(len(sys.argv)>2):
276         tail=int(sys.argv[2],16);
277     else:
278         print "Please specify a tail of 0xAA or 0x55.";
279         sys.exit(1);
280     client.RF_setsmac(tail);
281     
282     #Longest length.
283     client.RF_setpacketlen(32);
284     
285     #Power radio, prime for RX, no checksum
286     client.poke(0x00,0x70|0x03); #0x08 for checksum, 0x04 for two.
287     
288     print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
289                                            client.RF_getfreq()/10**6);
290     #Now we're ready to get packets.
291     while 1:
292         packet=None;
293         while packet==None:
294             #time.sleep(0.1);
295             packet=client.RF_rxpacket();
296         printpacket(packet);
297         sys.stdout.flush();
298
299 class AutoTuner():
300     """This guesses addresses by searching through packets."""
301     addresses={};
302     client=None;
303     
304     #Limits on search space, because you usually know what you're looking for.
305     rate=False;
306     chan=False;
307     sync=False;
308     startch=0; #Useful for forcing an early match.
309     def init(self,goodfet,
310              rate=True,chan=True,sync=True):
311         """Initializes a link to the GoodFET for autotuning."""
312         self.client=goodfet;
313         self.rate=rate;
314         self.chan=chan;
315         self.sync=sync;
316         
317         client.poke(0x00,0x00); #Stop nRF
318         client.poke(0x01,0x00); #Disable Shockburst
319         client.poke(0x02,0x01); #Set RX Pipe 0
320         
321         #Disable shockburst.
322         client.poke(0x1C,0x00);
323         client.poke(0x1D,0x00);
324         
325         client.RF_setmaclen(2); # SETUP_AW for shortest
326         
327         #historic
328         #client.RF_setsmac(0x00AA);
329         #client.RF_setsmac(0x0055);
330         
331         client.poke(0x00,0x70|0x03); #prime radio.
332         
333         return;
334     def packetaddr(self,packet,justmac=False):
335         """Returns a loaded packet address, including channel and rate."""
336         
337         sync=self.client.RF_getsmac()&0xFF;
338         
339         mac="";
340         #MAC,RF_CH,RATE
341         for i in range(0,5):
342             mac="%s%02x" % (mac,ord(packet[i]));
343         if justmac:
344             return mac;
345         ch=self.client.peek(0x05);
346         rate=self.client.peek(0x06);
347         return "%02x,%s,%02x,%02x" % (
348             sync,mac,ch,rate);
349     def validmac(self,packet):
350         sync=self.client.RF_getsmac()&0xFF;
351         mac=self.packetaddr(packet,justmac=True);
352         if (ord(packet[0])&0x80)^(sync&0x80):
353             #print "%02x%02x invalid entry." % (sync,ord(packet[0]));
354             #This is a special kind of failure.  Freq is probably right, but MAC is wrong.
355             return False;
356         if mac=='5555555555' or mac=='aaaaaaaaaa' or mac=='0000000000':
357             return False;
358         return True;
359         
360     def handle(self,packet):
361         """Handles a packet."""
362         #printpacket(packet);
363         
364         if not self.validmac(packet):
365             #print "Dropped packet from %s" % self.packetaddr(packet,justmac=True);
366             #printpacket(packet);
367             return;
368         
369         addr=self.packetaddr(packet);
370         
371         #Increment the address count.
372         count=0;
373         try:
374             count=self.addresses[addr];
375         except:
376             pass;
377         self.addresses[addr]=count+1;
378         rate=count*1.0/len(self.addresses);
379         if self.addresses[addr]>1 or rate>0.01:
380             print "'%s' looks valid\t%i\t%0.5f" % (
381                 addr,count,rate);
382         return addr;
383     tunecount=0;
384     def selftune(self,threshold=2,forever=False,
385                  delay=5.0):
386         """Tunes to the first strong signal.
387         It's important that this not get triggered by false positives."""
388         
389         while 1:
390             self.retune();
391             start=time.mktime(time.localtime());
392             sys.stdout.flush();
393             while (time.mktime(time.localtime())-start) < delay:
394                 packet=None;
395                 while packet==None:
396                     packet=client.RF_rxpacket();
397                 addr=guesser.handle(packet);
398                 try:
399                     count=self.addresses[addr];
400                 except:
401                     count=0;
402                 if count>threshold and forever==False:
403                     #Tune it in here?
404                     client.tune(addr);
405                     return addr;
406             
407         
408     def retune(self):
409         """Tunes to another channel or preamble looking for the next packet."""
410         count=self.tunecount;
411         self.tunecount=count+1;
412         
413         #Swap the SYNC value most often.
414         if self.sync:
415             sync=0x00AA;
416             if count&1:
417                 sync=0x0055;
418             self.client.RF_setsmac(sync);
419             count=(count>>1);
420         
421         if self.rate:
422             #Then the data rate.
423             rate=0;
424             
425             #This swaps between 1Mbps and 2Mbps.
426             #TODO add support for 256kbps, if anyone uses it.
427             if count&1:
428                 rate=rate|0x08;
429             #print "Setting rate to 0x%02x" % rate;
430             if(rate==0x20):
431                 rate=0x08;
432             self.client.poke(0x06,rate);
433             count=(count>>1);
434         
435         if self.chan:
436             self.client.poke(0x05,
437                              (count+self.startch)&0x7f);
438             print "Tuned to %i MHz" % (
439                 self.client.RF_getfreq()
440                 /(10**6));
441         #Grab two packets to clear buffers.
442         #Should retune only after a few packets to reduce this delay.
443         packet=client.RF_rxpacket();
444         packet=client.RF_rxpacket();
445         return;
446         
447         
448 if(sys.argv[1]=="autotune"):
449     #Reversal of transmitter code from nRF_CMD.c of OpenBeacon
450     #TODO remove all poke() calls.
451     guesser=AutoTuner();
452     guesser.init(client,rate=True,sync=True,chan=True);
453     
454     
455     #client.RF_setfreq(2481 * 10**6);
456     client.poke(0x06,0x09); #2MBps, -18dBm in RF_SETUP
457     client.poke(0x07,0x78); #Reset status register
458     
459     #This is determined by the MAC, which we don't yet know.
460     
461     #Longest length.
462     client.RF_setpacketlen(32);
463     
464     #Power radio, prime for RX, no checksum
465     client.poke(0x00,0x70|0x03); #0x08 for checksum, 0x04 for two.
466     
467     print "Autotuning on %i MHz" % (
468         client.RF_getfreq()/10**6);
469     print "sync,mac,r5,r6";
470     #Now we're ready to get packets.
471     guesser.selftune(threshold=2,
472                      forever=True);
473
474 if(sys.argv[1]=="sniffmacs"):
475     #Reversal of transmitter code from nRF_CMD.c of OpenBeacon
476     #TODO remove all poke() calls.
477     guesser=AutoTuner();
478     guesser.init(client,rate=False,sync=True,chan=False);
479     
480     #Longest length.
481     client.RF_setpacketlen(32);
482     
483     #Power radio, prime for RX, no checksum
484     client.poke(0x00,0x70|0x03); #0x08 for checksum, 0x04 for two.
485     
486     print "Holding autotune on %i MHz" % (
487         client.RF_getfreq()/10**6);
488     print "sync,mac,r5,r6";
489     #Now we're ready to get packets.
490     guesser.selftune(threshold=2,
491                      forever=True);
492
493 if(sys.argv[1]=="sniffmskb"):
494     #MSWK 3000 v2.0
495     #TODO remove all poke() calls.
496     
497     client.poke(0x00,0x00); #Stop nRF
498     client.poke(0x01,0x00); #Disable Shockburst
499     client.poke(0x02,0x01); #Set RX Pipe 0
500     
501     client.poke(0x06,0x09); #2MBps, -18dBm in RF_SETUP
502     client.poke(0x07,0x78); #Reset status register
503     
504     #This is the address of a specific keyboard.
505     #Other keyboards will be different.
506     
507     client.RF_setmaclen(5);
508     
509     #Known pairs.  The channel and the low address bytes must match.
510     #client.RF_setfreq((2400+0x13) * 10**6);
511     #client.RF_setsmac(0xc00a3598cd);
512     
513     #client.RF_setfreq((2400+0x15) * 10**6);
514     #client.RF_setsmac(0xc10446facd);
515     
516     #Mac packet length, illegally 0-length address field.
517     client.RF_setpacketlen(16);
518     
519     #aa,c00a3598cd,13,09
520     if len(sys.argv)>2:
521         client.tune(sys.argv[2]);
522     else:
523         
524         print "Searching for a keyboard.";
525         
526         guesser=AutoTuner();
527         guesser.init(client, rate=False, sync=True, chan=True);
528         guesser.selftune(threshold=4,forever=False,
529                          delay=10.0);
530     
531     client.poke(0x00,0x00); #Stop nRF
532     client.poke(0x01,0x00); #Disable Shockburst
533     client.poke(0x02,0x01); #Set RX Pipe 0
534     client.RF_setmaclen(5);
535     
536     #Finally, dynamic payload lengths need to be enabled.
537     #client.poke(0x01,0x01);
538     client.poke(0x1C,0x01);
539     client.poke(0x1D,0x06);
540     
541     client.poke(0x00,0x70|0x03); #prime radio.
542     print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
543                                            client.RF_getfreq()/10**6);
544     #Now we're ready to get packets.
545     while 1:
546         packet=None;
547         while packet==None:
548             #time.sleep(1);
549             packet=client.RF_rxpacket();
550             #print ".";
551         printmspacket(packet);
552         sys.stdout.flush();
553
554 if(sys.argv[1]=="sniffant"):
555     #Prototyped on Garmin device.
556     #Channel hopping is pretty damned fast, hard to follow.
557     #This doesn't really work yet, still experimenting.
558     
559     #Might be more effective to sniff knowing the MFG ID and Dev. ID,
560     #as these predict a lot of the MAC address.
561     
562     client.poke(0x00,0x00); #Stop nRF
563     client.poke(0x01,0x00); #Disable Shockburst
564     client.poke(0x02,0x01); #Set RX Pipe 0
565     
566     client.poke(0x05,57); #broadcast-only channel
567     client.poke(0x06,0x00); #1MBps
568     client.poke(0x07,0x78); #Reset status register
569     
570     #Is this appropriate?  Might be 3.
571     client.RF_setmaclen(5);
572     
573     
574     #Mac packet length, illegally 0-length address field.
575     client.RF_setpacketlen(16);
576     
577     if len(sys.argv)>2:
578         client.tune(sys.argv[2]);
579     else:
580         
581         print "Searching for ANT+.";
582         
583         guesser=AutoTuner();
584         guesser.init(client, rate=False, sync=True, chan=True);
585         guesser.selftune(threshold=2,forever=False,
586                          delay=9.0);
587     
588     client.poke(0x00,0x00); #Stop nRF
589     client.poke(0x01,0x00); #Disable Shockburst
590     client.poke(0x02,0x01); #Set RX Pipe 0
591     client.RF_setmaclen(5);
592     
593     
594     client.poke(0x00,0x70|0x03); #prime radio.
595     print "Dumping ANT as %010x on %i MHz" % (client.RF_getsmac(),
596                                               client.RF_getfreq()/10**6);
597     #Now we're ready to get packets.
598     while 1:
599         packet=None;
600         while packet==None:
601             #time.sleep(1);
602             packet=client.RF_rxpacket();
603             #print ".";
604         printpacket(packet);
605         sys.stdout.flush();
606
607
608
609 if(sys.argv[1]=="sniffskybrake"):
610     #Reversal of transmitter code from nRF_CMD.c of OpenBeacon
611     #TODO remove all poke() calls.
612     
613     client.poke(0x00,0x00); #Stop nRF
614     client.poke(0x01,0x00); #Disable Shockburst
615     client.poke(0x02,0x01); #Set RX Pipe 0
616     
617     client.RF_setfreq(2439 * 10**6);
618     client.poke(0x06,0x00); #1MBps
619     client.poke(0x07,0x78); #Reset status register
620     
621     #OpenBeacon defines these in little endian as follows.
622     client.RF_setmaclen(2); # SETUP_AW for 3-byte addresses.
623     #0x01, 0x02, 0x03, 0x02, 0x01
624     
625     client.RF_setsmac(0x070700d2c4); #reversed
626     
627     #client.RF_setsmac(0xd2c4);
628     #client.RF_setsmac(0);
629     
630     #Mac packet length, illegally 0-length address field.
631     client.RF_setpacketlen(32);
632     
633     #Power radio, prime for RX, one-byte checksum.
634     client.poke(0x00,0x70|0x03); #0x08 for one byte, 0x04 for two.
635     
636     print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
637                                            client.RF_getfreq()/10**6);
638     print "%i byte mac match." % client.RF_getmaclen();
639     #Now we're ready to get packets.
640     while 1:
641         packet=None;
642         while packet==None:
643             #time.sleep(0.1);
644             packet=client.RF_rxpacket();
645         printpacket(packet);
646         sys.stdout.flush();
647
648 if(sys.argv[1]=="sniffsf"):
649     #Reversal of transmitter code from nRF_CMD.c of OpenBeacon
650     #TODO remove all poke() calls.
651     
652     client.poke(0x00,0x00); #Stop nRF
653     client.poke(0x01,0x00); #Disable Shockburst
654     client.poke(0x02,0x01); #Set RX Pipe 0
655     
656     client.RF_setfreq(2402 * 10**6);
657     client.poke(0x06,0x07); #1Mbps
658     client.poke(0x07,0x78); #Reset status register
659     
660     #OpenBeacon defines these in little endian as follows.
661     client.RF_setmaclen(5); # SETUP_AW for 5-byte addresses.
662     client.RF_setsmac(0xe7e7e7e7e7);
663     client.RF_settmac(0xe7e7e7e7e7);
664     
665     #Set packet length of 16.
666     client.RF_setpacketlen(4);
667     
668     #Power radio, prime for RX, one-byte checksum.
669     client.poke(0x00,0x70|0x03|0x08); #0x08 for one byte, 0x04 for two.
670     
671     print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
672                                            client.RF_getfreq()/10**6);
673     #Now we're ready to get packets.
674     while 1:
675         packet=None;
676         while packet==None:
677             #time.sleep(0.1);
678             packet=client.RF_rxpacket();
679         printpacket(packet);
680         sys.stdout.flush();
681
682 if(sys.argv[1]=="snifftp"):
683     client.poke(0x00,0x00); #Stop nRF
684     client.poke(0x01,0x00); #Disable Shockburst
685     client.poke(0x02,0x01); #Set RX Pipe 0
686     
687     #Disable shockburst.
688     client.poke(0x1C,0x00);
689     client.poke(0x1D,0x00);
690     
691     client.RF_setfreq((2400+0x29) * 10**6);
692     client.poke(0x06,0x00); #1Mbps
693     client.poke(0x07,0x78); #Reset status register
694     
695     client.RF_setmaclen(3); # SETUP_AW for 3-byte addresses.
696     client.RF_setsmac(0x123456);
697     client.RF_setpacketlen(4);
698     
699     #Power radio, prime for RX, two-byte checksum.
700     client.poke(0x00,0x70|0x03|0x04|0x08);
701     
702     print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
703                                            client.RF_getfreq()/10**6);
704     #Now we're ready to get packets.
705     while 1:
706         packet=None;
707         while packet==None:
708             #time.sleep(0.1);
709             packet=client.RF_rxpacket();
710         printpacket(packet);
711         sys.stdout.flush();
712
713 if(sys.argv[1]=="hosttp"):
714     client.poke(0x00,0x00); #Stop nRF
715     client.poke(0x01,0x00); #Disable Shockburst
716     client.poke(0x02,0x01); #Set RX Pipe 0
717     
718     chan=0x29;
719
720     client.RF_setfreq((2400+chan) * 10**6);
721     client.poke(0x06,0x00); #1Mbps
722     client.poke(0x07,0x78); #Reset status register
723     
724     client.RF_setmaclen(3); # SETUP_AW for 3-byte addresses.
725     client.RF_setsmac(0x123456);
726     client.RF_setpacketlen(4);
727     
728     #Power radio, prime for RX, two-byte checksum.
729     client.poke(0x00,0x70|0x03|0x04|0x08);
730     
731     print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
732                                            client.RF_getfreq()/10**6);
733     #Now we're ready to get packets.
734     while 1:
735         packet=None;
736         while packet==None:
737             packet=client.RF_rxpacket();
738         mac=((ord(packet[0])<<16)+
739              (ord(packet[1])<<8)+
740              ord(packet[2]));
741         key=packet[3];
742         print "%c from %06x" % (key,mac);
743         sys.stdout.flush();
744
745 if(sys.argv[1]=="sniff"):
746     if len(sys.argv)>2:
747         print "Set MAC to %s" % sys.argv[2];
748         client.tune(sys.argv[2]);
749         client.RF_setmaclen(5);
750         
751     #client.poke(0x00,0x00); #Stop nRF
752     client.poke(0x07,0x78); #Reset status register
753     
754     #Power radio, prime for RX, no checksum.
755     client.poke(0x00,0x70|0x03);
756     #Mac packet length.
757     client.RF_setpacketlen(32);
758     #Mac length, reduced
759     #client.RF_setmaclen(3); # SETUP_AW for shortest
760     
761     print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
762                                            client.RF_getfreq()/10**6);
763     #Now we're ready to get packets.
764     
765     while 1:
766         packet=None;
767         while packet==None:
768             #time.sleep(0.1);
769             packet=client.RF_rxpacket();
770         printpacket(packet);
771         sys.stdout.flush();
772 if(sys.argv[1]=="explore"):
773     #client.poke(0x00,0x00); #Stop nRF
774     client.poke(0x07,0x78); #Reset status register
775     
776     #Power radio, prime for RX, no checksum.
777     client.poke(0x00,0x70|0x03);
778     
779     #Set packet length of 32.
780     #Without checksums, extra data will mix in.
781     client.RF_setpacketlen(32);
782     client.RF_setmaclen(3); # shortest address length
783     
784     #Now we're ready to get packets.
785     for smac in [0x0102030201, 0]:
786         client.RF_setsmac(smac);
787         for chan in range(0,0x80):
788             client.RF_setfreq((2400+chan) * 10**6);
789             time.sleep(1);
790             packet=client.RF_rxpacket();
791             if packet!=None:
792                 print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
793                                                         client.RF_getfreq()/10**6);
794                 printpacket(packet);
795                 sys.stdout.flush();