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 sniff [chan]" % sys.argv[0];
27 print "%s bsniff [chan]" % sys.argv[0];
28 print "%s sniffdissect" % sys.argv[0];
30 print "\n%s txtoscount [-i|-r] TinyOS BlinkToLED" % sys.argv[0];
31 print "%s reflexjam [channel=11] [delay=0]" % sys.argv[0];
35 #Initialize FET and set baud rate
36 client=GoodFETCCSPI();
42 #Might read as all ones if chip has a startup delay.
44 if(sys.argv[1]=="carrier"):
46 client.RF_setfreq(eval(sys.argv[2]));
52 if(sys.argv[1]=="modulated_spectrum"):
54 client.RF_setfreq(eval(sys.argv[2]));
56 client.RF_modulated_spectrum();
60 if(sys.argv[1]=="reflexjam" or sys.argv[1]=="reflexjamack"):
61 #Setup the radio to listen promiscously on a frequency
62 client.RF_promiscuity(1);
65 freq=eval(sys.argv[2]);
67 client.RF_setfreq(freq);
69 client.RF_setchan(freq);
72 duration=eval(sys.argv[3]);
74 print "Reflexively jamming on %i MHz" % (client.RF_getfreq()/10**6);
75 #Now we let the firmware take over, watching for packets and jamming them.
76 #Standard reflexive jam is done with duration=0.
77 #To selectively jam packets that are above a certain length, set duration
78 # to the number of milliseconds needed to jam frames of that length.
79 # Api-Do project has script available to tune/test this duration.
80 # code.google.com/p/zigbeesecurity (rmspeers)
81 if sys.argv[1]=="reflexjam":
82 client.RF_reflexjam(duration);
83 elif sys.argv[1]=="reflexjamack":
84 client.RF_reflexjam_autoack();
86 if(sys.argv[1]=="info"):
87 print "Found %s" % client.identstr();
88 print "Freq: %05f MHz" % (client.RF_getfreq()/(10**6));
89 print "Status: %s" % client.status();
90 if(sys.argv[1]=="regs"):
91 for adr in range(0x10,0x40): #*1024):
93 print "%04x:=0x%04x" % (adr,val);
94 if(sys.argv[1]=="test"):
95 data=client.trans([0x20, 0xde, 0xad]);
96 print "%02x %02x" % (ord(data[1]), ord(data[2]));
97 data=client.trans([0x40|0x20, 0xde, 0xad]);
98 print "%02x %02x" % (ord(data[1]), ord(data[2]));
99 if(sys.argv[1]=="rssi"):
101 freq=eval(sys.argv[2]);
103 client.RF_setfreq(freq);
105 client.RF_setchan(freq);
106 print "Listening on %f MHz." % (client.RF_getfreq()/10.0**6);
108 client.strobe(0x02); #Calibrate
113 #client.strobe(0x03); #SRXON
114 rssi=client.RF_getrssi();
115 #client.CC_RFST_IDLE(); #idle
118 for foo in range(0,rssi>>2):
119 string=("%s."%string);
120 print "%02x %04i %s" % (rssi,rssi, string);
122 if(sys.argv[1]=="sniff" or sys.argv[1]=="sniffdissect"):
124 client.RF_promiscuity(1);
125 client.RF_autocrc(0);
128 freq=eval(sys.argv[2]);
130 client.RF_setfreq(freq);
132 client.RF_setchan(freq);
134 print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
135 client.RF_getfreq()/10**6);
136 #Now we're ready to get packets.
140 packet=client.RF_rxpacket();
141 if sys.argv[1]=="sniffdissect":
142 client.printdissect(packet);
144 client.printpacket(packet);
147 if(sys.argv[1]=="bsniff"):
149 client.RF_promiscuity(0);
150 client.RF_setsmac(0xFFFFFFFF);
151 client.RF_autocrc(1);
154 freq=eval(sys.argv[2]);
156 client.RF_setfreq(freq);
158 client.RF_setchan(freq);
160 print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
161 client.RF_getfreq()/10**6);
162 #Now we're ready to get packets.
166 packet=client.RF_rxpacket();
167 client.printpacket(packet);
170 if(sys.argv[1]=="txtest"):
172 freq=eval(sys.argv[2]);
174 client.RF_setfreq(freq);
176 client.RF_setchan(freq);
177 print "Transmitting DEADBEEF as %010x on %i MHz" % (
179 client.RF_getfreq()/10**6);
182 client.RF_txpacket([0x0f, 0x01, 0x08, 0x82,
183 0xff, 0xff, 0xff, 0xff,
184 0xde, 0xad, 0xbe, 0xef,
187 if(sys.argv[1]=="txtoscount"):
189 Clone of what TinyOS's RadioCountToLeds demo code does. Specify a
190 channel a TinyOS mote programmed with RadioCountToLeds is on, and
191 this will act as the second device. (ryan@rmspeers.com)
193 if (len(sys.argv)<=3):
194 print "Provide -r to work via replays or -i to work via incrementing itself.";
196 if (sys.argv[3]=="-r"):
197 client.RF_promiscuity(1);
198 client.RF_autocrc(1);
200 freq=eval(sys.argv[2]);
202 client.RF_setfreq(freq);
204 client.RF_setchan(freq);
205 if (sys.argv[3]=="-r"):
207 print "Listening as %010x on %i MHz" % (client.RF_getsmac(), client.RF_getfreq()/10**6);
208 print "Transmitting like the TinyOS CountToRadio program on %i MHz" % (client.RF_getfreq()/10**6);
209 if (sys.argv[3]=="-i"):
211 countpkt = [0x0f, 0x41, 0x88, 0xFF, 0x22, 0x00, 0xff, 0xff, 0x01, 0x00, 0x3f, 0x06, 0x00, 0xFF];
213 if (sys.argv[3]=="-r"): #give -r to do via replays from the other device
216 packet=client.RF_rxpacket();
218 client.RF_txpacket(pkt);
219 elif (sys.argv[3]=="-i"): #give -i to have it increment and send
220 #Use this code for it to actually do increments itself:
224 client.RF_txpacket(pkt);
229 if(sys.argv[1]=="txpiptest" or sys.argv[1]=="txpipscapy"):
231 freq=eval(sys.argv[2]);
233 client.RF_setfreq(freq);
235 client.RF_setchan(freq);
236 print "Transmitting on as %010x on %i MHz" % (
238 client.RF_getfreq()/10**6);
240 client.RF_setsync(0xFFFF);
243 if(sys.argv[1]=="txpiptest"):
246 #Real header, must begin with SFD.
251 0x1f, 0x01, 0x08, 0x82,
252 0xDF, 0xff, 0xff, 0xff,
253 0xde, 0xad, 0xbe, 0xef,
259 0x00, 0xA7, #CC2420 SFD
261 0x0f, 0x01, 0x08, 0x82,
262 0xff, 0xff, 0xff, 0xff,
263 0xde, 0xad, 0xbe, 0xef,
266 0xff, 0xff, 0xff, 0xff,
267 0xff, 0xff, 0xff, 0xff,
268 0xff, 0xff, 0xff, 0xff,
269 0xff, 0xff, 0xff, 0xff,
270 0xff, 0xff, 0xff, 0xff,
271 0xff, 0xff, 0xff, 0xff,
272 0xff, 0xff, 0xff, 0xff,
274 elif(sys.argv[1]=="txpipscapy"):
275 # NB: Requires Scapy with dot15d4.py layer. (rmspeers)
277 from scapy.all import Dot15d4, Dot15d4FCS, Dot15d4Data, Raw
280 print "To use packet building, Scapy must be installed and have the dot15d4 layer present."
281 print "try: hg clone http://hg.secdev.org/scapy-com";
282 print " sudo ./setup.py install";
283 #Overall method is to build from the inner packet outwards in the pkt string
285 scapyinner = Dot15d4FCS(seqnum=130)/Dot15d4Data()/Raw('\xde\xad\xbe\xef');
286 pkt = str(scapyinner); #build inner pkt to bytes, adding FCS automatically
287 pkt = struct.pack('b', len(pkt)) + pkt #prepend with its length
288 pkt = "\x00\x00\x00\x00\xA7" + pkt #add preamble and SFD to inner packet
289 # Make outer (wrapping) packet
290 scapyouter = Dot15d4(seqnum=130)/Dot15d4Data(dest_panid=0xffdf)/Raw('\xde\xad\xbe\xef\xba\xbe\xc0') #TODO why need these last 3 bytes?
291 pkt = str(scapyouter) + pkt
292 pkt = struct.pack('b', len(pkt)) + pkt #prepend with its length
293 pkt = '\x00\x00\x00\x00\xA7' + pkt + ('\xff'*28) #start with preamble/SFD and add 0xff fill at end
294 pkt = struct.pack('b', len(pkt)) + pkt #prepend with its length (originally used \x7f)
295 client.printpacket(pkt)
296 client.RF_autocrc(1);
297 client.RF_txpacket(pkt)
299 if(sys.argv[1]=="peek"):
302 start=int(sys.argv[2],16);
305 stop=int(sys.argv[3],16);
306 print "Peeking from %04x to %04x." % (start,stop);
308 print "%04x: 0x%04x" % (start,client.peek(start));
310 if(sys.argv[1]=="poke"):
314 start=int(sys.argv[2],16);
316 val=int(sys.argv[3],16);
317 print "Poking r%02x to become 0x%04x." % (start,val);
319 client.poke(start,val);