X-Git-Url: https://oss.titaniummirror.com/gitweb/?a=blobdiff_plain;f=tos%2Fchips%2Fcc2420%2Ftransmit%2FCC2420TransmitP.nc;h=7e12cec89ae136f5c2b5496975083e72528f2cb7;hb=e9bfab607e051bae6afb47b44892ce37541d1b44;hp=4fe02ebda654a34a77025fa31607dc3be062a071;hpb=e72a6756a30fecdd80f4f1b1ee799749f1ab02a7;p=tinyos-2.x.git diff --git a/tos/chips/cc2420/transmit/CC2420TransmitP.nc b/tos/chips/cc2420/transmit/CC2420TransmitP.nc index 4fe02ebd..7e12cec8 100644 --- a/tos/chips/cc2420/transmit/CC2420TransmitP.nc +++ b/tos/chips/cc2420/transmit/CC2420TransmitP.nc @@ -1,5 +1,5 @@ -/* - * Copyright (c) 2005-2006 Arch Rock Corporation +/* + * Copyright (c) 2005-2006 Arch Rock Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -33,26 +33,30 @@ * @author Jonathan Hui * @author David Moss * @author Jung Il Choi Initial SACK implementation + * @author JeongGil Ko + * @author Razvan Musaloiu-E * @version $Revision$ $Date$ */ #include "CC2420.h" +#include "CC2420TimeSyncMessage.h" #include "crc.h" #include "message.h" -module CC2420TransmitP { +module CC2420TransmitP @safe() { provides interface Init; provides interface StdControl; provides interface CC2420Transmit as Send; provides interface RadioBackoff; - provides interface RadioTimeStamping as TimeStamp; provides interface ReceiveIndicator as EnergyIndicator; provides interface ReceiveIndicator as ByteIndicator; uses interface Alarm as BackoffTimer; uses interface CC2420Packet; uses interface CC2420PacketBody; + uses interface PacketTimeStamp; + uses interface PacketTimeSyncOffset; uses interface GpioCapture as CaptureSFD; uses interface GeneralIO as CCA; uses interface GeneralIO as CSN; @@ -69,6 +73,13 @@ module CC2420TransmitP { 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; } @@ -84,9 +95,7 @@ implementation { S_SFD, S_EFD, S_ACK_WAIT, - S_LOAD_CANCEL, - S_TX_CANCEL, - S_CCA_CANCEL, + S_CANCEL, } cc2420_transmit_state_t; // This specifies how many jiffies the stack should wait after a @@ -96,15 +105,26 @@ 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 *m_msg; + norace message_t * ONE_NOK m_msg; norace bool m_cca; norace uint8_t m_tx_power; cc2420_transmit_state_t m_state = S_STOPPED; - + bool m_receiving = FALSE; uint16_t m_prev_time; @@ -126,7 +146,7 @@ implementation { /***************** Prototypes ****************/ - error_t send( message_t *p_msg, bool cca ); + error_t send( message_t * ONE p_msg, bool cca ); error_t resend( bool cca ); void loadTXFIFO(); void attemptSend(); @@ -169,7 +189,7 @@ implementation { /**************** Send Commands ****************/ - async command error_t Send.send( message_t* p_msg, bool useCca ) { + async command error_t Send.send( message_t* ONE p_msg, bool useCca ) { return send( p_msg, useCca ); } @@ -181,15 +201,9 @@ implementation { atomic { switch( m_state ) { case S_LOAD: - m_state = S_LOAD_CANCEL; - break; - case S_SAMPLE_CCA: - m_state = S_CCA_CANCEL; - break; - case S_BEGIN_TRANSMIT: - m_state = S_TX_CANCEL; + m_state = S_CANCEL; break; default: @@ -242,7 +256,13 @@ implementation { } - + inline uint32_t getTime32(uint16_t time) + { + uint32_t recent_time = call BackoffTimer.getNow(); + + return recent_time - (uint16_t)(recent_time - time); + } + /** * The CaptureSFD event is actually an interrupt from the capture pin * which is connected to timing circuitry and timer modules. This @@ -257,14 +277,32 @@ implementation { * would have picked up and executed had our microcontroller been fast enough. */ async event void CaptureSFD.captured( uint16_t time ) { + 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(); - signal TimeStamp.transmittedSFD( time, m_msg ); + call PacketTimeStamp.set(m_msg, time32); + if (call PacketTimeSyncOffset.isSet(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( 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 ) ) { // This is an ack packet, don't release the chip's SPI bus lock. abortSpiRelease = TRUE; @@ -272,16 +310,11 @@ implementation { releaseSpiResource(); call BackoffTimer.stop(); - - if ( ( ( (call CC2420PacketBody.getHeader( m_msg ))->fcf >> IEEE154_FCF_FRAME_TYPE ) & 7 ) == IEEE154_TYPE_DATA ) { - (call CC2420PacketBody.getMetadata( m_msg ))->time = time; - } - if ( call SFD.get() ) { break; } /** Fall Through because the next interrupt was already received */ - + case S_EFD: sfdHigh = FALSE; call CaptureSFD.captureRisingEdge(); @@ -299,27 +332,42 @@ 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(); - signal TimeStamp.receivedSFD( time ); - call CC2420Receive.sfd( time ); + // safe the SFD pin status for later use + sfd_state = call SFD.get(); + call CC2420Receive.sfd( time32 ); m_receiving = TRUE; m_prev_time = time; if ( call SFD.get() ) { // 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 ( 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; - } } } @@ -344,10 +392,9 @@ implementation { uint8_t* ack_buf; uint8_t length; - if ( type == IEEE154_TYPE_ACK ) { + 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(); @@ -381,9 +428,7 @@ implementation { attemptSend(); break; - case S_LOAD_CANCEL: - case S_CCA_CANCEL: - case S_TX_CANCEL: + case S_CANCEL: call CSN.clr(); call SFLUSHTX.strobe(); call CSN.set(); @@ -391,6 +436,7 @@ implementation { atomic { m_state = S_STARTED; } + signal Send.sendDone( m_msg, ECANCEL ); break; default: @@ -408,7 +454,7 @@ implementation { error_t error ) { call CSN.set(); - if ( m_state == S_LOAD_CANCEL ) { + if ( m_state == S_CANCEL ) { atomic { call CSN.clr(); call SFLUSHTX.strobe(); @@ -416,25 +462,18 @@ implementation { } releaseSpiResource(); m_state = S_STARTED; - + signal Send.sendDone( m_msg, ECANCEL ); + } else if ( !m_cca ) { atomic { - if (m_state == S_LOAD_CANCEL) { - m_state = S_TX_CANCEL; - } else { - m_state = S_BEGIN_TRANSMIT; - } + m_state = S_BEGIN_TRANSMIT; } attemptSend(); } else { releaseSpiResource(); atomic { - if (m_state == S_LOAD_CANCEL) { - m_state = S_CCA_CANCEL; - } else { - m_state = S_SAMPLE_CCA; - } + m_state = S_SAMPLE_CCA; } signal RadioBackoff.requestInitialBackoff(m_msg); @@ -471,12 +510,8 @@ implementation { } break; - case S_CCA_CANCEL: - m_state = S_TX_CANCEL; - /** Fall Through */ - case S_BEGIN_TRANSMIT: - case S_TX_CANCEL: + case S_CANCEL: if ( acquireSpiResource() == SUCCESS ) { attemptSend(); } @@ -508,11 +543,9 @@ implementation { * @param *p_msg Pointer to the message that needs to be sent * @param cca TRUE if this transmit should use clear channel assessment */ - error_t send( message_t* p_msg, bool cca ) { + error_t send( message_t* ONE p_msg, bool cca ) { atomic { - if (m_state == S_LOAD_CANCEL - || m_state == S_CCA_CANCEL - || m_state == S_TX_CANCEL) { + if (m_state == S_CANCEL) { return ECANCEL; } @@ -520,6 +553,9 @@ implementation { return FAIL; } +#ifdef CC2420_HW_SECURITY + securityChecked = 0; +#endif m_state = S_LOAD; m_cca = cca; m_msg = p_msg; @@ -541,9 +577,7 @@ implementation { error_t resend( bool cca ) { atomic { - if (m_state == S_LOAD_CANCEL - || m_state == S_CCA_CANCEL - || m_state == S_TX_CANCEL) { + if (m_state == S_CANCEL) { return ECANCEL; } @@ -566,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 @@ -579,23 +729,30 @@ 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; bool congestion = TRUE; atomic { - if (m_state == S_TX_CANCEL) { + if (m_state == S_CANCEL) { call SFLUSHTX.strobe(); releaseSpiResource(); call CSN.set(); m_state = S_STARTED; + 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(); @@ -603,11 +760,11 @@ implementation { congestion = FALSE; } } - + m_state = congestion ? S_SAMPLE_CCA : S_SFD; call CSN.set(); } - + if ( congestion ) { totalCcaChecks = 0; releaseSpiResource(); @@ -677,7 +834,10 @@ implementation { m_tx_power = tx_power; - call TXFIFO.write( (uint8_t*)header, header->length - 1); + { + uint8_t tmpLen __DEPUTY_UNUSED__ = header->length - 1; + call TXFIFO.write(TCAST(uint8_t * COUNT(tmpLen), header), header->length - 1); + } } void signalDone( error_t err ) { @@ -686,17 +846,6 @@ implementation { call ChipSpiResource.attemptRelease(); signal Send.sendDone( m_msg, err ); } - - - - /***************** Tasks ****************/ - - /***************** Defaults ****************/ - default async event void TimeStamp.transmittedSFD( uint16_t time, message_t* p_msg ) { - } - - default async event void TimeStamp.receivedSFD( uint16_t time ) { - } }