]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - tos/chips/cc2420/transmit/CC2420TransmitP.nc
Backport change from CVS for getTime32() in CC2420TransmitP.
[tinyos-2.x.git] / tos / chips / cc2420 / transmit / CC2420TransmitP.nc
index a571fc70d6d955d1812958bfb7ebe862f21dca6b..7e12cec89ae136f5c2b5496975083e72528f2cb7 100644 (file)
@@ -33,6 +33,8 @@
  * @author Jonathan Hui <jhui@archrock.com>
  * @author David Moss
  * @author Jung Il Choi Initial SACK implementation
+ * @author JeongGil Ko
+ * @author Razvan Musaloiu-E
  * @version $Revision$ $Date$
  */
 
@@ -71,6 +73,13 @@ module CC2420TransmitP @safe() {
   uses interface CC2420Strobe as SFLUSHTX;
   uses interface CC2420Register as MDMCTRL1;
 
+  uses interface CC2420Strobe as STXENC;
+  uses interface CC2420Register as SECCTRL0;
+  uses interface CC2420Register as SECCTRL1;
+  uses interface CC2420Ram as KEY0;
+  uses interface CC2420Ram as KEY1;
+  uses interface CC2420Ram as TXNONCE;
+
   uses interface CC2420Receive;
   uses interface Leds;
 }
@@ -96,6 +105,17 @@ implementation {
   enum {
     CC2420_ABORT_PERIOD = 320
   };
+
+#ifdef CC2420_HW_SECURITY
+  uint16_t startTime = 0;
+  norace uint8_t secCtrlMode = 0;
+  norace uint8_t nonceValue[16] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
+  norace uint8_t skip;
+  norace uint16_t CTR_SECCTRL0, CTR_SECCTRL1;
+  uint8_t securityChecked = 0;
+  
+  void securityCheck();
+#endif
   
   norace message_t * ONE_NOK m_msg;
   
@@ -104,7 +124,7 @@ implementation {
   norace uint8_t m_tx_power;
   
   cc2420_transmit_state_t m_state = S_STOPPED;
-  
+
   bool m_receiving = FALSE;
   
   uint16_t m_prev_time;
@@ -236,12 +256,11 @@ implementation {
   }
   
   
-  inline uint32_t time16to32(uint16_t time, uint32_t recent_time)
+  inline uint32_t getTime32(uint16_t time)
   {
-    if ((recent_time&0xFFFF)<time)
-      return ((recent_time-0x10000UL)&0xFFFF0000UL)|time;
-    else
-      return (recent_time&0xFFFF0000UL)|time;
+    uint32_t recent_time = call BackoffTimer.getNow();
+
+    return recent_time - (uint16_t)(recent_time - time);
   }
 
   /**
@@ -258,22 +277,30 @@ implementation {
    * would have picked up and executed had our microcontroller been fast enough.
    */
   async event void CaptureSFD.captured( uint16_t time ) {
-    uint32_t time32 = time16to32(time, call BackoffTimer.getNow());
+    uint32_t time32;
+    uint8_t sfd_state = 0;
     atomic {
+      time32 = getTime32(time);
       switch( m_state ) {
         
       case S_SFD:
         m_state = S_EFD;
         sfdHigh = TRUE;
+        // in case we got stuck in the receive SFD interrupts, we can reset
+        // the state here since we know that we are not receiving anymore
+        m_receiving = FALSE;
         call CaptureSFD.captureFallingEdge();
         call PacketTimeStamp.set(m_msg, time32);
         if (call PacketTimeSyncOffset.isSet(m_msg)) {
-           timesync_radio_t *timesync = (timesync_radio_t*)((void*)m_msg + call PacketTimeSyncOffset.get(m_msg));
+           uint8_t absOffset = sizeof(message_header_t)-sizeof(cc2420_header_t)+call PacketTimeSyncOffset.get(m_msg);
+           timesync_radio_t *timesync = (timesync_radio_t *)((nx_uint8_t*)m_msg+absOffset);
            // set timesync event time as the offset between the event time and the SFD interrupt time (TEP  133)
            *timesync  -= time32;
            call CSN.clr();
-           call TXFIFO_RAM.write( call PacketTimeSyncOffset.get(m_msg), (void*)timesync, sizeof(timesync_radio_t) );
+           call TXFIFO_RAM.write( absOffset, (uint8_t*)timesync, sizeof(timesync_radio_t) );
            call CSN.set();
+           //restoring the event time to the original value
+           *timesync  += time32;
         }
 
         if ( (call CC2420PacketBody.getHeader( m_msg ))->fcf & ( 1 << IEEE154_FCF_ACK_REQ ) ) {
@@ -283,16 +310,11 @@ implementation {
         releaseSpiResource();
         call BackoffTimer.stop();
 
-        
-        if ( ( ( (call CC2420PacketBody.getHeader( m_msg ))->fcf >> IEEE154_FCF_FRAME_TYPE ) & 7 ) == IEEE154_TYPE_DATA ) {
-          call PacketTimeStamp.set(m_msg, time32);
-        }
-        
         if ( call SFD.get() ) {
           break;
         }
         /** Fall Through because the next interrupt was already received */
-        
+
       case S_EFD:
         sfdHigh = FALSE;
         call CaptureSFD.captureRisingEdge();
@@ -310,9 +332,12 @@ implementation {
         /** Fall Through because the next interrupt was already received */
         
       default:
-        if ( !m_receiving ) {
+        /* this is the SFD for received messages */
+        if ( !m_receiving && sfdHigh == FALSE ) {
           sfdHigh = TRUE;
           call CaptureSFD.captureFallingEdge();
+          // safe the SFD pin status for later use
+          sfd_state = call SFD.get();
           call CC2420Receive.sfd( time32 );
           m_receiving = TRUE;
           m_prev_time = time;
@@ -320,18 +345,29 @@ implementation {
             // wait for the next interrupt before moving on
             return;
           }
+          // if SFD.get() = 0, then an other interrupt happened since we
+          // reconfigured CaptureSFD! Fall through
         }
         
-        sfdHigh = FALSE;
-        call CaptureSFD.captureRisingEdge();
-        m_receiving = FALSE;
-        if ( time - m_prev_time < 10 ) {
-          call CC2420Receive.sfd_dropped();
-         if (m_msg)
-           call PacketTimeStamp.clear(m_msg);
+        if ( sfdHigh == TRUE ) {
+          sfdHigh = FALSE;
+          call CaptureSFD.captureRisingEdge();
+          m_receiving = FALSE;
+          /* if sfd_state is 1, then we fell through, but at the time of
+           * saving the time stamp the SFD was still high. Thus, the timestamp
+           * is valid.
+           * if the sfd_state is 0, then either we fell through and SFD
+           * was low while we safed the time stamp, or we didn't fall through.
+           * Thus, we check for the time between the two interrupts.
+           * FIXME: Why 10 tics? Seams like some magic number...
+           */
+          if ((sfd_state == 0) && (time - m_prev_time < 10) ) {
+            call CC2420Receive.sfd_dropped();
+            if (m_msg)
+              call PacketTimeStamp.clear(m_msg);
+          }
+          break;
         }
-        break;
-      
       }
     }
   }
@@ -359,7 +395,6 @@ implementation {
     if ( type == IEEE154_TYPE_ACK && m_msg) {
       ack_header = call CC2420PacketBody.getHeader( ack_msg );
       msg_header = call CC2420PacketBody.getHeader( m_msg );
-
       
       if ( m_state == S_ACK_WAIT && msg_header->dsn == ack_header->dsn ) {
         call BackoffTimer.stop();
@@ -518,6 +553,9 @@ implementation {
         return FAIL;
       }
       
+#ifdef CC2420_HW_SECURITY
+      securityChecked = 0;
+#endif
       m_state = S_LOAD;
       m_cca = cca;
       m_msg = p_msg;
@@ -562,7 +600,123 @@ implementation {
     
     return SUCCESS;
   }
-  
+#ifdef CC2420_HW_SECURITY
+
+  task void waitTask(){
+    call Leds.led2Toggle();
+    if(SECURITYLOCK == 1){
+      post waitTask();
+    }else{
+      securityCheck();
+    }
+  }
+
+  void securityCheck(){
+
+    cc2420_header_t* msg_header;
+    cc2420_status_t status;
+    security_header_t* secHdr;
+    uint8_t mode;
+    uint8_t key;
+    uint8_t micLength;
+
+    msg_header = call CC2420PacketBody.getHeader( m_msg );
+
+    if(!(msg_header->fcf & (1 << IEEE154_FCF_SECURITY_ENABLED))){
+      // Security is not used for this packet
+      // Make sure to set mode to 0 and the others to the default values
+      CTR_SECCTRL0 = ((0 << CC2420_SECCTRL0_SEC_MODE) |
+                     (1 << CC2420_SECCTRL0_SEC_M) |
+                     (1 << CC2420_SECCTRL0_SEC_TXKEYSEL) |
+                     (1 << CC2420_SECCTRL0_SEC_CBC_HEAD)) ;
+      
+      call CSN.clr();
+      call SECCTRL0.write(CTR_SECCTRL0);
+      call CSN.set();
+
+      return;
+    }
+
+    if(SECURITYLOCK == 1){
+      post waitTask();
+    }else {
+      //Will perform encryption lock registers
+      atomic SECURITYLOCK = 1;
+
+      secHdr = (security_header_t*) &msg_header->secHdr;
+      memcpy(&nonceValue[3], &(secHdr->frameCounter), 4);
+
+      skip = secHdr->reserved;
+      key = secHdr->keyID[0]; // For now this is the only key selection mode.
+
+      if (secHdr->secLevel == NO_SEC){
+       mode = CC2420_NO_SEC;
+       micLength = 4;
+      }else if (secHdr->secLevel == CBC_MAC_4){
+       mode = CC2420_CBC_MAC;
+       micLength = 4;
+      }else if (secHdr->secLevel == CBC_MAC_8){
+       mode = CC2420_CBC_MAC;
+       micLength = 8;
+      }else if (secHdr->secLevel == CBC_MAC_16){
+       mode = CC2420_CBC_MAC;
+       micLength = 16;
+      }else if (secHdr->secLevel == CTR){
+       mode = CC2420_CTR;
+       micLength = 4;
+      }else if (secHdr->secLevel == CCM_4){
+       mode = CC2420_CCM;
+       micLength = 4;
+      }else if (secHdr->secLevel == CCM_8){
+       mode = CC2420_CCM;
+       micLength = 8;
+      }else if (secHdr->secLevel == CCM_16){
+       mode = CC2420_CCM;
+       micLength = 16;
+      }else{
+       return;
+      }
+
+      CTR_SECCTRL0 = ((mode << CC2420_SECCTRL0_SEC_MODE) |
+                     ((micLength-2)/2 << CC2420_SECCTRL0_SEC_M) |
+                     (key << CC2420_SECCTRL0_SEC_TXKEYSEL) |
+                     (1 << CC2420_SECCTRL0_SEC_CBC_HEAD)) ;
+#ifndef TFRAMES_ENABLED
+      CTR_SECCTRL1 = (skip+11+sizeof(security_header_t)+((skip+11+sizeof(security_header_t))<<8));
+#else
+      CTR_SECCTRL1 = (skip+10+sizeof(security_header_t)+((skip+10+sizeof(security_header_t))<<8));
+#endif
+
+      call CSN.clr();
+      call SECCTRL0.write(CTR_SECCTRL0);
+      call CSN.set();
+
+      call CSN.clr();
+      call SECCTRL1.write(CTR_SECCTRL1);
+      call CSN.set();
+
+      call CSN.clr();
+      call TXNONCE.write(0, nonceValue, 16);
+      call CSN.set();
+
+      call CSN.clr();
+      status = call SNOP.strobe();
+      call CSN.set();
+
+      while(status & CC2420_STATUS_ENC_BUSY){
+       call CSN.clr();
+       status = call SNOP.strobe();
+       call CSN.set();
+      }
+      
+      // Inline security will be activated by STXON or STXONCCA strobes
+
+      atomic SECURITYLOCK = 0;
+
+    }
+  }
+#endif
+
   /**
    * Attempt to send the packet we have loaded into the tx buffer on 
    * the radio chip.  The STXONCCA will send the packet immediately if
@@ -575,6 +729,9 @@ implementation {
    *
    * If the packet got sent, we should expect an SFD interrupt to take
    * over, signifying the packet is getting sent.
+   * 
+   * If security is enabled, STXONCCA or STXON will perform inline security
+   * options before transmitting the packet.
    */
   void attemptSend() {
     uint8_t status;
@@ -589,10 +746,13 @@ implementation {
         signal Send.sendDone( m_msg, ECANCEL );
         return;
       }
-      
-      
+#ifdef CC2420_HW_SECURITY
+      if(securityChecked != 1){
+       securityCheck();
+      }
+      securityChecked = 1;
+#endif
       call CSN.clr();
-
       status = m_cca ? call STXONCCA.strobe() : call STXON.strobe();
       if ( !( status & CC2420_STATUS_TX_ACTIVE ) ) {
         status = call SNOP.strobe();
@@ -600,11 +760,11 @@ implementation {
           congestion = FALSE;
         }
       }
-      
+
       m_state = congestion ? S_SAMPLE_CCA : S_SFD;
       call CSN.set();
     }
-    
+
     if ( congestion ) {
       totalCcaChecks = 0;
       releaseSpiResource();
@@ -686,5 +846,6 @@ implementation {
     call ChipSpiResource.attemptRelease();
     signal Send.sendDone( m_msg, err );
   }
+
 }