f8d10bdf656b99f7a5288fe11eb92e7008c56a78
[goodfet] / client / goodfet.ccspi
1 #!/usr/bin/env python
2
3 #GoodFET Chipcon SPI Client
4 # (C) 2011 Travis Goodspeed
5 # Additions 2011-2012 Ryan Speers ryan@rmspeers.com
6
7 #N.B.,
8 #Might be CC2420 Specific
9
10 import sys;
11 import binascii;
12 import array, time;
13
14 from GoodFETCCSPI import GoodFETCCSPI;
15
16 if(len(sys.argv)==1):
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];
24     
25     print "\n%s rssi" % sys.argv[0];
26     print "%s spectrum" % sys.argv[0];
27     print "%s spectrumcsv" % sys.argv[0];
28     
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];
33     
34     print "\n%s txtoscount [-i|-r]   TinyOS BlinkToLED" % sys.argv[0];
35     print "%s reflexjam [channel=11] [delay=0]" % sys.argv[0];
36
37     sys.exit();
38
39 #Initialize FET and set baud rate
40 client=GoodFETCCSPI();
41 client.serInit()
42
43 client.setup();
44
45 #Dummy read.
46 #Might read as all ones if chip has a startup delay.
47
48 if(sys.argv[1]=="carrier"):
49     if len(sys.argv)>2:
50         client.RF_setfreq(eval(sys.argv[2]));
51     while 1:
52         client.RF_carrier();
53     while(1):
54         time.sleep(1);
55
56 if(sys.argv[1]=="modulated_spectrum"):
57     if len(sys.argv)>2:
58         client.RF_setfreq(eval(sys.argv[2]));
59     while 1:
60         client.RF_modulated_spectrum();
61     while(1):
62         time.sleep(1);
63
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);
67     client.RF_autocrc(0);
68     if len(sys.argv)>2:
69         freq=eval(sys.argv[2]);
70         if freq>100:
71             client.RF_setfreq(freq);
72         else:
73             client.RF_setchan(freq);
74     duration=0;
75     if len(sys.argv)>3:
76         duration=eval(sys.argv[3]);
77     client.CC_RFST_RX();
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();
89
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):
96         val=client.peek(adr);
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"):
104     if len(sys.argv)>2:
105         freq=eval(sys.argv[2]);
106         if freq>100:
107             client.RF_setfreq(freq);
108         else:
109             client.RF_setchan(freq);
110     print "Listening on %f MHz." % (client.RF_getfreq()/10.0**6);
111         
112     client.strobe(0x02); #Calibrate
113     time.sleep(1);
114     
115     while 1:
116         client.CC_RFST_RX();
117         #client.strobe(0x03); #SRXON
118         rssi=client.RF_getrssi();
119         #client.CC_RFST_IDLE(); #idle
120         time.sleep(0.01);
121         string="";
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);
129         
130         client.strobe(0x02); #Calibrate
131         #time.sleep(0.01);
132         
133         maxrssi=0;
134         for foo in range(1,10):
135             client.CC_RFST_RX();
136             rssi=client.RF_getrssi();
137             maxrssi=max(rssi,maxrssi);
138         string="";
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"):
143     start=time.time();
144     while 1:
145         for freq in range(2400000000,2480000000,1000000):
146             client.RF_setfreq(freq);
147             
148             client.strobe(0x02); #Calibrate
149             client.CC_RFST_RX();
150             rssi=client.RF_getrssi();
151         
152             print "%f %i %3i" % (
153                 time.time()-start,
154                 client.RF_getfreq()/10.0**6,
155                 rssi); 
156         sys.stdout.flush();
157
158 if sys.argv[1]=="surf":
159     print "Scanning channels [11,26].";
160     
161     #Promiscuous mode.
162     client.RF_promiscuity(1);
163     client.RF_autocrc(1);
164     
165     chan=11;
166     if len(sys.argv)>2:
167         chan=eval(sys.argv[2]);
168         
169     client.CC_RFST_RX();
170     
171     #Now we're ready to get packets.
172     while 1:
173         if chan>26: chan=11;
174         
175         client.setup(); #Really oughtn't be necessary, but can't hurt.
176         client.RF_setchan(chan);
177         
178         packet=None;
179         lasttime=time.time();
180         while packet==None and time.time()-lasttime<0.5:
181             packet=client.RF_rxpacket();
182         if packet!=None:
183             client.printpacket(packet=packet,
184                            prefix=("%02d: "%chan));
185         sys.stdout.flush();
186         chan=chan+1;
187
188 if(sys.argv[1]=="sniff" or sys.argv[1]=="sniffdissect"):
189     #Promiscuous mode.
190     client.RF_promiscuity(1);
191     client.RF_autocrc(1);
192     
193     if len(sys.argv)>2:
194         freq=eval(sys.argv[2]);
195         if freq>3000:
196             client.RF_setfreq(freq);
197         elif freq>100:
198             client.RF_setfreq(freq*1000000);
199         else:
200             client.RF_setchan(freq);
201     client.CC_RFST_RX();
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.
205     while 1:
206         client.setup(); #Really oughtn't be necessary, but can't hurt.
207         client.CC_RFST_RX();
208         
209         packet=None;
210         while packet==None:
211             packet=client.RF_rxpacket();
212         if sys.argv[1]=="sniffdissect":
213             client.printdissect(packet);
214         else:
215             client.printpacket(packet);
216         sys.stdout.flush();
217
218 if(sys.argv[1]=="bsniff"):
219     #Just broadcast.
220     client.RF_promiscuity(0);
221     client.RF_setsmac(0xFFFFFFFF);
222     client.RF_autocrc(1);
223     
224     if len(sys.argv)>2:
225         freq=eval(sys.argv[2]);
226         if freq>100:
227             client.RF_setfreq(freq);
228         else:
229             client.RF_setchan(freq);
230     client.CC_RFST_RX();
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.
234     while 1:
235         packet=None;
236         while packet==None:
237             packet=client.RF_rxpacket();
238         client.printpacket(packet);
239         sys.stdout.flush();
240
241 if(sys.argv[1]=="txtest"):
242     if len(sys.argv)>2:
243         freq=eval(sys.argv[2]);
244         if freq>100:
245             client.RF_setfreq(freq);
246         else:
247             client.RF_setchan(freq);
248     print "Transmitting DEADBEEF as %010x on %i MHz" % (
249         client.RF_getsmac(),
250         client.RF_getfreq()/10**6);
251     
252     while 1:
253         client.RF_txpacket([0x0f, 0x01, 0x08, 0x82,
254                             0xff, 0xff, 0xff, 0xff,
255                             0xde, 0xad, 0xbe, 0xef,
256                             0xba, 0xbe, 0xc0]);
257
258 if(sys.argv[1]=="txtoscount"):
259     '''
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)
263     '''
264     if (len(sys.argv)<=3):
265         print "Provide -r to work via replays or -i to work via incrementing itself.";
266         sys.exit(1);
267     if (sys.argv[3]=="-r"):
268         client.RF_promiscuity(1);
269     client.RF_autocrc(1);
270     if len(sys.argv)>2:
271         freq=eval(sys.argv[2]);
272         if freq>100:
273             client.RF_setfreq(freq);
274         else:
275             client.RF_setchan(freq);
276     if (sys.argv[3]=="-r"):
277         client.CC_RFST_RX();
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"):
281         i = 0;
282         countpkt = [0x0f, 0x41, 0x88, 0xFF, 0x22, 0x00, 0xff, 0xff, 0x01, 0x00, 0x3f, 0x06, 0x00, 0xFF];
283     while 1:
284         if (sys.argv[3]=="-r"): #give -r to do via replays from the other device
285             packet=None;
286             while packet==None:
287                 packet=client.RF_rxpacket();
288             pkt = packet[:14];
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:
292             pkt = countpkt[:];
293             pkt[3] = i;
294             pkt[13] = i+1;
295             client.RF_txpacket(pkt);
296             if i >= 31: i = 0;
297             else:       i += 1;
298             time.sleep(0.5);
299
300 if(sys.argv[1]=="txpiptest" or sys.argv[1]=="txpipscapy"):
301     if len(sys.argv)>2:
302         freq=eval(sys.argv[2]);
303         if freq>100:
304             client.RF_setfreq(freq);
305         else:
306             client.RF_setchan(freq);
307     print "Transmitting on as %010x on %i MHz" % (
308         client.RF_getsmac(),
309         client.RF_getfreq()/10**6);
310     
311     client.RF_setsync(0xFFFF);
312     
313     while 1:
314         if(sys.argv[1]=="txpiptest"):
315             client.RF_txpacket([
316                     0x7f, 
317                     #Real header, must begin with SFD.
318                     0x00, 0x00, 0x00,
319                     0x00, 0xA7,
320                     
321                     #Length
322                     0x1f, 0x01, 0x08, 0x82,
323                     0xDF, 0xff, 0xff, 0xff,
324                     0xde, 0xad, 0xbe, 0xef,
325                     0xba, 0xbe, 0xc0,
326                     
327                     #Preamble
328                     0x00, 0x00, 0x00,
329                     #SFD
330                     0x00, 0xA7,  #CC2420 SFD
331                     #Packet In Packet
332                     0x0f, 0x01, 0x08, 0x82,
333                     0xff, 0xff, 0xff, 0xff,
334                     0xde, 0xad, 0xbe, 0xef,
335                     0xba, 0xbe, 0xc0,
336                     
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,
344                     ]);
345         elif(sys.argv[1]=="txpipscapy"):
346             # NB: Requires Scapy with dot15d4.py layer. (rmspeers)
347             try:
348                 from scapy.all import Dot15d4, Dot15d4FCS, Dot15d4Data, Raw
349                 import struct
350             except ImportError:
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
355             # Make inner packet
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)
369
370 if(sys.argv[1]=="peek"):
371     start=0x0000;
372     if(len(sys.argv)>2):
373         start=int(sys.argv[2],16);
374     stop=start;
375     if(len(sys.argv)>3):
376         stop=int(sys.argv[3],16);
377     print "Peeking from %04x to %04x." % (start,stop);
378     while start<=stop:
379         print "%04x: 0x%04x" % (start,client.peek(start));
380         start=start+1;
381 if(sys.argv[1]=="poke"):
382     start=0x0000;
383     val=0x00;
384     if(len(sys.argv)>2):
385         start=int(sys.argv[2],16);
386     if(len(sys.argv)>3):
387         val=int(sys.argv[3],16);
388     print "Poking r%02x to become 0x%04x." % (start,val);
389     
390     client.poke(start,val);
391