Files
TencentOS-tiny/components/connectivity/LoraWAN/mac/LoRaMacFCntHandler.c
supowang edb2879617 first commit for opensource
first commit for opensource
2019-09-16 13:19:50 +08:00

320 lines
9.0 KiB
C

/*
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
___ _____ _ ___ _ _____ ___ ___ ___ ___
/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
embedded.connectivity.solutions===============
Description: LoRa MAC layer frame counter handling implementation
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis ( Semtech ), Daniel Jaeckle ( STACKFORCE ), Johannes Bruder ( STACKFORCE )
*/
#include <string.h>
#include "utilities.h"
#include "LoRaMacFCntHandler.h"
/*
* Initial value of the frame counters
*/
#define FCNT_DOWN_INITAL_VALUE 0xFFFFFFFF
/*!
* LoRaWAN Frame counter list.
*/
typedef struct sFCntList
{
/*
* Uplink frame counter which is incremented with each uplink.
*/
uint32_t FCntUp;
/*
* Network downlink frame counter which is incremented with each downlink on FPort 0
* or when the FPort field is missing.
*/
uint32_t NFCntDown;
/*
* Application downlink frame counter which is incremented with each downlink
* on a port different than 0.
*/
uint32_t AFCntDown;
/*
* In case if the device is connected to a LoRaWAN 1.0 Server,
* this counter is used for every kind of downlink frame.
*/
uint32_t FCntDown;
/*!
* Multicast downlink counter for index 0
*/
uint32_t McFCntDown0;
/*!
* Multicast downlink counter for index 1
*/
uint32_t McFCntDown1;
/*!
* Multicast downlink counter for index 2
*/
uint32_t McFCntDown2;
/*!
* Multicast downlink counter for index 3
*/
uint32_t McFCntDown3;
}FCntList_t;
/*
* LoRaMac Commands Context structure
*/
typedef struct sLoRaMacFCntHandlerNvmCtx
{
/*
* Frame counter list
*/
FCntList_t FCntList;
} LoRaMacFCntHandlerNvmCtx_t;
/*
* Non-volatile module context.
*/
static LoRaMacFCntHandlerNvmCtx_t FCntHandlerNvmCtx;
/*
* Callback function to notify the upper layer about context change
*/
static EventNvmCtxChanged FCntHandlerNvmCtxChanged;
/*
* \brief Wrapper function for the NvmCtx
*/
static void NvmCtxChanged( void )
{
if( FCntHandlerNvmCtxChanged != NULL )
{
FCntHandlerNvmCtxChanged( );
}
}
LoRaMacFCntHandlerStatus_t LoRaMacFCntHandlerInit( EventNvmCtxChanged fCntHandlerNvmCtxChanged )
{
// Initialize with default
LoRaMacResetFCnts( );
// Assign callback
FCntHandlerNvmCtxChanged = fCntHandlerNvmCtxChanged;
return LORAMAC_FCNT_HANDLER_SUCCESS;
}
LoRaMacFCntHandlerStatus_t LoRaMacFCntHandlerRestoreNvmCtx( void* fCntHandlerNvmCtx )
{
// Restore module context
if( fCntHandlerNvmCtx != NULL )
{
memcpy1( ( uint8_t* ) &FCntHandlerNvmCtx, ( uint8_t* ) fCntHandlerNvmCtx, sizeof( FCntHandlerNvmCtx ) );
return LORAMAC_FCNT_HANDLER_SUCCESS;
}
else
{
return LORAMAC_FCNT_HANDLER_ERROR_NPE;
}
}
void* LoRaMacFCntHandlerGetNvmCtx( size_t* fCntHandlerNvmCtxSize )
{
*fCntHandlerNvmCtxSize = sizeof( FCntHandlerNvmCtx );
return &FCntHandlerNvmCtx;
}
LoRaMacFCntHandlerStatus_t LoRaMacGetFCntDown( AddressIdentifier_t addrID, FType_t fType, LoRaMacMessageData_t* macMsg, Version_t lrWanVersion,
uint16_t maxFCntGap, FCntIdentifier_t* fCntID, uint32_t* currentDown )
{
uint32_t previousDown = 0;
int32_t fCntDiff = 0;
if( ( macMsg == NULL ) || ( fCntID == NULL ) ||
( currentDown == NULL ) )
{
return LORAMAC_FCNT_HANDLER_ERROR_NPE;
}
// Determine the frame counter identifier and choose counter from FCntList
switch( addrID )
{
case UNICAST_DEV_ADDR:
if( lrWanVersion.Fields.Minor == 1 )
{
if( ( fType == FRAME_TYPE_A ) || ( fType == FRAME_TYPE_D ) )
{
*fCntID = A_FCNT_DOWN;
previousDown = FCntHandlerNvmCtx.FCntList.AFCntDown;
}
else
{
*fCntID = N_FCNT_DOWN;
previousDown = FCntHandlerNvmCtx.FCntList.NFCntDown;
}
}
else
{ // For LoRaWAN 1.0.X
*fCntID = FCNT_DOWN;
previousDown = FCntHandlerNvmCtx.FCntList.FCntDown;
}
break;
case MULTICAST_0_ADDR:
*fCntID = MC_FCNT_DOWN_0;
previousDown = FCntHandlerNvmCtx.FCntList.McFCntDown0;
break;
case MULTICAST_1_ADDR:
*fCntID = MC_FCNT_DOWN_1;
previousDown = FCntHandlerNvmCtx.FCntList.McFCntDown1;
break;
case MULTICAST_2_ADDR:
*fCntID = MC_FCNT_DOWN_2;
previousDown = FCntHandlerNvmCtx.FCntList.McFCntDown3;
break;
case MULTICAST_3_ADDR:
*fCntID = MC_FCNT_DOWN_3;
previousDown = FCntHandlerNvmCtx.FCntList.McFCntDown3;
break;
default:
return LORAMAC_FCNT_HANDLER_ERROR;
}
// For LoRaWAN 1.0.X only, allow downlink frames of 0
if( previousDown == FCNT_DOWN_INITAL_VALUE )
{
*currentDown = macMsg->FHDR.FCnt;
}
else
{
// Add difference, consider roll-over
fCntDiff = ( int32_t )macMsg->FHDR.FCnt - ( int32_t )( previousDown & 0x0000FFFF );
if( fCntDiff > 0 )
{ // Positive difference
*currentDown = previousDown + fCntDiff;
}
else if( fCntDiff == 0 )
{ // Duplicate FCnt value, keep the current value.
*currentDown = previousDown;
return LORAMAC_FCNT_HANDLER_CHECK_FAIL;
}
else
{ // Negative difference, assume a roll-over of one uint16_t
*currentDown = ( previousDown & 0xFFFF0000 ) + 0x10000 + macMsg->FHDR.FCnt;
}
}
// For LoRaWAN 1.0.X only, check maxFCntGap
if( lrWanVersion.Fields.Minor == 0 )
{
if( ( ( int32_t )*currentDown - ( int32_t )previousDown ) >= maxFCntGap )
{
return LORAMAC_FCNT_HANDLER_MAX_GAP_FAIL;
}
}
return LORAMAC_FCNT_HANDLER_SUCCESS;
}
LoRaMacFCntHandlerStatus_t LoRaMacSetFCntDown( FCntIdentifier_t fCntID, uint32_t currentDown )
{
switch( fCntID )
{
case FCNT_UP:
return LORAMAC_FCNT_HANDLER_ERROR_INVALID_FCNT_ID;
case N_FCNT_DOWN:
FCntHandlerNvmCtx.FCntList.NFCntDown = currentDown;
break;
case A_FCNT_DOWN:
FCntHandlerNvmCtx.FCntList.AFCntDown = currentDown;
break;
case FCNT_DOWN:
FCntHandlerNvmCtx.FCntList.FCntDown = currentDown;
break;
case MC_FCNT_DOWN_0:
FCntHandlerNvmCtx.FCntList.McFCntDown0 = currentDown;
break;
case MC_FCNT_DOWN_1:
FCntHandlerNvmCtx.FCntList.McFCntDown1 = currentDown;
break;
case MC_FCNT_DOWN_2:
FCntHandlerNvmCtx.FCntList.McFCntDown2 = currentDown;
break;
case MC_FCNT_DOWN_3:
FCntHandlerNvmCtx.FCntList.McFCntDown3 = currentDown;
break;
default:
return LORAMAC_FCNT_HANDLER_ERROR;
}
NvmCtxChanged( );
return LORAMAC_FCNT_HANDLER_SUCCESS;
}
LoRaMacFCntHandlerStatus_t LoRaMacGetFCntUp( uint32_t* currentUp )
{
if( currentUp == NULL )
{
return LORAMAC_FCNT_HANDLER_ERROR_NPE;
}
*currentUp = FCntHandlerNvmCtx.FCntList.FCntUp + 1;
return LORAMAC_FCNT_HANDLER_SUCCESS;
}
LoRaMacFCntHandlerStatus_t LoRaMacSetFCntUp( uint32_t currentUp )
{
FCntHandlerNvmCtx.FCntList.FCntUp = currentUp;
NvmCtxChanged( );
return LORAMAC_FCNT_HANDLER_SUCCESS;
}
LoRaMacFCntHandlerStatus_t LoRaMacResetFCnts( void )
{
FCntHandlerNvmCtx.FCntList.FCntUp = 0;
FCntHandlerNvmCtx.FCntList.NFCntDown = FCNT_DOWN_INITAL_VALUE;
FCntHandlerNvmCtx.FCntList.AFCntDown = FCNT_DOWN_INITAL_VALUE;
FCntHandlerNvmCtx.FCntList.FCntDown = FCNT_DOWN_INITAL_VALUE;
FCntHandlerNvmCtx.FCntList.McFCntDown0 = FCNT_DOWN_INITAL_VALUE;
FCntHandlerNvmCtx.FCntList.McFCntDown1 = FCNT_DOWN_INITAL_VALUE;
FCntHandlerNvmCtx.FCntList.McFCntDown2 = FCNT_DOWN_INITAL_VALUE;
FCntHandlerNvmCtx.FCntList.McFCntDown3 = FCNT_DOWN_INITAL_VALUE;
NvmCtxChanged( );
return LORAMAC_FCNT_HANDLER_SUCCESS;
}
LoRaMacFCntHandlerStatus_t LoRaMacFCntHandlerSetMulticastReference( MulticastCtx_t* multicastList )
{
if( multicastList == NULL )
{
return LORAMAC_FCNT_HANDLER_ERROR_NPE;
}
multicastList[0].DownLinkCounter = &FCntHandlerNvmCtx.FCntList.McFCntDown0;
multicastList[1].DownLinkCounter = &FCntHandlerNvmCtx.FCntList.McFCntDown1;
multicastList[2].DownLinkCounter = &FCntHandlerNvmCtx.FCntList.McFCntDown2;
multicastList[3].DownLinkCounter = &FCntHandlerNvmCtx.FCntList.McFCntDown3;
return LORAMAC_FCNT_HANDLER_SUCCESS;
}