+
+ /*****************Decryption Options*********************/
+#ifdef CC2420_HW_SECURITY
+ task void waitTask(){
+
+ if(SECURITYLOCK == 1){
+ post waitTask();
+ }else{
+ m_state = S_RX_DEC;
+ beginDec();
+ }
+ }
+
+ void beginDec(){
+ if(call SpiResource.isOwner()) {
+ dec();
+ } else if (call SpiResource.immediateRequest() == SUCCESS) {
+ dec();
+ } else {
+ call SpiResource.request();
+ }
+ }
+
+ norace uint8_t decLoopCount = 0;
+
+ task void waitDecTask(){
+
+ cc2420_status_t status;
+
+ call CSN.clr();
+ status = call SNOP.strobe();
+ call CSN.set();
+
+ atomic decLoopCount ++;
+
+ if(decLoopCount > 10){
+ call CSN.clr();
+ atomic call SECCTRL0.write((0 << CC2420_SECCTRL0_SEC_MODE) |
+ (0 << CC2420_SECCTRL0_SEC_M) |
+ (0 << CC2420_SECCTRL0_SEC_RXKEYSEL) |
+ (1 << CC2420_SECCTRL0_SEC_CBC_HEAD) |
+ (1 << CC2420_SECCTRL0_RXFIFO_PROTECTION)) ;
+ call CSN.set();
+ SECURITYLOCK = 0;
+ call SpiResource.release();
+ atomic flush_flag = 1;
+ beginReceive();
+ }else if(status & CC2420_STATUS_ENC_BUSY){
+ post waitDecTask();
+ }else{
+ call CSN.clr();
+ atomic call SECCTRL0.write((0 << CC2420_SECCTRL0_SEC_MODE) |
+ (0 << CC2420_SECCTRL0_SEC_M) |
+ (0 << CC2420_SECCTRL0_SEC_RXKEYSEL) |
+ (1 << CC2420_SECCTRL0_SEC_CBC_HEAD) |
+ (1 << CC2420_SECCTRL0_RXFIFO_PROTECTION)) ;
+ call CSN.set();
+ SECURITYLOCK = 0;
+ call SpiResource.release();
+ beginReceive();
+ }
+
+ }
+
+ void waitDec(){
+ cc2420_status_t status;
+ call CSN.clr();
+ status = call SNOP.strobe();
+ call CSN.set();
+
+ if(status & CC2420_STATUS_ENC_BUSY){
+ atomic decLoopCount = 1;
+ post waitDecTask();
+ }else{
+ call CSN.clr();
+ atomic call SECCTRL0.write((0 << CC2420_SECCTRL0_SEC_MODE) |
+ (0 << CC2420_SECCTRL0_SEC_M) |
+ (0 << CC2420_SECCTRL0_SEC_RXKEYSEL) |
+ (1 << CC2420_SECCTRL0_SEC_CBC_HEAD) |
+ (1 << CC2420_SECCTRL0_RXFIFO_PROTECTION)) ;
+ call CSN.set();
+ SECURITYLOCK = 0;
+ call SpiResource.release();
+ beginReceive();
+ }
+ }
+
+ void dec(){
+ cc2420_header_t header;
+ security_header_t secHdr;
+ uint8_t mode, key, temp, crc;
+
+ atomic pos = (packetLength+pos)%RXFIFO_SIZE;
+ atomic secHdrPos = (pos+10)%RXFIFO_SIZE;
+
+ if (pos + 3 > RXFIFO_SIZE){
+ temp = RXFIFO_SIZE - pos;
+ call CSN.clr();
+ atomic call RXFIFO_RAM.read(pos,(uint8_t*)&header, temp);
+ call CSN.set();
+ call CSN.clr();
+ atomic call RXFIFO_RAM.read(0,(uint8_t*)&header+temp, 3-temp);
+ call CSN.set();
+ }else{
+ call CSN.clr();
+ atomic call RXFIFO_RAM.read(pos,(uint8_t*)&header, 3);
+ call CSN.set();
+ }
+
+ packetLength = header.length+1;
+
+ if(packetLength == 6){ // ACK packet
+ m_state = S_RX_LENGTH;
+ call SpiResource.release();
+ beginReceive();
+ return;
+ }
+
+ if (pos + sizeof(cc2420_header_t) > RXFIFO_SIZE){
+ temp = RXFIFO_SIZE - pos;
+ call CSN.clr();
+ atomic call RXFIFO_RAM.read(pos,(uint8_t*)&header, temp);
+ call CSN.set();
+ call CSN.clr();
+ atomic call RXFIFO_RAM.read(0,(uint8_t*)&header+temp, sizeof(cc2420_header_t)-temp);
+ call CSN.set();
+ }else{
+ call CSN.clr();
+ atomic call RXFIFO_RAM.read(pos,(uint8_t*)&header, sizeof(cc2420_header_t));
+ call CSN.set();
+ }
+
+ if (pos+header.length+1 > RXFIFO_SIZE){
+ temp = header.length - (RXFIFO_SIZE - pos);
+ call CSN.clr();
+ atomic call RXFIFO_RAM.read(temp,&crc, 1);
+ call CSN.set();
+ }else{
+ call CSN.clr();
+ atomic call RXFIFO_RAM.read(pos+header.length,&crc, 1);
+ call CSN.set();
+ }
+
+ if(header.length+1 > RXFIFO_SIZE || !(crc << 7)){
+ atomic flush_flag = 1;
+ m_state = S_RX_LENGTH;
+ call SpiResource.release();
+ beginReceive();
+ return;
+ }
+ if( (header.fcf & (1 << IEEE154_FCF_SECURITY_ENABLED)) && (crc << 7) ){
+ if(call CC2420Config.isAddressRecognitionEnabled()){
+ if(!(header.dest==call CC2420Config.getShortAddr() || header.dest==AM_BROADCAST_ADDR)){
+ packetLength = header.length + 1;
+ m_state = S_RX_LENGTH;
+ call SpiResource.release();
+ beginReceive();
+ return;
+ }
+ }
+ if(SECURITYLOCK == 1){
+ call SpiResource.release();
+ post waitTask();
+ return;
+ }else{
+ //We are going to decrypt so lock the registers
+ atomic SECURITYLOCK = 1;
+
+ if (secHdrPos + sizeof(security_header_t) > RXFIFO_SIZE){
+ temp = RXFIFO_SIZE - secHdrPos;
+ call CSN.clr();
+ atomic call RXFIFO_RAM.read(secHdrPos,(uint8_t*)&secHdr, temp);
+ call CSN.set();
+ call CSN.clr();
+ atomic call RXFIFO_RAM.read(0,(uint8_t*)&secHdr+temp, sizeof(security_header_t) - temp);
+ call CSN.set();
+ } else {
+ call CSN.clr();
+ atomic call RXFIFO_RAM.read(secHdrPos,(uint8_t*)&secHdr, sizeof(security_header_t));
+ call CSN.set();
+ }
+
+ key = secHdr.keyID[0];
+
+ if (secHdr.secLevel == NO_SEC){
+ mode = CC2420_NO_SEC;
+ micLength = 0;
+ }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 = 0;
+ }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{
+ atomic SECURITYLOCK = 0;
+ packetLength = header.length + 1;
+ m_state = S_RX_LENGTH;
+ call SpiResource.release();
+ beginReceive();
+ return;
+ }
+
+ if(mode < 4 && mode > 0) { // if mode is valid