/**
* \file mimac_at86rf.c
*
* \brief MAC Layer Abstraction for AT86RFx implementation
*
* Copyright (c) 2018 - 2019 Microchip Technology Inc. and its subsidiaries.
*
* \asf_license_start
*
* \page License
*
* Subject to your compliance with these terms, you may use Microchip
* software and any derivatives exclusively with Microchip products.
* It is your responsibility to comply with third party license terms applicable
* to your use of third party software (including open source software) that
* may accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*
* \asf_license_stop
*
*/
/*
* Support and FAQ: visit Microchip Support
*/
#include
#include
#include
#include "miwi_config.h"
#if defined(PROTOCOL_P2P) || defined (PROTOCOL_STAR)
#include "miwi_config_p2p.h" //MiWi Protocol layer configuration file
#endif
#include "delay.h"
#include "sal.h"
#include "phy.h"
#include "mimac_at86rf.h"
#if defined(ENABLE_NETWORK_FREEZER)
#include "pdsDataServer.h"
#endif
#ifdef ENABLE_SECURITY
const char mySecurityKey[16] = {SECURITY_KEY_00, SECURITY_KEY_01, SECURITY_KEY_02, SECURITY_KEY_03, SECURITY_KEY_04,
SECURITY_KEY_05, SECURITY_KEY_06, SECURITY_KEY_07, SECURITY_KEY_08, SECURITY_KEY_09, SECURITY_KEY_10, SECURITY_KEY_11,
SECURITY_KEY_12, SECURITY_KEY_13, SECURITY_KEY_14, SECURITY_KEY_15};
uint8_t final_mic_value[16] , CBC_mic[16] , CTR_mic[16];
uint8_t InitVect_in[16];
const uint8_t myKeySequenceNumber = KEY_SEQUENCE_NUMBER; // The sequence number of security key. Used to identify the security key
API_UINT32_UNION OutgoingFrameCounter;
#endif
/*- Variables --------------------------------------------------------------*/
uint8_t MACCurrentChannel;
API_UINT16_UNION MAC_PANID;
API_UINT16_UNION myNetworkAddress;
uint8_t IEEESeqNum;
MACINIT_PARAM MACInitParams;
uint8_t BankIndex = 0xFF;
// Mic Size is 4 bytes.
uint8_t calculated_mic_values[AES_BLOCKSIZE/4];
uint8_t received_mic_values[AES_BLOCKSIZE/4];
bool dataConfAvailable = 0;
miwi_status_t dataStatus;
uint8_t dataHandle = 0;
uint8_t* dataPointer = NULL;
DataConf_callback_t dataConfCallback = NULL;
/************************************************************************************
* Function:
* bool MiMAC_SetAltAddress(uint8_t *Address, uint8_t *PANID)
*
* Summary:
* This function set the alternative network address and PAN identifier if
* applicable
*
* Description:
* This is the primary MiMAC interface for the protocol layer to
* set alternative network address and/or PAN identifier. This function
* call applies to only IEEE 802.15.4 compliant RF transceivers. In case
* alternative network address is not supported, this function will return
* FALSE.
*
* PreCondition:
* MiMAC initialization has been done.
*
* Parameters:
* uint8_t * Address - The alternative network address of the host device.
* uint8_t * PANID - The PAN identifier of the host device
*
* Returns:
* A boolean to indicates if setting alternative network address is successful.
*
* Example:
*
* uint16_t NetworkAddress = 0x0000;
* uint16_t PANID = 0x1234;
* MiMAC_SetAltAddress(&NetworkAddress, &PANID);
*
*
* Remarks:
* None
*
*****************************************************************************************/
bool MiMAC_SetAltAddress( uint8_t *Address, uint8_t *PanId)
{
myNetworkAddress.v[0] = Address[0];
myNetworkAddress.v[1] = Address[1];
MAC_PANID.v[0] = PanId[0];
MAC_PANID.v[1] = PanId[1];
PHY_SetShortAddr(myNetworkAddress.Val);
PHY_SetPanId(MAC_PANID.Val);
return true;
}
#if defined (ENABLE_SECURITY)
uint8_t addr[8] = {0xda , 0x98 , 0x22 , 0xfe , 0xff , 0xa3 , 0x04 , 0x00};
void mic_generator (uint8_t *Payloadinfo, uint8_t len , uint8_t frame_control , API_UINT32_UNION FrameCounter , uint8_t *SourceIEEEAddress)
{
uint8_t i , j , iterations , copy_packet1[128] , cbc_header_with_padding[16];
// Calculating No of blocks in the packet (1 block = 16 bytes of data)
iterations = len/16;
if (len % 16 != 0) iterations++;
InitVect_in[0] = 0x49;//frame_control;
cbc_header_with_padding[0] = 0x00; // l(a)
cbc_header_with_padding[1] = 0x0d; // l(a)Header Length
cbc_header_with_padding[2] = frame_control; //frame_control; //byte 1
for (i=0;i<8;i++)
{
InitVect_in[i+1] = SourceIEEEAddress[i];
cbc_header_with_padding[i+7] = SourceIEEEAddress[i];
}
for (i=0;i<4;i++)
{
InitVect_in[i+9] = FrameCounter.v[i];
cbc_header_with_padding[i+3] = FrameCounter.v[i];
}
//cbc_header_with_padding[14] = 0x00; // Padding
cbc_header_with_padding[15] = 0x00; // Padding
InitVect_in[13] = SECURITY_LEVEL; //Security Mode // 0x04 --> CCM-32
InitVect_in[14] = 0x00; // 15 th byte padded to zero
InitVect_in[15] = len; // For MIC calculation All preceding blocks will be incremented by 1
PHY_EncryptReq(&InitVect_in[0], (uint8_t *)mySecurityKey);
for (i=0;i<16;i++)
{
copy_packet1[i] = cbc_header_with_padding[i];
}
// Copy the Payload and Do the padding
for (i=16;i
* DataEncrypt(key, payload, &payloadLen, FrameCounter, FrameControl);
*
*
* Remarks:
* None
*
*****************************************************************************************/
bool DataEncrypt(uint8_t *Payloadinfo, uint8_t *Payload_len, API_UINT32_UNION FrameCounter,
uint8_t FrameControl)
{
uint8_t i , iterations , block[16] , j , CTR_Nonce_and_Counter[16], CipheringData[CALC_SEC_PAYLOAD_SIZE(TX_BUFFER_SIZE)];
// Calculating No of blocks in the packet (1 block = 16 bytes of data)
iterations = *Payload_len/16;
if (*Payload_len % 16 != 0) iterations++;
// Copy payload for security processing
memcpy(CipheringData, Payloadinfo, *Payload_len);
mic_generator(&Payloadinfo[0] , *Payload_len, FrameControl , FrameCounter , MACInitParams.PAddress);
for (i=*Payload_len;i CCM-32
CTR_Nonce_and_Counter[14] = 0x00; // 15 th byte padded to zero
CTR_Nonce_and_Counter[15] = 0x00; // For MIC calculation All preceding blocks will be incremented by 1
for (i=0;i
* DataDecrypt(key, payload, &payloadLen, SourceIEEEAddr, FrameCounter, FrameControl);
*
*
* Remarks:
* None
*
*****************************************************************************************/
bool DataDecrypt(uint8_t *Payload, uint8_t *PayloadLen, uint8_t *SourceIEEEAddress,
API_UINT32_UNION FrameCounter, uint8_t FrameControl)
{
uint8_t i , iterations , block[16] , j , CTR_Nonce_and_Counter[16], CipheringData[CALC_SEC_PAYLOAD_SIZE(RX_BUFFER_SIZE)];
// Calculating No of blocks in the packet (1 block = 16 bytes of data)
iterations = *PayloadLen/16;
if (*PayloadLen % 16 != 0) iterations++;
// Copy payload for security processing
memcpy(CipheringData, Payload, *PayloadLen);
//mic_generator(&Payloadinfo[0] , *Payload_len);
for (i=*PayloadLen;i
* // Put RF transceiver into sleep
* MiMAC_PowerState(POWER_STATE_DEEP_SLEEP);
* // Put MCU to sleep
* Sleep();
* // Wake up the MCU by WDT, external interrupt or any other means
*
* // Wake up the RF transceiver
* MiMAC_PowerState(POWER_STATE_OPERATE);
*
*
* Remarks:
* None
*
*****************************************************************************************/
bool MiMAC_PowerState(INPUT uint8_t PowerState)
{
switch (PowerState)
{
case POWER_STATE_DEEP_SLEEP:
{
//;clear the WAKE pin in order to allow the device to go to sleep
PHY_Sleep();
}
break;
case POWER_STATE_OPERATE:
{
PHY_Wakeup();
}
break;
default:
return false;
}
return true;
}
/************************************************************************************
* Function:
* bool MiMAC_Set(mac_set_params_t id, uint8_t *value);
*
* Summary:
* This function sets the values
*
* Description:
* This is the primary MiMAC interface for the protocol layer to
* set the valuesr. for ex:Valid channel
* number are from 0 to 31. For different frequency band, data rate
* and other RF settings, some channels from 0 to 31 might be
* unavailable. Paramater offsetFreq is used to fine tune the center
* frequency across the frequency band. For transceivers that follow
* strict definition of channels, this parameter may be discarded.
* The center frequency is calculated as
* (LowestFrequency + Channel * ChannelGap + offsetFreq)
*
* PreCondition:
* Hardware initialization on MCU has been done.
*
* Parameters:
* set_params id - The identifier of the value to be set
* value - value to be set
*
* Returns:
* A boolean to indicates if channel setting is successful.
*
* Example:
*
* // Set center frequency to be exactly channel 12
* MiMAC_Set(CHANNEL, &channel);
*
*
* Remarks:
* None
*
*****************************************************************************************/
bool MiMAC_Set(mac_set_params_t id, uint8_t *value)
{
switch(id)
{
case MAC_CHANNEL:
{
if(*value > 26) //TODO: this check is necessary here? as we may connect a sub-gig or a 2.4gig?
{
return false;
}
MACCurrentChannel = *value;
PHY_SetChannel(MACCurrentChannel);
return true;
}
break;
default:
break;
}
return false;
}
/************************************************************************************
* Function:
* bool MiMAC_Init(MACINIT_PARAM initValue)
*
* Summary:
* This function initialize MiMAC layer
*
* Description:
* This is the primary MiMAC interface for the protocol layer to
* initialize the MiMAC layer. The initialization parameter is
* assigned in the format of structure MACINIT_PARAM.
*
* PreCondition:
* MCU initialization has been done.
*
* Parameters:
* MACINIT_PARAM initValue - Initialization value for MiMAC layer
*
* Returns:
* A boolean to indicates if initialization is successful.
*
* Example:
*
* MiMAC_Init(initParameter);
*
*
* Remarks:
* None
*
*****************************************************************************************/
bool MiMAC_Init(MACINIT_PARAM initValue)
{
uint8_t i;
PHY_Init();
MACInitParams = initValue;
uint16_t x = PHY_RandomReq();
// Set RF mode
PHY_SetRxState(true);
IEEESeqNum = x & 0xff;
// Set Node Address
PHY_SetIEEEAddr(MACInitParams.PAddress);
for (i = 0; i < BANK_SIZE; i++)
{
RxBuffer[i].PayloadLen = 0;
}
#ifdef ENABLE_SECURITY
#if defined(ENABLE_NETWORK_FREEZER)
if (initValue.actionFlags.bits.NetworkFreezer)
{
PDS_Restore(PDS_OUTGOING_FRAME_COUNTER_ID);
OutgoingFrameCounter.Val += FRAME_COUNTER_UPDATE_INTERVAL;
PDS_Store(PDS_OUTGOING_FRAME_COUNTER_ID);
} else
{
OutgoingFrameCounter.Val = 0;
PDS_Store(PDS_OUTGOING_FRAME_COUNTER_ID);
OutgoingFrameCounter.Val = 1;
}
#else
OutgoingFrameCounter.Val = 1;
#endif
#endif
return true;
}
/************************************************************************************
* Function:
* BOOL MiMAC_SendPacket( MAC_TRANS_PARAM transParam,
* uint8_t *MACPayload, uint8_t MACPayloadLen,
uint8_t msghandle,MiMacDataConf_callback_t ConfCallback)
*
* Summary:
* This function transmit a packet
*
* Description:
* This is the primary MiMAC interface for the protocol layer to
* send a packet. Input parameter transParam configure the way
* to transmit the packet.
*
* PreCondition:
* MiMAC initialization has been done.
*
* Parameters:
* MAC_TRANS_PARAM transParam - The struture to configure the transmission way
* uint8_t * MACPaylaod - Pointer to the buffer of MAC payload
* uint8_t MACPayloadLen - The size of the MAC payload
* uint8_t msghandle Message handle
* MiMacDataConf_callback_t ConfCallback Callback function to be called once packet is sent
*
* Returns:
* A boolean to indicate if a packet has been received by the RF transceiver.
*
* Example:
*
* MiMAC_SendPacket(transParam, MACPayload, MACPayloadLen, 6, callback);
*
*
* Remarks:
* None
*
*****************************************************************************************/
uint8_t packet[128];//temp buffer
bool MiMAC_SendPacket( MAC_TRANS_PARAM transParam,
uint8_t *MACPayload,
uint8_t MACPayloadLen, uint8_t msghandle,
DataConf_callback_t ConfCallback)
{
uint8_t headerLength;
uint8_t loc = 0;
uint8_t i = 0;
uint8_t frameControl = 0;
PHY_DataReq_t phyDataRequest;
#ifndef TARGET_SMALL
bool IntraPAN;
#endif
if (transParam.flags.bits.broadcast)
{
transParam.altDestAddr = true;
}
#if !defined(PROTOCOL_MESH)
if (transParam.flags.bits.secEn)
{
transParam.altSrcAddr = false;
}
#endif
// set the frame control in variable i
if (transParam.flags.bits.packetType == PACKET_TYPE_COMMAND)
{
frameControl = 0x03;
} else if (transParam.flags.bits.packetType == PACKET_TYPE_DATA)
{
frameControl = 0x01;
}
// decide the header length for different addressing mode
#ifndef TARGET_SMALL
if ((transParam.DestPANID.Val == MAC_PANID.Val) && (MAC_PANID.Val != 0xFFFF)) // this is intraPAN
#endif
{
headerLength = 5;
frameControl |= 0x40;
#ifndef TARGET_SMALL
IntraPAN = true;
#endif
}
#ifndef TARGET_SMALL
else
{
headerLength = 7;
IntraPAN = false;
}
#endif
if (transParam.altDestAddr)
{
headerLength += 2;
} else
{
headerLength += 8;
}
if (transParam.altSrcAddr)
{
headerLength += 2;
} else
{
headerLength += 8;
}
if (transParam.flags.bits.ackReq && transParam.flags.bits.broadcast == false)
{
frameControl |= 0x20;
}
// use PACKET_TYPE_RESERVE to represent beacon. Fixed format for beacon packet
if (transParam.flags.bits.packetType == PACKET_TYPE_RESERVE)
{
frameControl = 0x00;
headerLength = 7;
#if !defined(TARGET_SMALL)
IntraPAN = false;
#endif
transParam.altSrcAddr = true;
transParam.flags.bits.ackReq = false;
}
#ifdef ENABLE_SECURITY
if (transParam.flags.bits.secEn)
{
frameControl |= 0x08;
DataEncrypt(MACPayload, &MACPayloadLen, OutgoingFrameCounter, frameControl);
}
#endif
// set packet length
#ifdef ENABLE_SECURITY
if (transParam.flags.bits.secEn)
{
// 4 byte mic and 5 byte outgoing frame counter
packet[loc++] = MACPayloadLen+headerLength+9;
} else
#endif
{
packet[loc++] = MACPayloadLen+headerLength;
}
// set frame control LSB
packet[loc++] = frameControl;
// set frame control MSB
if (transParam.flags.bits.packetType == PACKET_TYPE_RESERVE)
{
packet[loc++] = 0x80;
// sequence number
packet[loc++] = IEEESeqNum++;
} else
{
if (transParam.altDestAddr && transParam.altSrcAddr)
{
packet[loc++] = 0x88;
} else if (transParam.altDestAddr && transParam.altSrcAddr == 0)
{
packet[loc++] = 0xC8;
} else if (transParam.altDestAddr == 0 && transParam.altSrcAddr == 1)
{
packet[loc++] = 0x8C;
} else
{
packet[loc++] = 0xCC;
}
// sequence number
packet[loc++] = IEEESeqNum++;
// destination PANID
packet[loc++] = transParam.DestPANID.v[0];
packet[loc++] = transParam.DestPANID.v[1];
// destination address
if (transParam.flags.bits.broadcast)
{
packet[loc++] = 0xFF;
packet[loc++] = 0xFF;
} else
{
if (transParam.altDestAddr)
{
packet[loc++] = transParam.DestAddress[0];
packet[loc++] = transParam.DestAddress[1];
} else
{
for (i = 0; i < 8; i++)
{
packet[loc++] = transParam.DestAddress[i];
}
}
}
}
#ifndef TARGET_SMALL
// source PANID if necessary
if (IntraPAN == false)
{
packet[loc++] = MAC_PANID.v[0];
packet[loc++] = MAC_PANID.v[1];
}
#endif
// source address
if (transParam.altSrcAddr)
{
packet[loc++] = myNetworkAddress.v[0];
packet[loc++] = myNetworkAddress.v[1];
} else
{
for (i = 0; i < 8; i++)
{
packet[loc++] = MACInitParams.PAddress[i];
}
}
#ifdef ENABLE_SECURITY
if (transParam.flags.bits.secEn)
{
// fill the additional security aux header
for (i = 0; i < 4; i++)
{
packet[loc++] = OutgoingFrameCounter.v[i];
}
OutgoingFrameCounter.Val++;
#if defined(ENABLE_NETWORK_FREEZER)
if ((OutgoingFrameCounter.v[0] == 0) && ((OutgoingFrameCounter.v[1] & 0x03) == 0))
{
PDS_Store(PDS_OUTGOING_FRAME_COUNTER_ID);
}
#endif
//copy myKeySequenceNumber
packet[loc++] = myKeySequenceNumber;
}
#endif
#ifndef ENABLE_SECURITY
// write the payload
for (i = 0; i < MACPayloadLen; i++)
{
packet[loc++] = MACPayload[i];
}
#else
// write the payload
for (i = 0; i < MACPayloadLen; i++) // MIC added
{
packet[loc++] = MACPayload[i];
}
packet[loc++] = final_mic_value[0];
packet[loc++] = final_mic_value[1];
packet[loc++] = final_mic_value[2];
packet[loc++] = final_mic_value[3];
#endif
// set the trigger value
if (transParam.flags.bits.ackReq && transParam.flags.bits.broadcast == false)
{
i = 0x05;
} else
{
i = 0x01;
}
dataPointer = MACPayload;
dataConfCallback = ConfCallback;
dataHandle = msghandle;
phyDataRequest.polledConfirmation = false;
phyDataRequest.confirmCallback = PHY_DataConf;
phyDataRequest.data = packet;
// Now Trigger the Transmission of packet
PHY_DataReq(&phyDataRequest);
return true;
}
/************************************************************************************
* Function:
* void MiMAC_DiscardPacket(void)
*
* Summary:
* This function discard the current packet received from the RF transceiver
*
* Description:
* This is the primary MiMAC interface for the protocol layer to
* discard the current packet received from the RF transceiver.
*
* PreCondition:
* MiMAC initialization has been done.
*
* Parameters:
* None
*
* Returns:
* None
*
* Example:
*
* if( true == MiMAC_ReceivedPacket() )
* {
* // handle the raw data from RF transceiver
*
* // discard the current packet
* MiMAC_DiscardPacket();
* }
*
*
* Remarks:
* None
*
*****************************************************************************************/
void MiMAC_DiscardPacket(void)
{
//re-enable buffer for next packets
if (BankIndex < BANK_SIZE)
{
RxBuffer[BankIndex].PayloadLen = 0;
}
}
/************************************************************************************
* Function:
* bool MiMAC_ReceivedPacket(void)
*
* Summary:
* This function check if a new packet has been received by the RF transceiver
*
* Description:
* This is the primary MiMAC interface for the protocol layer to
* check if a packet has been received by the RF transceiver. When a packet has
* been received, all information will be stored in the global variable
* MACRxPacket in the format of MAC_RECEIVED_PACKET;
*
* PreCondition:
* MiMAC initialization has been done.
*
* Parameters:
* None
*
* Returns:
* A boolean to indicate if a packet has been received by the RF transceiver.
*
* Example:
*
* if( true == MiMAC_ReceivedPacket() )
* {
* // handle the raw data from RF transceiver
*
* // discard the current packet
* MiMAC_DiscardPacket();
* }
*
*
* Remarks:
* None
*
*****************************************************************************************/
bool MiMAC_ReceivedPacket(void)
{
uint8_t i;
BankIndex = 0xFF;
for (i = 0; i < BANK_SIZE; i++)
{
if (RxBuffer[i].PayloadLen > 0)
{
BankIndex = i;
break;
}
}
if (BankIndex < BANK_SIZE)
{
uint8_t addrMode;
#ifndef TARGET_SMALL
bool bIntraPAN = true;
if ((RxBuffer[BankIndex].Payload[0] & 0x40) == 0)
{
bIntraPAN = false;
}
#endif
MACRxPacket.flags.Val = 0;
MACRxPacket.altSourceAddress = false;
MACRxPacket.SourcePANID.Val = 0xFFFF;
//Determine the start of the MAC payload
addrMode = RxBuffer[BankIndex].Payload[1] & 0xCC;
switch (addrMode)
{
case 0xC8: //short dest, long source
// for P2P only broadcast allows short destination address
if (RxBuffer[BankIndex].Payload[5] == 0xFF && RxBuffer[BankIndex].Payload[6] == 0xFF)
{
MACRxPacket.flags.bits.broadcast = 1;
}
MACRxPacket.flags.bits.sourcePrsnt = 1;
#ifndef TARGET_SMALL
if (bIntraPAN) // check if it is intraPAN
#endif
{
#ifndef TARGET_SMALL
MACRxPacket.SourcePANID.v[0] = RxBuffer[BankIndex].Payload[3];
MACRxPacket.SourcePANID.v[1] = RxBuffer[BankIndex].Payload[4];
#endif
MACRxPacket.SourceAddress = &(RxBuffer[BankIndex].Payload[7]);
MACRxPacket.PayloadLen = RxBuffer[BankIndex].PayloadLen - 19;
MACRxPacket.Payload = &(RxBuffer[BankIndex].Payload[15]);
}
#ifndef TARGET_SMALL
else
{
MACRxPacket.SourcePANID.v[0] = RxBuffer[BankIndex].Payload[7];
MACRxPacket.SourcePANID.v[1] = RxBuffer[BankIndex].Payload[8];
MACRxPacket.SourceAddress = &(RxBuffer[BankIndex].Payload[9]);
MACRxPacket.PayloadLen = RxBuffer[BankIndex].PayloadLen - 21;
MACRxPacket.Payload = &(RxBuffer[BankIndex].Payload[17]);
}
#endif
break;
case 0xCC: // long dest, long source
MACRxPacket.flags.bits.sourcePrsnt = 1;
#ifndef TARGET_SMALL
if (bIntraPAN) // check if it is intraPAN
#endif
{
//rxFrame.flags.bits.intraPAN = 1;
#ifndef TARGET_SMALL
MACRxPacket.SourcePANID.v[0] = RxBuffer[BankIndex].Payload[3];
MACRxPacket.SourcePANID.v[1] = RxBuffer[BankIndex].Payload[4];
#endif
MACRxPacket.SourceAddress = &(RxBuffer[BankIndex].Payload[13]);
MACRxPacket.PayloadLen = RxBuffer[BankIndex].PayloadLen - 25;
MACRxPacket.Payload = &(RxBuffer[BankIndex].Payload[21]);
}
#ifndef TARGET_SMALL
else
{
MACRxPacket.SourcePANID.v[0] = RxBuffer[BankIndex].Payload[13];
MACRxPacket.SourcePANID.v[1] = RxBuffer[BankIndex].Payload[14];
MACRxPacket.SourceAddress = &(RxBuffer[BankIndex].Payload[15]);
MACRxPacket.PayloadLen = RxBuffer[BankIndex].PayloadLen - 27;
MACRxPacket.Payload = &(RxBuffer[BankIndex].Payload[23]);
}
#endif
break;
case 0x80: // short source only. used in beacon
{
MACRxPacket.flags.bits.broadcast = 1;
MACRxPacket.flags.bits.sourcePrsnt = 1;
MACRxPacket.altSourceAddress = true;
MACRxPacket.SourcePANID.v[0] = RxBuffer[BankIndex].Payload[3];
MACRxPacket.SourcePANID.v[1] = RxBuffer[BankIndex].Payload[4];
MACRxPacket.SourceAddress = &(RxBuffer[BankIndex].Payload[5]);
MACRxPacket.PayloadLen = RxBuffer[BankIndex].PayloadLen - 11;
MACRxPacket.Payload = &(RxBuffer[BankIndex].Payload[7]);
}
break;
case 0x88: // short dest, short source
{
if (RxBuffer[BankIndex].Payload[5] == 0xFF && RxBuffer[BankIndex].Payload[6] == 0xFF)
{
MACRxPacket.flags.bits.broadcast = 1;
}
MACRxPacket.flags.bits.sourcePrsnt = 1;
MACRxPacket.altSourceAddress = true;
#ifndef TARGET_SMALL
if (bIntraPAN == false)
{
MACRxPacket.SourcePANID.v[0] = RxBuffer[BankIndex].Payload[7];
MACRxPacket.SourcePANID.v[1] = RxBuffer[BankIndex].Payload[8];
MACRxPacket.SourceAddress = &(RxBuffer[BankIndex].Payload[9]);
MACRxPacket.PayloadLen = RxBuffer[BankIndex].PayloadLen - 15;
MACRxPacket.Payload = &(RxBuffer[BankIndex].Payload[11]);
} else
#endif
{
MACRxPacket.SourcePANID.v[0] = RxBuffer[BankIndex].Payload[3];
MACRxPacket.SourcePANID.v[1] = RxBuffer[BankIndex].Payload[4];
MACRxPacket.SourceAddress = &(RxBuffer[BankIndex].Payload[7]);
MACRxPacket.PayloadLen = RxBuffer[BankIndex].PayloadLen - 13;
MACRxPacket.Payload = &(RxBuffer[BankIndex].Payload[9]);
}
}
break;
case 0x8C: // long dest, short source
{
MACRxPacket.flags.bits.sourcePrsnt = 1;
MACRxPacket.altSourceAddress = true;
#ifndef TARGET_SMALL
if (bIntraPAN) // check if it is intraPAN
#endif
{
#ifndef TARGET_SMALL
MACRxPacket.SourcePANID.v[0] = RxBuffer[BankIndex].Payload[3];
MACRxPacket.SourcePANID.v[1] = RxBuffer[BankIndex].Payload[4];
#endif
#if defined(PROTOCOL_MESH)
MACRxPacket.SourceAddress = &(RxBuffer[BankIndex].Payload[13]);
#else
MACRxPacket.SourceAddress = &(RxBuffer[BankIndex].Payload[12]);
#endif
MACRxPacket.PayloadLen = RxBuffer[BankIndex].PayloadLen - 19;
MACRxPacket.Payload = &(RxBuffer[BankIndex].Payload[15]);
}
#ifndef TARGET_SMALL
else
{
MACRxPacket.SourcePANID.v[0] = RxBuffer[BankIndex].Payload[12];
MACRxPacket.SourcePANID.v[1] = RxBuffer[BankIndex].Payload[13];
MACRxPacket.SourceAddress = &(RxBuffer[BankIndex].Payload[14]);
MACRxPacket.PayloadLen = RxBuffer[BankIndex].PayloadLen - 21;
MACRxPacket.Payload = &(RxBuffer[BankIndex].Payload[17]);
}
#endif
}
break;
case 0x08: //dest-short, source-none
{
if (RxBuffer[BankIndex].Payload[5] == 0xFF && RxBuffer[BankIndex].Payload[6] == 0xFF)
{
MACRxPacket.flags.bits.broadcast = 1;
}
MACRxPacket.PayloadLen = RxBuffer[BankIndex].PayloadLen - 10;
MACRxPacket.Payload = &(RxBuffer[BankIndex].Payload[7]);
}
break;
// all other addressing mode will not be supported in P2P
default:
// not valid addressing mode or no addressing info
MiMAC_DiscardPacket();
return false;
}
#ifdef ENABLE_SECURITY
if (RxBuffer[BankIndex].Payload[0] & 0x08)
{
API_UINT32_UNION FrameCounter;
if (addrMode < 0xC0)
{
MiMAC_DiscardPacket();
return false;
}
FrameCounter.v[0] = MACRxPacket.Payload[0];
FrameCounter.v[1] = MACRxPacket.Payload[1];
FrameCounter.v[2] = MACRxPacket.Payload[2];
FrameCounter.v[3] = MACRxPacket.Payload[3];
for (i = 0; i < CONNECTION_SIZE; i++)
{
if ((defaultParamsRomOrRam.ConnectionTable[i].status.bits.isValid) &&
isSameAddress(defaultParamsRomOrRam.ConnectionTable[i].Address, MACRxPacket.SourceAddress))
{
break;
}
}
if (i < CONNECTION_SIZE)
{
if (IncomingFrameCounter[i].Val > FrameCounter.Val)
{
MiMAC_DiscardPacket();
return false;
} else
{
IncomingFrameCounter[i].Val = FrameCounter.Val;
}
}
MACRxPacket.PayloadLen -= 5; // used to 5 for frame counter now -4 also added for MIC integrity
received_mic_values[0] = MACRxPacket.Payload[MACRxPacket.PayloadLen+1];
received_mic_values[1] = MACRxPacket.Payload[MACRxPacket.PayloadLen+2];
received_mic_values[2] = MACRxPacket.Payload[MACRxPacket.PayloadLen+3];
received_mic_values[3] = MACRxPacket.Payload[MACRxPacket.PayloadLen+4];
//MACRxPacket.PayloadLen -= 4;
if (false == DataDecrypt(&(MACRxPacket.Payload[5]), &(MACRxPacket.PayloadLen), MACRxPacket.SourceAddress, FrameCounter, RxBuffer[BankIndex].Payload[0]))
{
MiMAC_DiscardPacket();
return false;
}
// remove the security header from the payload
MACRxPacket.Payload = &(MACRxPacket.Payload[5]);
MACRxPacket.flags.bits.secEn = 1;
}
#else
if (RxBuffer[BankIndex].Payload[0] & 0x08)
{
MiMAC_DiscardPacket();
return false;
}
#endif
// check the frame type. Only the data and command frame type
// are supported. Acknowledgement frame type is handled in
// AT96RF233 transceiver hardware.
switch (RxBuffer[BankIndex].Payload[0] & 0x07) // check frame type
{
case 0x01: // data frame
MACRxPacket.flags.bits.packetType = PACKET_TYPE_DATA;
break;
case 0x03: // command frame
MACRxPacket.flags.bits.packetType = PACKET_TYPE_COMMAND;
break;
case 0x00:
// use reserved packet type to represent beacon packet
MACRxPacket.flags.bits.packetType = PACKET_TYPE_RESERVE;
break;
default: // not support frame type
MiMAC_DiscardPacket();
return false;
}
#ifndef TARGET_SMALL
MACRxPacket.LQIValue = RxBuffer[BankIndex].Payload[RxBuffer[BankIndex].PayloadLen - 2];
MACRxPacket.RSSIValue = RxBuffer[BankIndex].Payload[RxBuffer[BankIndex].PayloadLen - 1];
#endif
return true;
}
return false;
}
/************************************************************************************
* Function:
* uint8_t MiMAC_ChannelAssessment(uint8_t AssessmentMode)
*
* Summary:
* This function perform the noise detection on current operating channel
*
* Description:
* This is the primary MiMAC interface for the protocol layer to
* perform the noise detection scan. Not all assessment modes are supported
* for all RF transceivers.
*
* PreCondition:
* MiMAC initialization has been done.
*
* Parameters:
* uint8_t AssessmentMode - The mode to perform noise assessment. The possible
* assessment modes are
* * CHANNEL_ASSESSMENT_CARRIER_SENSE Carrier sense detection mode
* * CHANNEL_ASSESSMENT_ENERGY_DETECT Energy detection mode
*
* Returns:
* A byte to indicate the noise level at current channel.
*
* Example:
*
* NoiseLevel = MiMAC_ChannelAssessment(CHANNEL_ASSESSMENT_CARRIER_SENSE);
*
*
* Remarks:
* None
*
*****************************************************************************************/
uint8_t MiMAC_ChannelAssessment(uint8_t AssessmentMode)
{
if( AssessmentMode == CHANNEL_ASSESSMENT_ENERGY_DETECT)
{
uint8_t ed;
ed = PHY_EdReq();
//printf(" %u ", ed);
return ed;
}
return 0;
}
/************************************************************************************
* Function:
* uint32_t MiMAC_SymbolToTicks(uint32_t symbols)
*
* Summary:
* This function converts symbol to ticks
*
* Description:
* This is the primary MiMAC interface for the protocol layer to
* convert symbol to ticks for all RF transceivers.
*
* Parameters:
* uint8_t symbols - The number of symbols to convert
*
* Returns:
* converted value in uint32.
*****************************************************************************************/
uint32_t MiMAC_SymbolToTicks(uint32_t symbols)
{
return SYMBOLS_TO_TICKS(symbols);
}
/************************************************************************************
* Function:
* uint32_t MiMAC_GetPHYChannelInfo(uint32_t supportedChannelMap)
*
* Summary:
* This function gets the supported channel map
*
* Description:
* This is the primary MiMAC interface for the protocol layer to
* get the supported channel mask
*
* Parameters:
* None
*
* Returns:
* channel map uint32.
*****************************************************************************************/
uint32_t MiMAC_GetPHYChannelInfo(void)
{
uint32_t channelMap = FULL_CHANNEL_MAP;
return channelMap;
}
/************************************************************************************
* Function:
* void PHY_DataConf(uint8_t status)
*
* Summary:
* This function returns the confirmation of the packet sent
*
* PreCondition:
* MCU initialization has been done.
*
* Parameters:
* status - status of the transmit operation
*
* Returns:
* None.
*
* Remarks:
* None
*
*****************************************************************************************/
void PHY_DataConf(uint8_t status)
{
dataStatus = (miwi_status_t)status;
dataConfAvailable = true;
}
void MiMAC_Task(void)
{
PHY_TaskHandler();
if(dataConfCallback && dataConfAvailable)
{
dataConfCallback(dataHandle, dataStatus, dataPointer);
dataConfAvailable = false;
}
}