3 #GoodFET Chipcon SPI Client
4 # (C) 2011 Travis Goodspeed
5 # Additions 2011-2012 Ryan Speers ryan@rmspeers.com
8 #Might be CC2420 Specific
14 from GoodFETCCSPI import GoodFETCCSPI;
17 print "Usage: %s verb [objects]\n" % sys.argv[0];
18 print "%s info" % sys.argv[0];
19 print "%s regs" % sys.argv[0];
20 print "%s ram" % sys.argv[0];
21 print "%s ramtest" % sys.argv[0];
22 print "%s test" % sys.argv[0];
23 print "%s peek 0x$start [0x$stop]" % sys.argv[0];
24 print "%s poke 0x$adr 0x$val" % sys.argv[0];
25 print "%s txtest" % sys.argv[0];
27 print "\n%s rssi" % sys.argv[0];
28 print "%s spectrum" % sys.argv[0];
29 print "%s spectrumcsv" % sys.argv[0];
31 print "\n%s surf" % sys.argv[0];
32 print "%s sniff [chan]" % sys.argv[0];
33 print "%s sniffstrings [chan]" % sys.argv[0];
34 print "%s bsniff [chan]" % sys.argv[0];
35 print "%s sniffcrypt 0x$key [chan]" % sys.argv[0];
36 print "%s sniffdissect" % sys.argv[0];
38 print "\n%s txtoscount [-i|-r] TinyOS BlinkToLED" % sys.argv[0];
39 print "%s reflexjam [channel=11] [delay=0]" % sys.argv[0];
43 #Initialize FET and set baud rate
44 client=GoodFETCCSPI();
50 #Might read as all ones if chip has a startup delay.
52 if(sys.argv[1]=="carrier"):
54 client.RF_setfreq(eval(sys.argv[2]));
60 if(sys.argv[1]=="modulated_spectrum"):
62 client.RF_setfreq(eval(sys.argv[2]));
64 client.RF_modulated_spectrum();
68 if(sys.argv[1]=="reflexjam" or sys.argv[1]=="reflexjamack"):
69 #Setup the radio to listen promiscously on a frequency
70 client.RF_promiscuity(1);
73 freq=eval(sys.argv[2]);
75 client.RF_setfreq(freq);
77 client.RF_setchan(freq);
80 duration=eval(sys.argv[3]);
82 print "Reflexively jamming on %i MHz" % (client.RF_getfreq()/10**6);
83 #Now we let the firmware take over, watching for packets and jamming them.
84 #Standard reflexive jam is done with duration=0.
85 #To selectively jam packets that are above a certain length, set duration
86 # to the number of milliseconds needed to jam frames of that length.
87 # Api-Do project has script available to tune/test this duration.
88 # code.google.com/p/zigbeesecurity (rmspeers)
89 if sys.argv[1]=="reflexjam":
90 client.RF_reflexjam(duration);
91 elif sys.argv[1]=="reflexjamack":
92 client.RF_reflexjam_autoack();
94 if(sys.argv[1]=="info"):
95 print "Found %s" % client.identstr();
96 print "Freq: %05f MHz" % (client.RF_getfreq()/(10**6));
97 print "Status: %s" % client.status();
98 if(sys.argv[1]=="regs"):
99 for adr in range(0x10,0x40): #*1024):
100 val=client.peek(adr);
101 print "%04x:=0x%04x" % (adr,val);
102 if(sys.argv[1]=="ram"):
103 for adr in range(0x0,0x16D,16):
104 row=client.peekram(adr,32);
107 s=s+(" %02x" % ord(foo))
108 print "%04x: %s" % (adr,s);
109 if(sys.argv[1]=="ramtest"):
110 client.pokeram(0x00,[0xde,0xad,0xbe,0xef,
120 0xde,0xad,0xbe,0xef]);
122 for adr in range(0x0,0x16D,16):
123 row=client.peekram(adr,32);
126 s=s+(" %02x" % ord(foo))
127 print "%04x: %s" % (adr,s);
128 if(sys.argv[1]=="test"):
129 data=client.trans([0x20, 0xde, 0xad]);
130 print "%02x %02x" % (ord(data[1]), ord(data[2]));
131 data=client.trans([0x40|0x20, 0xde, 0xad]);
132 print "%02x %02x" % (ord(data[1]), ord(data[2]));
133 if(sys.argv[1]=="rssi"):
135 freq=eval(sys.argv[2]);
137 client.RF_setfreq(freq);
139 client.RF_setchan(freq);
140 print "Listening on %f MHz." % (client.RF_getfreq()/10.0**6);
142 client.strobe(0x02); #Calibrate
147 #client.strobe(0x03); #SRXON
148 rssi=client.RF_getrssi();
149 #client.CC_RFST_IDLE(); #idle
152 for foo in range(0,rssi>>2):
153 string=("%s."%string);
154 print "%02x %04i %s" % (rssi,rssi, string);
155 if(sys.argv[1]=="spectrum"):
156 for chan in range(2400000000,2480000000,5000000):
157 client.RF_setfreq(chan);
158 #print "Listening on %f MHz." % (client.RF_getfreq()/10.0**6);
160 client.strobe(0x02); #Calibrate
164 for foo in range(1,10):
166 rssi=client.RF_getrssi();
167 maxrssi=max(rssi,maxrssi);
169 for foo in range(50,rssi):
170 string=("%s."%string);
171 print "%04i %i %s" % (client.RF_getfreq()/10.0**6,rssi, string);
172 if(sys.argv[1]=="spectrumcsv"):
175 for freq in range(2400000000,2480000000,1000000):
176 client.RF_setfreq(freq);
178 client.strobe(0x02); #Calibrate
180 rssi=client.RF_getrssi();
182 print "%f %i %3i" % (
184 client.RF_getfreq()/10.0**6,
188 if sys.argv[1]=="surf":
189 print "Scanning channels [11,26].";
192 client.RF_promiscuity(1);
193 client.RF_autocrc(1);
197 chan=eval(sys.argv[2]);
201 #Now we're ready to get packets.
205 client.setup(); #Really oughtn't be necessary, but can't hurt.
206 client.RF_setchan(chan);
209 lasttime=time.time();
210 while packet==None and time.time()-lasttime<0.5:
211 packet=client.RF_rxpacket();
213 client.printpacket(packet=packet,
214 prefix=("%02d: "%chan));
218 if(sys.argv[1]=="sniff" or sys.argv[1]=="sniffdissect" or sys.argv[1]=="sniffstrings"):
220 client.RF_promiscuity(1);
221 client.RF_autocrc(1);
224 freq=eval(sys.argv[2]);
226 client.RF_setfreq(freq);
228 client.RF_setfreq(freq*1000000);
230 client.RF_setchan(freq);
232 print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
233 client.RF_getfreq()/10**6);
234 #Now we're ready to get packets.
236 #client.setup(); #Really oughtn't be necessary, but can't hurt.
241 packet=client.RF_rxpacket();
242 if sys.argv[1]=="sniffdissect":
243 client.printdissect(packet);
244 elif sys.argv[1]=="sniffstrings":
247 client.printpacket(packet);
250 if(sys.argv[1]=="bsniff"):
252 client.RF_promiscuity(0);
253 client.RF_setsmac(0xFFFFFFFF);
254 client.RF_autocrc(1);
257 freq=eval(sys.argv[2]);
259 client.RF_setfreq(freq);
261 client.RF_setchan(freq);
263 print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
264 client.RF_getfreq()/10**6);
265 #Now we're ready to get packets.
269 packet=client.RF_rxpacket();
270 client.printpacket(packet);
273 if(sys.argv[1]=="sniffcrypt"):
274 print "Zigbee crypto is pretty damned complicated, and this doesn't work yet.";
276 client.RF_promiscuity(1);
277 client.RF_setsmac(0xFFFFFFFF);
278 client.RF_autocrc(1);
279 #client.poke(0x19, 0x03C7); #SECCTRL0, enabling CCM crypto w/ KEY0
280 client.poke(0x19, 0x03C6); #SECCTRL0, enabling CTRL crypto w/ KEY0
282 #What follows is the nonce.
283 client.poke(0x20, 0x000a); #SECCTRL1, skipping 10 bytes of header
286 key=int(sys.argv[2],16);
287 print "Setting KEY0 to %x" % key;
288 client.RF_setkey(key);
290 freq=eval(sys.argv[3]);
292 client.RF_setfreq(freq);
294 client.RF_setchan(freq);
296 print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
297 client.RF_getfreq()/10**6);
298 #Now we're ready to get packets.
302 packet=client.RF_rxpacketdec();
303 client.printpacket(packet);
306 if(sys.argv[1]=="txtest"):
308 freq=eval(sys.argv[2]);
310 client.RF_setfreq(freq);
312 client.RF_setchan(freq);
313 print "Transmitting DEADBEEF as %010x on %i MHz" % (
315 client.RF_getfreq()/10**6);
318 client.RF_txpacket([0x0f, 0x01, 0x08, 0x82,
319 0xff, 0xff, 0xff, 0xff,
320 0xde, 0xad, 0xbe, 0xef,
323 if(sys.argv[1]=="txtoscount"):
325 Clone of what TinyOS's RadioCountToLeds demo code does. Specify a
326 channel a TinyOS mote programmed with RadioCountToLeds is on, and
327 this will act as the second device. (ryan@rmspeers.com)
329 if (len(sys.argv)<=3):
330 print "Provide -r to work via replays or -i to work via incrementing itself.";
332 if (sys.argv[3]=="-r"):
333 client.RF_promiscuity(1);
334 client.RF_autocrc(1);
336 freq=eval(sys.argv[2]);
338 client.RF_setfreq(freq);
340 client.RF_setchan(freq);
341 if (sys.argv[3]=="-r"):
343 print "Listening as %010x on %i MHz" % (client.RF_getsmac(), client.RF_getfreq()/10**6);
344 print "Transmitting like the TinyOS CountToRadio program on %i MHz" % (client.RF_getfreq()/10**6);
345 if (sys.argv[3]=="-i"):
347 countpkt = [0x0f, 0x41, 0x88, 0xFF, 0x22, 0x00, 0xff, 0xff, 0x01, 0x00, 0x3f, 0x06, 0x00, 0xFF];
349 if (sys.argv[3]=="-r"): #give -r to do via replays from the other device
352 packet=client.RF_rxpacket();
354 client.RF_txpacket(pkt);
355 elif (sys.argv[3]=="-i"): #give -i to have it increment and send
356 #Use this code for it to actually do increments itself:
360 client.RF_txpacket(pkt);
365 if(sys.argv[1]=="txpiptest" or sys.argv[1]=="txpipscapy"):
367 freq=eval(sys.argv[2]);
369 client.RF_setfreq(freq);
371 client.RF_setchan(freq);
372 print "Transmitting on as %010x on %i MHz" % (
374 client.RF_getfreq()/10**6);
376 client.RF_setsync(0xFFFF);
379 if(sys.argv[1]=="txpiptest"):
382 #Real header, must begin with SFD.
387 0x1f, 0x01, 0x08, 0x82,
388 0xDF, 0xff, 0xff, 0xff,
389 0xde, 0xad, 0xbe, 0xef,
395 0x00, 0xA7, #CC2420 SFD
397 0x0f, 0x01, 0x08, 0x82,
398 0xff, 0xff, 0xff, 0xff,
399 0xde, 0xad, 0xbe, 0xef,
402 0xff, 0xff, 0xff, 0xff,
403 0xff, 0xff, 0xff, 0xff,
404 0xff, 0xff, 0xff, 0xff,
405 0xff, 0xff, 0xff, 0xff,
406 0xff, 0xff, 0xff, 0xff,
407 0xff, 0xff, 0xff, 0xff,
408 0xff, 0xff, 0xff, 0xff,
410 elif(sys.argv[1]=="txpipscapy"):
411 # NB: Requires Scapy with dot15d4.py layer. (rmspeers)
413 from scapy.all import Dot15d4, Dot15d4FCS, Dot15d4Data, Raw
416 print "To use packet building, Scapy must be installed and have the dot15d4 layer present."
417 print "try: hg clone http://hg.secdev.org/scapy-com";
418 print " sudo ./setup.py install";
419 #Overall method is to build from the inner packet outwards in the pkt string
421 scapyinner = Dot15d4FCS(seqnum=130)/Dot15d4Data()/Raw('\xde\xad\xbe\xef');
422 pkt = str(scapyinner); #build inner pkt to bytes, adding FCS automatically
423 pkt = struct.pack('b', len(pkt)) + pkt #prepend with its length
424 pkt = "\x00\x00\x00\x00\xA7" + pkt #add preamble and SFD to inner packet
425 # Make outer (wrapping) packet
426 scapyouter = Dot15d4(seqnum=130)/Dot15d4Data(dest_panid=0xffdf)/Raw('\xde\xad\xbe\xef\xba\xbe\xc0') #TODO why need these last 3 bytes?
427 pkt = str(scapyouter) + pkt
428 pkt = struct.pack('b', len(pkt)) + pkt #prepend with its length
429 pkt = '\x00\x00\x00\x00\xA7' + pkt + ('\xff'*28) #start with preamble/SFD and add 0xff fill at end
430 pkt = struct.pack('b', len(pkt)) + pkt #prepend with its length (originally used \x7f)
431 client.printpacket(pkt)
432 client.RF_autocrc(1);
433 client.RF_txpacket(pkt)
435 if(sys.argv[1]=="peek"):
438 start=int(sys.argv[2],16);
441 stop=int(sys.argv[3],16);
442 print "Peeking from %04x to %04x." % (start,stop);
444 print "%04x: 0x%04x" % (start,client.peek(start));
446 if(sys.argv[1]=="poke"):
450 start=int(sys.argv[2],16);
452 val=int(sys.argv[3],16);
453 print "Poking r%02x to become 0x%04x." % (start,val);
455 client.poke(start,val);