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 test" % sys.argv[0];
21 print "%s peek 0x$start [0x$stop]" % sys.argv[0];
22 print "%s poke 0x$adr 0x$val" % sys.argv[0];
23 print "%s txtest" % sys.argv[0];
25 print "\n%s rssi" % sys.argv[0];
26 print "%s spectrum" % sys.argv[0];
27 print "%s spectrumcsv" % sys.argv[0];
29 print "\n%s surf" % sys.argv[0];
30 print "%s sniff [chan]" % sys.argv[0];
31 print "%s bsniff [chan]" % sys.argv[0];
32 print "%s sniffdissect" % sys.argv[0];
34 print "\n%s txtoscount [-i|-r] TinyOS BlinkToLED" % sys.argv[0];
35 print "%s reflexjam [channel=11] [delay=0]" % sys.argv[0];
39 #Initialize FET and set baud rate
40 client=GoodFETCCSPI();
46 #Might read as all ones if chip has a startup delay.
48 if(sys.argv[1]=="carrier"):
50 client.RF_setfreq(eval(sys.argv[2]));
56 if(sys.argv[1]=="modulated_spectrum"):
58 client.RF_setfreq(eval(sys.argv[2]));
60 client.RF_modulated_spectrum();
64 if(sys.argv[1]=="reflexjam" or sys.argv[1]=="reflexjamack"):
65 #Setup the radio to listen promiscously on a frequency
66 client.RF_promiscuity(1);
69 freq=eval(sys.argv[2]);
71 client.RF_setfreq(freq);
73 client.RF_setchan(freq);
76 duration=eval(sys.argv[3]);
78 print "Reflexively jamming on %i MHz" % (client.RF_getfreq()/10**6);
79 #Now we let the firmware take over, watching for packets and jamming them.
80 #Standard reflexive jam is done with duration=0.
81 #To selectively jam packets that are above a certain length, set duration
82 # to the number of milliseconds needed to jam frames of that length.
83 # Api-Do project has script available to tune/test this duration.
84 # code.google.com/p/zigbeesecurity (rmspeers)
85 if sys.argv[1]=="reflexjam":
86 client.RF_reflexjam(duration);
87 elif sys.argv[1]=="reflexjamack":
88 client.RF_reflexjam_autoack();
90 if(sys.argv[1]=="info"):
91 print "Found %s" % client.identstr();
92 print "Freq: %05f MHz" % (client.RF_getfreq()/(10**6));
93 print "Status: %s" % client.status();
94 if(sys.argv[1]=="regs"):
95 for adr in range(0x10,0x40): #*1024):
97 print "%04x:=0x%04x" % (adr,val);
98 if(sys.argv[1]=="test"):
99 data=client.trans([0x20, 0xde, 0xad]);
100 print "%02x %02x" % (ord(data[1]), ord(data[2]));
101 data=client.trans([0x40|0x20, 0xde, 0xad]);
102 print "%02x %02x" % (ord(data[1]), ord(data[2]));
103 if(sys.argv[1]=="rssi"):
105 freq=eval(sys.argv[2]);
107 client.RF_setfreq(freq);
109 client.RF_setchan(freq);
110 print "Listening on %f MHz." % (client.RF_getfreq()/10.0**6);
112 client.strobe(0x02); #Calibrate
117 #client.strobe(0x03); #SRXON
118 rssi=client.RF_getrssi();
119 #client.CC_RFST_IDLE(); #idle
122 for foo in range(0,rssi>>2):
123 string=("%s."%string);
124 print "%02x %04i %s" % (rssi,rssi, string);
125 if(sys.argv[1]=="spectrum"):
126 for chan in range(2400000000,2480000000,5000000):
127 client.RF_setfreq(chan);
128 #print "Listening on %f MHz." % (client.RF_getfreq()/10.0**6);
130 client.strobe(0x02); #Calibrate
134 for foo in range(1,10):
136 rssi=client.RF_getrssi();
137 maxrssi=max(rssi,maxrssi);
139 for foo in range(50,rssi):
140 string=("%s."%string);
141 print "%04i %i %s" % (client.RF_getfreq()/10.0**6,rssi, string);
142 if(sys.argv[1]=="spectrumcsv"):
145 for freq in range(2400000000,2480000000,1000000):
146 client.RF_setfreq(freq);
148 client.strobe(0x02); #Calibrate
150 rssi=client.RF_getrssi();
152 print "%f %i %3i" % (
154 client.RF_getfreq()/10.0**6,
158 if sys.argv[1]=="surf":
159 print "Scanning channels [11,26].";
162 client.RF_promiscuity(1);
163 client.RF_autocrc(1);
167 chan=eval(sys.argv[2]);
171 #Now we're ready to get packets.
175 client.setup(); #Really oughtn't be necessary, but can't hurt.
176 client.RF_setchan(chan);
179 lasttime=time.time();
180 while packet==None and time.time()-lasttime<0.5:
181 packet=client.RF_rxpacket();
183 client.printpacket(packet=packet,
184 prefix=("%02d: "%chan));
188 if(sys.argv[1]=="sniff" or sys.argv[1]=="sniffdissect"):
190 client.RF_promiscuity(1);
191 client.RF_autocrc(1);
194 freq=eval(sys.argv[2]);
196 client.RF_setfreq(freq);
198 client.RF_setfreq(freq*1000000);
200 client.RF_setchan(freq);
202 print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
203 client.RF_getfreq()/10**6);
204 #Now we're ready to get packets.
206 client.setup(); #Really oughtn't be necessary, but can't hurt.
211 packet=client.RF_rxpacket();
212 if sys.argv[1]=="sniffdissect":
213 client.printdissect(packet);
215 client.printpacket(packet);
218 if(sys.argv[1]=="bsniff"):
220 client.RF_promiscuity(0);
221 client.RF_setsmac(0xFFFFFFFF);
222 client.RF_autocrc(1);
225 freq=eval(sys.argv[2]);
227 client.RF_setfreq(freq);
229 client.RF_setchan(freq);
231 print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
232 client.RF_getfreq()/10**6);
233 #Now we're ready to get packets.
237 packet=client.RF_rxpacket();
238 client.printpacket(packet);
241 if(sys.argv[1]=="txtest"):
243 freq=eval(sys.argv[2]);
245 client.RF_setfreq(freq);
247 client.RF_setchan(freq);
248 print "Transmitting DEADBEEF as %010x on %i MHz" % (
250 client.RF_getfreq()/10**6);
253 client.RF_txpacket([0x0f, 0x01, 0x08, 0x82,
254 0xff, 0xff, 0xff, 0xff,
255 0xde, 0xad, 0xbe, 0xef,
258 if(sys.argv[1]=="txtoscount"):
260 Clone of what TinyOS's RadioCountToLeds demo code does. Specify a
261 channel a TinyOS mote programmed with RadioCountToLeds is on, and
262 this will act as the second device. (ryan@rmspeers.com)
264 if (len(sys.argv)<=3):
265 print "Provide -r to work via replays or -i to work via incrementing itself.";
267 if (sys.argv[3]=="-r"):
268 client.RF_promiscuity(1);
269 client.RF_autocrc(1);
271 freq=eval(sys.argv[2]);
273 client.RF_setfreq(freq);
275 client.RF_setchan(freq);
276 if (sys.argv[3]=="-r"):
278 print "Listening as %010x on %i MHz" % (client.RF_getsmac(), client.RF_getfreq()/10**6);
279 print "Transmitting like the TinyOS CountToRadio program on %i MHz" % (client.RF_getfreq()/10**6);
280 if (sys.argv[3]=="-i"):
282 countpkt = [0x0f, 0x41, 0x88, 0xFF, 0x22, 0x00, 0xff, 0xff, 0x01, 0x00, 0x3f, 0x06, 0x00, 0xFF];
284 if (sys.argv[3]=="-r"): #give -r to do via replays from the other device
287 packet=client.RF_rxpacket();
289 client.RF_txpacket(pkt);
290 elif (sys.argv[3]=="-i"): #give -i to have it increment and send
291 #Use this code for it to actually do increments itself:
295 client.RF_txpacket(pkt);
300 if(sys.argv[1]=="txpiptest" or sys.argv[1]=="txpipscapy"):
302 freq=eval(sys.argv[2]);
304 client.RF_setfreq(freq);
306 client.RF_setchan(freq);
307 print "Transmitting on as %010x on %i MHz" % (
309 client.RF_getfreq()/10**6);
311 client.RF_setsync(0xFFFF);
314 if(sys.argv[1]=="txpiptest"):
317 #Real header, must begin with SFD.
322 0x1f, 0x01, 0x08, 0x82,
323 0xDF, 0xff, 0xff, 0xff,
324 0xde, 0xad, 0xbe, 0xef,
330 0x00, 0xA7, #CC2420 SFD
332 0x0f, 0x01, 0x08, 0x82,
333 0xff, 0xff, 0xff, 0xff,
334 0xde, 0xad, 0xbe, 0xef,
337 0xff, 0xff, 0xff, 0xff,
338 0xff, 0xff, 0xff, 0xff,
339 0xff, 0xff, 0xff, 0xff,
340 0xff, 0xff, 0xff, 0xff,
341 0xff, 0xff, 0xff, 0xff,
342 0xff, 0xff, 0xff, 0xff,
343 0xff, 0xff, 0xff, 0xff,
345 elif(sys.argv[1]=="txpipscapy"):
346 # NB: Requires Scapy with dot15d4.py layer. (rmspeers)
348 from scapy.all import Dot15d4, Dot15d4FCS, Dot15d4Data, Raw
351 print "To use packet building, Scapy must be installed and have the dot15d4 layer present."
352 print "try: hg clone http://hg.secdev.org/scapy-com";
353 print " sudo ./setup.py install";
354 #Overall method is to build from the inner packet outwards in the pkt string
356 scapyinner = Dot15d4FCS(seqnum=130)/Dot15d4Data()/Raw('\xde\xad\xbe\xef');
357 pkt = str(scapyinner); #build inner pkt to bytes, adding FCS automatically
358 pkt = struct.pack('b', len(pkt)) + pkt #prepend with its length
359 pkt = "\x00\x00\x00\x00\xA7" + pkt #add preamble and SFD to inner packet
360 # Make outer (wrapping) packet
361 scapyouter = Dot15d4(seqnum=130)/Dot15d4Data(dest_panid=0xffdf)/Raw('\xde\xad\xbe\xef\xba\xbe\xc0') #TODO why need these last 3 bytes?
362 pkt = str(scapyouter) + pkt
363 pkt = struct.pack('b', len(pkt)) + pkt #prepend with its length
364 pkt = '\x00\x00\x00\x00\xA7' + pkt + ('\xff'*28) #start with preamble/SFD and add 0xff fill at end
365 pkt = struct.pack('b', len(pkt)) + pkt #prepend with its length (originally used \x7f)
366 client.printpacket(pkt)
367 client.RF_autocrc(1);
368 client.RF_txpacket(pkt)
370 if(sys.argv[1]=="peek"):
373 start=int(sys.argv[2],16);
376 stop=int(sys.argv[3],16);
377 print "Peeking from %04x to %04x." % (start,stop);
379 print "%04x: 0x%04x" % (start,client.peek(start));
381 if(sys.argv[1]=="poke"):
385 start=int(sys.argv[2],16);
387 val=int(sys.argv[3],16);
388 print "Poking r%02x to become 0x%04x." % (start,val);
390 client.poke(start,val);