Package killerbee :: Module GoodFETCCSPI
[hide private]
[frames] | no frames]

Source Code for Module killerbee.GoodFETCCSPI

  1  #!/usr/bin/env python 
  2  # GoodFET Chipcon RF Radio Client 
  3  #  
  4  # (C) 2009, 2012 Travis Goodspeed <travis at radiantmachines.com> 
  5  # 
  6  # This code is being rewritten and refactored.  You've been warned! 
  7   
  8  import sys, time, string, cStringIO, struct, glob, os; 
  9   
 10  from GoodFET import GoodFET; 
 11   
12 -class GoodFETCCSPI(GoodFET):
13 CCSPIAPP=0x51; 14 CCversions={0x233d: "CC2420", 15 }
16 - def setup(self):
17 """Move the FET into the CCSPI application.""" 18 self.writecmd(self.CCSPIAPP,0x10,0,self.data); #CCSPI/SETUP 19 20 #Set up the radio for ZigBee 21 self.strobe(0x01); #SXOSCON 22 self.strobe(0x02); #SCAL 23 self.poke(0x11, 0x0AC2 & (~0x0800)); #MDMCTRL0, promiscuous 24 self.poke(0x12, 0x0500); #MDMCTRL1 25 self.poke(0x1C, 0x007F); #IOCFG0 26 self.poke(0x19, 0x01C4); #SECCTRL0, disabling crypto
27 #self.poke(0x19, 0x0204); #SECCTRL0, as seen elsewhere. 28 #self.RF_setsync(); 29
30 - def ident(self):
31 return self.peek(0x1E); #MANFIDL
32 - def identstr(self):
33 manfidl=self.peek(0x1E); 34 #manfidh=self.peek(0x1f); 35 try: 36 return "%s" % (self.CCversions[manfidl]); 37 except: 38 return "Unknown0x%04x" % manfidl;
39 - def trans8(self,byte):
40 """Read and write 8 bits by CCSPI.""" 41 data=self.CCSPItrans([byte]); 42 return ord(data[0]);
43
44 - def trans(self,data):
45 """Exchange data by CCSPI.""" 46 self.data=data; 47 self.writecmd(self.CCSPIAPP,0x00,len(data),data); 48 return self.data;
49 - def strobe(self,reg=0x00):
50 """Strobes a strobe register, returning the status.""" 51 data=[reg]; 52 self.trans(data); 53 return ord(self.data[0]);
54 - def CC_RFST_IDLE(self):
55 """Switch the radio to idle mode, clearing overflows and errors.""" 56 self.strobe(0x06); #SRXOFF
57 - def CC_RFST_TX(self):
58 """Switch the radio to TX mode.""" 59 self.strobe(0x04); #0x05 for CCA
60 - def CC_RFST_RX(self):
61 """Switch the radio to RX mode.""" 62 self.strobe(0x03); #RX ON
63 - def CC_RFST_CAL(self):
64 """Calibrate strobe the radio.""" 65 self.strobe(0x02); #RX Calibrate
66 - def CC_RFST(self,state=0x00):
67 self.strobe(state); 68 return;
69 - def peek(self,reg,bytes=2):
70 """Read a CCSPI Register. For long regs, result is flipped.""" 71 72 #Reg is ORed with 0x40 by the GoodFET. 73 data=[reg,0,0]; 74 75 #Automatically calibrate the len. 76 bytes=2; 77 78 self.writecmd(self.CCSPIAPP,0x02,len(data),data); 79 try: 80 toret=( ord(self.data[2]) + (ord(self.data[1])<<8) ); 81 except Exception as e: 82 print "issue in peeking for a register" 83 print e 84 toret=( (ord(self.data[1])<<8) ); 85 return toret;
86 - def poke(self,reg,val,bytes=2):
87 """Write a CCSPI Register.""" 88 data=[reg,(val>>8)&0xFF,val&0xFF]; 89 self.writecmd(self.CCSPIAPP,0x03,len(data),data); 90 if self.peek(reg,bytes)!=val and reg!=0x18: 91 print "Warning, failed to set r%02x=0x%04x, got %02x." %( 92 reg, 93 val, 94 self.peek(reg,bytes)); 95 return False; 96 return True;
97
98 - def status(self):
99 """Read the status byte.""" 100 statusbits={0x80: "?", 101 0x40: "XOSC16M_STABLE", 102 0x20: "TX_UNDERFLOW", 103 0x10: "ENC_BUSY", 104 0x08: "TX_ACTIVE", 105 0x04: "LOCK", 106 0x02: "RSSI_VALID", 107 0x01: "?"}; 108 status=self.strobe(0x00); 109 i=1; 110 str=""; 111 while i<0x100: 112 if status&i: 113 str="%s %s" % (statusbits[i],str); 114 i*=2; 115 return str;
116 117 #Radio stuff begins here.
118 - def RF_setenc(self,code="802.15.4"):
119 """Set the encoding type.""" 120 return code;
121 - def RF_getenc(self):
122 """Get the encoding type.""" 123 return "802.15.4";
124 - def RF_getrate(self):
125 return 0;
126 - def RF_setrate(self,rate=0):
127 return 0;
128 - def RF_getsync(self):
129 return self.peek(0x14);
130 - def RF_setsync(self,sync=0xa70F):
131 """Set the SYNC preamble. 132 Use 0xA70F for 0xA7.""" 133 self.poke(0x14,sync); 134 return;
135
136 - def RF_setkey(self,key):
137 """Sets the first key for encryption to the given argument.""" 138 print "ERROR: Forgot to set the key."; 139 140 return;
141 - def RF_setnonce(self,key):
142 """Sets the first key for encryption to the given argument.""" 143 print "ERROR: Forgot to set the nonce."; 144 145 return;
146
147 - def RF_setfreq(self,frequency):
148 """Set the frequency in Hz.""" 149 mhz=frequency/1000000; 150 #fsctrl=0x8000; # 151 fsctrl=self.peek(0x18)&(~0x3FF); 152 fsctrl=fsctrl+int(mhz-2048) 153 self.poke(0x18,fsctrl); 154 #self.CC_RFST_IDLE(); 155 self.strobe(0x02);#SCAL 156 time.sleep(0.01); 157 self.strobe(0x03);#SRXON
158 - def RF_getfreq(self):
159 """Get the frequency in Hz.""" 160 fsctrl=self.peek(0x18); 161 mhz=2048+(fsctrl&0x3ff) 162 return mhz*1000000;
163 - def RF_setchan(self,channel):
164 """Set the ZigBee/802.15.4 channel number.""" 165 if channel < 11 or channel > 26: 166 print "Only 802.15.4 channels 11 to 26 are currently supported."; 167 else: 168 self.RF_setfreq( ( (channel-11)*5 + 2405 ) * 1000000 );
169 - def RF_getsmac(self):
170 """Return the source MAC address.""" 171 return 0xdeadbeef;
172 - def RF_setsmac(self,mac):
173 """Set the source MAC address.""" 174 return 0xdeadbeef;
175 - def RF_gettmac(self):
176 """Return the target MAC address.""" 177 return 0xdeadbeef;
178 - def RF_settmac(self,mac):
179 """Set the target MAC address.""" 180 return 0xdeadbeef;
181 - def RF_getrssi(self):
182 """Returns the received signal strength, with a weird offset.""" 183 rssival=self.peek(0x13)&0xFF; #raw RSSI register 184 return rssival^0x80;
185
186 - def peekram(self,adr,count):
187 """Peeks data from CC2420 RAM.""" 188 data=[ 189 adr&0xFF,adr>>8, # Address first. 190 count&0xFF,count>>8 # Then length. 191 ]; 192 self.writecmd(self.CCSPIAPP,0x84,len(data),data); 193 return self.data;
194 - def pokeram(self,adr,data):
195 """Pokes data into CC2420 RAM.""" 196 data=[adr&0xFF, adr>>8]+data; 197 self.writecmd(self.CCSPIAPP,0x85,len(data),data); 198 return;
199 200 lastpacket=range(0,0xff);
201 - def RF_rxpacket(self):
202 """Get a packet from the radio. Returns None if none is 203 waiting.""" 204 205 data="\0"; 206 self.data=data; 207 self.writecmd(self.CCSPIAPP,0x80,len(data),data); 208 buffer=self.data; 209 210 self.lastpacket=buffer; 211 if(len(buffer)==0): 212 return None; 213 214 return buffer;
215 - def RF_rxpacketrepeat(self):
216 """Gets packets from the radio, ignoring all future requests so as 217 not to waste time. Call RF_rxpacket() after this.""" 218 219 self.writecmd(self.CCSPIAPP,0x91,0,None); 220 return None;
221
222 - def RF_rxpacketdec(self):
223 """Get and decrypt a packet from the radio. Returns None if 224 none is waiting.""" 225 226 data="\0"; 227 self.data=data; 228 self.writecmd(self.CCSPIAPP,0x90,len(data),data); 229 buffer=self.data; 230 231 self.lastpacket=buffer; 232 if(len(buffer)==0): 233 return None; 234 235 return buffer;
236
237 - def RF_txpacket(self,packet):
238 """Send a packet through the radio.""" 239 self.writecmd(self.CCSPIAPP,0x81,len(packet),packet); 240 #time.sleep(1); 241 #self.strobe(0x09); 242 return;
243
244 - def RF_reflexjam(self,duration=0):
245 """Place the device into reflexive jamming mode.""" 246 data = [duration&0xff, 247 (duration>>8)&0xff]; 248 self.writecmd(self.CCSPIAPP,0xA0,len(data),data); 249 return;
250
251 - def RF_reflexjam_autoack(self):
252 """Place the device into reflexive jamming mode 253 and that also sends a forged ACK if needed.""" 254 data = ""; 255 self.writecmd(self.CCSPIAPP,0xA1,len(data),data); 256 print "Got:", data, "and", self.data 257 return;
258
259 - def RF_modulated_spectrum(self):
260 """Hold a carrier wave on the present frequency.""" 261 # print "Don't know how to hold a carrier."; 262 # 33.1 p.55: 263 # reset chip 264 # SXOSCON 265 # set MDMCTRL1.TX_MODE to 3 0x12 3:2 266 # STXON 0x04 267 268 mdmctrl1=self.peek(0x12); 269 #print "mdmctrl1 was %04x" % mdmctrl1; 270 mdmctrl1=mdmctrl1|0x00c0; #MDMCTRL1.TX_MODE = 3 271 self.poke(0x12, mdmctrl1); #MDMCTRL1 272 273 mdmctrl1=self.peek(0x12); 274 #print "mdmctrl1 is %04x" % mdmctrl1; 275 276 # http://e2e.ti.com/support/low_power_rf/f/155/t/15914.aspx?PageIndex=2 277 # suggests this 278 self.strobe(0x02); #STXCAL 279 #print "STXCAL status: %s" % self.status() 280 281 # is this necessary? 282 self.strobe(0x09); #SFLUSHTX 283 #print "SFLUSHTX status: %s" % self.status() 284 285 self.strobe(0x04); #STXON
286 #print "STXON status: %s" % self.status() 287
288 - def RF_carrier(self):
289 """Hold a carrier wave on the present frequency.""" 290 # print "Don't know how to hold a carrier."; 291 # 33.1 p.54: 292 # reset chip 293 # SXOSCON 294 # set MDMCTRL1.TX_MODE to 2 or 3 0x12 3:2 295 # set DACTST to 0x1800 0x2E 296 # STXON 0x04 297 298 mdmctrl1=self.peek(0x12); 299 #print "mdmctrl1 was %04x" % mdmctrl1; 300 mdmctrl1=mdmctrl1|0x0080; 301 mdmctrl1=mdmctrl1&0x0080; #MDMCTRL1.TX_MODE = 2 302 self.poke(0x12, mdmctrl1); #MDMCTRL1 303 304 mdmctrl1=self.peek(0x12); 305 #print "mdmctrl1 is %04x" % mdmctrl1; 306 307 self.poke(0x2E, 0x1800); #DACTST 308 dactst=self.peek(0x2E); 309 #print "dactst is %04x" % dactst; 310 311 # see above for why this is here 312 self.strobe(0x02); #STXCAL 313 #print "STXCAL status: %s" % self.status() 314 self.strobe(0x09); #SFLUSHTX 315 #print "SFLUSHTX status: %s" % self.status() 316 317 self.strobe(0x04); #STXON
318 #print "STXON status: %s" % self.status() 319
320 - def RF_promiscuity(self,promiscuous=1):
321 mdmctrl0=self.peek(0x11); 322 if promiscuous>0: 323 mdmctrl0=mdmctrl0&(~0x800); 324 else: 325 mdmctrl0=mdmctrl0|0x800; 326 self.poke(0x11,mdmctrl0); 327 return;
328 - def RF_autocrc(self,autocrc=1):
329 mdmctrl0=self.peek(0x11); 330 if autocrc==0: 331 mdmctrl0=mdmctrl0&(~0x0020); 332 else: 333 mdmctrl0=mdmctrl0|0x0020; 334 self.poke(0x11,mdmctrl0); 335 return;
336 - def RF_autoack(self,autoack=1):
337 mdmctrl0=self.peek(0x11); 338 if autoack==0: 339 mdmctrl0=mdmctrl0&(~0x0010); 340 else: 341 mdmctrl0=mdmctrl0|0x0010; 342 self.poke(0x11,mdmctrl0); 343 return;
344 packetlen=16;
345 - def RF_setpacketlen(self,len=16):
346 """Set the number of bytes in the expected payload.""" 347 #self.poke(0x11,len); 348 self.packetlen=len;
349 - def RF_getpacketlen(self):
350 """Set the number of bytes in the expected payload.""" 351 #len=self.peek(0x11); 352 self.packetlen=len; 353 return len;
354 maclen=5;
355 - def RF_getmaclen(self):
356 """Get the number of bytes in the MAC address.""" 357 choices=[0, 3, 4, 5]; 358 choice=self.peek(0x03)&3; 359 self.maclen=choices[choice]; 360 return self.maclen;
361 - def RF_setmaclen(self,len):
362 """Set the number of bytes in the MAC address.""" 363 choices=["illegal", "illegal", "illegal", 364 1, 2, 3]; 365 choice=choices[len]; 366 self.poke(0x03,choice); 367 self.maclen=len;
368 - def printpacket(self,packet,prefix="#"):
369 print self.packet2str(packet,prefix);
370 - def packet2str(self,packet,prefix="#"):
371 s=""; 372 i=0; 373 for foo in packet: 374 s="%s %02x" % (s,ord(foo)); 375 return "%s%s" % (prefix,s);
376
377 - def printdissect(self,packet):
378 try: 379 from scapy.all import Dot15d4 380 except ImportError: 381 print "To use packet disection, Scapy must be installed and have the Dot15d4 extension present." 382 print "try: hg clone http://hg.secdev.org/scapy-com"; 383 print " sudo ./setup.py install"; 384 self.printpacket(packet); 385 try: 386 scapyd = Dot15d4(packet[1:]); 387 scapyd.show(); 388 except: 389 pass;
390