Added 'goodfet.ccspi sniffnonce' for sniffing the nonce sequences.
[goodfet] / client / GoodFETCCSPI.py
index 78273ac..4905dfb 100644 (file)
@@ -1,11 +1,11 @@
 #!/usr/bin/env python
 # GoodFET Chipcon RF Radio Client
 # 
-# (C) 2009 Travis Goodspeed <travis at radiantmachines.com>
+# (C) 2009, 2012 Travis Goodspeed <travis at radiantmachines.com>
 #
 # This code is being rewritten and refactored.  You've been warned!
 
-import sys, time, string, cStringIO, struct, glob, serial, os;
+import sys, time, string, cStringIO, struct, glob, os;
 
 from GoodFET import GoodFET;
 
@@ -20,11 +20,12 @@ class GoodFETCCSPI(GoodFET):
         #Set up the radio for ZigBee
         self.strobe(0x01);       #SXOSCON
         self.strobe(0x02);       #SCAL
-        self.poke(0x11, 0x0AC2); #MDMCTRL0
+        self.poke(0x11, 0x0AC2 & (~0x0800)); #MDMCTRL0, promiscuous
         self.poke(0x12, 0x0500); #MDMCTRL1
         self.poke(0x1C, 0x007F); #IOCFG0
         self.poke(0x19, 0x01C4); #SECCTRL0, disabling crypto
-        self.RF_setsync();
+        #self.poke(0x19, 0x0204); #SECCTRL0, as seen elsewhere.
+        #self.RF_setsync();
         
     def ident(self):
         return self.peek(0x1E); #MANFIDL
@@ -58,10 +59,10 @@ class GoodFETCCSPI(GoodFET):
         self.strobe(0x04);  #0x05 for CCA
     def CC_RFST_RX(self):
         """Switch the radio to RX mode."""
-        self.strobe(0x03);
+        self.strobe(0x03); #RX ON
     def CC_RFST_CAL(self):
         """Calibrate strobe the radio."""
-        self.strobe(0x02);
+        self.strobe(0x02); #RX Calibrate
     def CC_RFST(self,state=0x00):
         self.strobe(state);
         return;
@@ -89,7 +90,8 @@ class GoodFETCCSPI(GoodFET):
                 reg,
                 val,
                 self.peek(reg,bytes));
-        return;
+            return False;
+        return True;
     
     def status(self):
         """Read the status byte."""
@@ -113,7 +115,7 @@ class GoodFETCCSPI(GoodFET):
     #Radio stuff begins here.
     def RF_setenc(self,code="802.15.4"):
         """Set the encoding type."""
-        return;
+        return code;
     def RF_getenc(self):
         """Get the encoding type."""
         return "802.15.4";
@@ -129,19 +131,35 @@ class GoodFETCCSPI(GoodFET):
         self.poke(0x14,sync);
         return;
     
+    def RF_setkey(self,key):
+        """Sets the first key for encryption to the given argument."""
+        print "ERROR: Forgot to set the key.";
+        
+        return;
+    def RF_setnonce(self,key):
+        """Sets the first key for encryption to the given argument."""
+        print "ERROR: Forgot to set the nonce.";
+        
+        return;
+    
     def RF_setfreq(self,frequency):
         """Set the frequency in Hz."""
         mhz=frequency/1000000;
-        fsctrl=0x8000; #self.peek(0x18)&(~0x3FF);
+        #fsctrl=0x8000; #
+        fsctrl=self.peek(0x18)&(~0x3FF);
         fsctrl=fsctrl+int(mhz-2048)
         self.poke(0x18,fsctrl);
-        self.strobe(0x02);
+        #self.CC_RFST_IDLE();
+        self.strobe(0x02);#SCAL
+        time.sleep(0.01);
+        self.strobe(0x03);#SRXON
     def RF_getfreq(self):
         """Get the frequency in Hz."""
         fsctrl=self.peek(0x18);
         mhz=2048+(fsctrl&0x3ff)
         return mhz*1000000;
     def RF_setchan(self,channel):
+        """Set the ZigBee/802.15.4 channel number."""
         if channel < 11 or channel > 26:
             print "Only 802.15.4 channels 11 to 26 are currently supported.";
         else:
@@ -159,16 +177,28 @@ class GoodFETCCSPI(GoodFET):
         """Set the target MAC address."""
         return 0xdeadbeef;
     def RF_getrssi(self):
-        """Returns the received signal strenght, with a weird offset."""
+        """Returns the received signal strength, with a weird offset."""
         rssival=self.peek(0x13)&0xFF; #raw RSSI register
         return rssival^0x80;
+
+    def peekram(self,adr,count):
+        """Peeks data from CC2420 RAM."""
+        data=[
+            adr&0xFF,adr>>8,     # Address first.
+            count&0xFF,count>>8  # Then length.
+            ];
+        self.writecmd(self.CCSPIAPP,0x84,len(data),data);
+        return self.data;
+    def pokeram(self,adr,data):
+        """Pokes data into CC2420 RAM."""
+        data=[adr&0xFF, adr>>8]+data;
+        self.writecmd(self.CCSPIAPP,0x85,len(data),data);
+        return;
+    
     lastpacket=range(0,0xff);
     def RF_rxpacket(self):
-        """Get a packet from the radio.  Returns None if none is waiting.  In
-        order to not require the SFD, FIFO, or FIFOP lines, this
-        implementation works by comparing the buffer to the older
-        contents.
-        """
+        """Get a packet from the radio.  Returns None if none is
+        waiting."""
         
         data="\0";
         self.data=data;
@@ -178,7 +208,23 @@ class GoodFETCCSPI(GoodFET):
         self.lastpacket=buffer;
         if(len(buffer)==0):
             return None;
+        
+        return buffer;
+    def RF_rxpacketdec(self):
+        """Get and decrypt a packet from the radio.  Returns None if
+        none is waiting."""
+        
+        data="\0";
+        self.data=data;
+        self.writecmd(self.CCSPIAPP,0x90,len(data),data);
+        buffer=self.data;
+        
+        self.lastpacket=buffer;
+        if(len(buffer)==0):
+            return None;
+        
         return buffer;
+
     def RF_txpacket(self,packet):
         """Send a packet through the radio."""
         self.writecmd(self.CCSPIAPP,0x81,len(packet),packet);
@@ -186,24 +232,20 @@ class GoodFETCCSPI(GoodFET):
         #self.strobe(0x09);
         return;
     
-    def RF_reflexjam(self):
+    def RF_reflexjam(self,duration=0):
         """Place the device into reflexive jamming mode."""
-        data = "";
+        data = [duration&0xff,
+                (duration>>8)&0xff];
         self.writecmd(self.CCSPIAPP,0xA0,len(data),data);
         return;
 
-    def RF_reflexjam_seq(self):
+    def RF_reflexjam_autoack(self):
         """Place the device into reflexive jamming mode
-           and return the sequence number of the jammed packet."""
-        #TODO make so that this function someone keeps receiving
-        #     the sequence numbers from each jammed frame, or probably
-        #     just make the firmware auto-ack if the frame requests
-        #     an ACK instead of sending data back to client.
-        data = "\0";
-        self.data = data;
+           and that also sends a forged ACK if needed."""
+        data = "";
         self.writecmd(self.CCSPIAPP,0xA1,len(data),data);
-        buffer = self.data;
-        return ord(buffer[3]);
+        print "Got:", data, "and", self.data
+        return;
 
     def RF_modulated_spectrum(self):
         """Hold a carrier wave on the present frequency."""
@@ -282,6 +324,14 @@ class GoodFETCCSPI(GoodFET):
             mdmctrl0=mdmctrl0|0x0020;
         self.poke(0x11,mdmctrl0);
         return;
+    def RF_autoack(self,autoack=1):
+        mdmctrl0=self.peek(0x11);
+        if autoack==0:
+            mdmctrl0=mdmctrl0&(~0x0010);
+        else:
+            mdmctrl0=mdmctrl0|0x0010;
+        self.poke(0x11,mdmctrl0);
+        return;
     packetlen=16;
     def RF_setpacketlen(self,len=16):
         """Set the number of bytes in the expected payload."""
@@ -306,12 +356,12 @@ class GoodFETCCSPI(GoodFET):
         choice=choices[len];
         self.poke(0x03,choice);
         self.maclen=len;
-    def printpacket(self,packet):
+    def printpacket(self,packet,prefix="#"):
         s="";
         i=0;
         for foo in packet:
             s="%s %02x" % (s,ord(foo));
-        print "#%s" % s;
+        print "%s%s" % (prefix,s);
         
     def printdissect(self,packet):
         try: