

/******************************************************************************
 Includes
 *****************************************************************************/
#include <string.h>
#include <stdint.h>

#include "mac_util.h"
#include "api_mac.h"

#include "smsgs.h"
#include "commonShim.h"
#include "ti_154stack_config.h"


#include <advanced_config.h>

#ifdef FEATURE_SECURE_COMMISSIONING
#include "sm_ti154.h"
#endif // FEATURE_SECURE_COMMISSIONING 

#ifdef USE_DMM
#include "remote_display.h"
#include "ti_dmm_application_policy.h"
#include <pthread.h>
#include <semaphore.h>
#include "util_timer.h"
#ifdef FEATURE_SECURE_COMMISSIONING
#include "sm_commissioning_gatt_profile.h"
#endif  /* FEATURE_SECURE_COMMISSIONING */
#endif /* USE_DMM */

#ifdef MAC_DUTY_CYCLE_CHECKING
#include "mac_duty_cycle/mac_duty_cycle.h"
#endif

#ifdef MAC_OVERRIDE_TX_DELAY
#include "mac_api.h"
#endif

#include <ti/log/Log.h>

/******************************************************************************
 Constants and definitions
 *****************************************************************************/

#if !defined(STATIC)
/* make local */
#define STATIC static
#endif

#if !defined(CONFIG_AUTO_START)
#if defined(AUTO_START)
#define CONFIG_AUTO_START 1
#else
#define CONFIG_AUTO_START 0
#endif
#endif

#if defined(IEEE_COEX_METRICS) && !defined(IEEE_COEX_ENABLED)
#error "IEEE_COEX_ENABLED must be defined to view coex metrics"
#endif

/* Default MSDU Handle rollover */
#define MSDU_HANDLE_MAX 0x1F

/* App marker in MSDU handle */
#define APP_MARKER_MSDU_HANDLE 0x80

/* App Config request marker for the MSDU handle */
#define APP_CONFIG_MSDU_HANDLE 0x40

/* Ramp data request marker for the MSDU handle */
#define RAMP_DATA_MSDU_HANDLE 0x20
/* App Broadcast Cmd Msg marker for the MSDU Handle */
#define APP_BROADCAST_MSDU_HANDLE 0x20

/* Delay for config request retry in busy network */
#define CONFIG_DELAY 2000
#define CONFIG_RESPONSE_DELAY 3*CONFIG_DELAY
/* Tracking timeouts */
#define TRACKING_CNF_DELAY_TIME 2000 /* in milliseconds */

#ifdef IEEE_COEX_TEST
/****************************************************************/
/* ZB Monitor Params                                            */
#define APSRETRIES

uint32_t frameRetries    = 0;
uint32_t TrackMsgRetries = 0;
uint32_t TrackMsgFail = 0;

/*!
Average end to end delay
*/
uint16_t avgE2EDelay;
/*!
Worst Case end to end delay
*/
uint16_t worstCaseE2EDelay;

/*! total number of Track data messages sent. */
uint32_t TrackMsgsSent = 0;

/*! total number of Track data messages sent. */
uint32_t TrackMsgsSuccess = 0;
/* accumulated total E2E delay */
uint32_t totalE2EDelaySum = 0;

/* saved end to end delay */
uint32_t endToEndDelay = 0;

/* End to end delay statistics timestamp */
static uint32_t startTrackMsgTimeStamp = 0;

/*! Clock tick period  */
#define CLOCK_TICK_PERIOD     (10)
/*! tick number for one ms  */
#define TICKPERIOD_MS_US      (1000/(CLOCK_TICK_PERIOD))

#endif // IEEE_COEX_TEST

/*******************************************************************/
#if (CONFIG_PHY_ID == APIMAC_50KBPS_915MHZ_PHY_1) || \
    (CONFIG_PHY_ID == APIMAC_50KBPS_868MHZ_PHY_3) || \
    (CONFIG_PHY_ID == APIMAC_50KBPS_433MHZ_PHY_128)
    #define SYMBOL_DURATION         (SYMBOL_DURATION_50_kbps)  //us

#elif (CONFIG_PHY_ID == APIMAC_200KBPS_915MHZ_PHY_132) || \
      (CONFIG_PHY_ID == APIMAC_200KBPS_868MHZ_PHY_133) || \
      (CONFIG_PHY_ID == APIMAC_200KBPS_920MHZ_PHY_136)
    #define SYMBOL_DURATION         (SYMBOL_DURATION_200_kbps) //us

#elif (CONFIG_PHY_ID == APIMAC_5KBPS_915MHZ_PHY_129) || \
      (CONFIG_PHY_ID == APIMAC_5KBPS_433MHZ_PHY_130) || \
      (CONFIG_PHY_ID == APIMAC_5KBPS_868MHZ_PHY_131)
    #define SYMBOL_DURATION         (SYMBOL_DURATION_LRM)      //us

#elif (CONFIG_PHY_ID == APIMAC_CUSTOM_PHY_ID)
    #define SYMBOL_DURATION        (SYMBOL_DURATION_CUSTOM)   //us

#elif (CONFIG_PHY_ID == APIMAC_250KBPS_IEEE_PHY_0)  // 2.4g
    #define SYMBOL_DURATION         (SYMBOL_DURATION_250_kbps)  //us
#else
    #define SYMBOL_DURATION         (SYMBOL_DURATION_50_kbps)  //us
#endif

#if (CONFIG_MAC_BEACON_ORDER != NON_BEACON_ORDER)
/* This is 3 times the polling interval used in beacon mode. */
#define TRACKING_TIMEOUT_TIME ((1<<CONFIG_MAC_BEACON_ORDER) * 960 * SYMBOL_DURATION * 3 / 1000) /*in milliseconds*/
#else
#define TRACKING_TIMEOUT_TIME (CONFIG_POLLING_INTERVAL * 3) /*in milliseconds*/
#endif

#ifdef IEEE_COEX_METRICS
/* Timeout in milliseconds for coex metrics reads */
#define COEX_IEEE_METRICS_TIMEOUT_TIME  120000
#endif
#ifdef MAC_STATS
/* Timeout in milliseconds for coex metrics reads */
#ifdef IEEE_COEX_TEST
#define MAC_STATS_TIMEOUT_TIME  5000
#else
#define MAC_STATS_TIMEOUT_TIME  10000
#endif
#endif

/* Initial delay before broadcast transmissions are started in FH mode */
#define BROADCAST_CMD_START_TIME 60000

/* Assoc Table (CLLC) status settings */
#define ASSOC_CONFIG_SENT       0x0100    /* Config Req sent */
#define ASSOC_CONFIG_RSP        0x0200    /* Config Rsp received */
#define ASSOC_CONFIG_MASK       0x0300    /* Config mask */
#define ASSOC_TRACKING_SENT     0x1000    /* Tracking Req sent */
#define ASSOC_TRACKING_RSP      0x2000    /* Tracking Rsp received */
#define ASSOC_TRACKING_RETRY    0x4000    /* Tracking Req retried */
#define ASSOC_TRACKING_ERROR    0x8000    /* Tracking Req error */
#define ASSOC_TRACKING_MASK     0xF000    /* Tracking mask  */
#define MAX_DATA_REQ_MSDU_MAP_TABLE_SIZE 3
#ifdef USE_DMM
#define NTWK_DISCOVER_TIMER         100
#endif /* USE_DMM */
/******************************************************************************
 Global variables
 *****************************************************************************/
/* Global Display Handle for UART Console */
//Display_Handle displayHandle;

UART2_Handle uartHandle;
uint8_t      uartRxBuffer[1]; // Uart 1 byte buffer.

/* Task pending events */
uint16_t Collector_events = 0;

/* Permit join setting */
extern bool permitJoining;

/******************************************************************************
 Local variables
 *****************************************************************************/

static void *sem;

/*! true if the device was restarted */
static bool restarted = false;

/*! CLLC State */
//STATIC Cllc_states_t cllcState = Cllc_states_initWaiting;

/*! Device's PAN ID */
STATIC uint16_t devicePanId = 0xFFFF;

/*! Device's Outgoing MSDU Handle values */
STATIC uint8_t deviceTxMsduHandle = 0;

STATIC bool fhEnabled = false;

STATIC ApiMac_msduAddrMap_t dataRequestMsduMappingTable[MAX_DATA_REQ_MSDU_MAP_TABLE_SIZE];

#ifdef USE_DMM
/* Device List Discovery Flag */
static bool listDiscovery = false;
/* current Sensor Address */
static uint16_t currentSensor;

STATIC ClockP_Struct ntwkDiscoverClkStruct;
STATIC ClockP_Handle ntwkDiscoverClkHandle;
#endif /* USE_DMM */

#ifdef FH_LOW_LATENCY_BROADCAST
#define LOW_LATENCY_BROADCAST_MAX_RETRIES 3
static uint16_t destDevAddr;
static uint16_t destDevAddr_copy;
static uint8_t sendCamCmd = 0;
static uint8_t broadcastQueue = 0;
#endif // FH_LOW_LATENCY_BROADCAST

/******************************************************************************
 Local function prototypes
 *****************************************************************************/




static void sendBroadcastMsg(Smsgs_cmdIds_t type, uint16_t len, uint8_t *pData);






#ifdef FEATURE_SECURE_COMMISSIONING
/* Security Manager callback functions */
static void smFailCMProcessCb(ApiMac_deviceDescriptor_t *devInfo, bool rxOnIdle,
                              bool keyRefreshment, SMMsgs_errorCode_t errorCode);
static void smSuccessCMProcessCb(ApiMac_deviceDescriptor_t *devInfo, bool keyRefreshment);
#endif /* FEATURE_SECURE_COMMISSIONING */





#ifdef DMM_OAD
static void Collector_dmmPausePolicyCb(uint16_t pause);
#endif /* DMM_OAD */

/******************************************************************************
 Callback tables
 *****************************************************************************/

/*! Table of MAC Callbacks for the Common Shim*/
ApiMac_callbacks_t CommonShimCallbacks =
    {
      /*! Associate Indicated callback */
      NULL,
      /*! Associate Confirmation callback */
      NULL,
      /*! Disassociate Indication callback */
      NULL,
      /*! Disassociate Confirmation callback */
      NULL,
      /*! Beacon Notify Indication callback */
      NULL,
      /*! Orphan Indication callback */
      OrphanIndication,
      /*! Scan Confirmation callback */
      ScanConfirm,
      /*! Start Confirmation callback */
      StartConfirm,
      /*! Sync Loss Indication callback */
      NULL,
      /*! Poll Confirm callback */
      NULL,
      /*! Comm Status Indication callback */
      NULL,
      /*! Poll Indication Callback */
      NULL,
      /*! Data Confirmation callback */
      NULL,
      /*! Data Indication callback */
      NULL,
      /*! Purge Confirm callback */
      NULL,
      /*! WiSUN Async Indication callback */
      NULL,
      /*! WiSUN Async Confirmation callback */
      NULL,
      /*! Unprocessed message callback */
      NULL
    };


#ifdef DMM_OAD
/*********************************************************************
 * DMM Policy Callbacks
 */
static DMMPolicy_AppCbs_t dmmPolicyAppCBs =
{
     Collector_dmmPausePolicyCb
};
#endif


/******************************************************************************
 Public Functions
 *****************************************************************************/



#ifdef OSAL_PORT2TIRTOS
void InitializeCommonShim(uint8_t macTaskId)
#else
void InitializeCommonShim(void)
#endif
{


    // Initialize the state machine that process the bytes received via UART2
    m_state = START;
    m_rxByteCount = 0;

    // Initiate UART2
    UART2_Params uartParams;

    UART2_Params_init(&uartParams);
    uartParams.baudRate      = 115200;
    uartParams.readMode      = UART2_Mode_CALLBACK; // This is the "Interrupt" mode
    uartParams.readCallback  = ReceiveByte;     // Receiving callback
    
    // CONFIG_UART2_0 is defined in ti_drivers_config.h via SysConfig
    uartHandle = UART2_open(CONFIG_UART2_0, &uartParams);

    if (uartHandle != NULL) {
        // Start the first asynchronous read
        UART2_read(uartHandle, uartRxBuffer, 1, NULL);
    }

    
    // Initialize the MAC 
#ifdef OSAL_PORT2TIRTOS
    sem = ApiMac_init(macTaskId,CONFIG_FH_ENABLE);
#else
    sem = ApiMac_init(CONFIG_FH_ENABLE);
#endif

    //Turn receiver ON for SCAN
    ApiMac_mlmeSetReqBool(ApiMac_attribute_RxOnWhenIdle, true);

    ApiMac_mlmeSetReqBool(ApiMac_attribute_associatePermit,true);
    
    ApiMac_mlmeSetReqUint8(ApiMac_attribute_phyCurrentDescriptorId,
                           (uint8_t)CONFIG_PHY_ID);

    ApiMac_mlmeSetReqUint8(ApiMac_attribute_channelPage,
                           (uint8_t)CONFIG_CHANNEL_PAGE);


    ApiMac_mlmeSetReqUint8(ApiMac_attribute_logicalChannel,
                           11);

    ApiMac_mlmeSetReqUint8(ApiMac_attribute_responseWaitTime, 32);

                           

    // Register the MAC Callbacks
    ApiMac_registerCallbacks(&CommonShimCallbacks);

    // for non beacon order
    ApiMac_mlmeSetReqUint16(ApiMac_attribute_transactionPersistenceTime,
                            INDIRECT_PERSISTENT_TIME);

    ApiMac_mlmeSetReqUint8(ApiMac_attribute_phyTransmitPowerSigned,
                           (uint8_t)CONFIG_TRANSMIT_POWER);

    // Set Min BE 
    ApiMac_mlmeSetReqUint8(ApiMac_attribute_backoffExponent,
                              (uint8_t)CONFIG_MIN_BE);
    // Set Max BE 
    ApiMac_mlmeSetReqUint8(ApiMac_attribute_maxBackoffExponent,
                              (uint8_t)CONFIG_MAX_BE);
    // Set MAC MAX CSMA Backoffs 
    ApiMac_mlmeSetReqUint8(ApiMac_attribute_maxCsmaBackoffs,
                              (uint8_t)CONFIG_MAC_MAX_CSMA_BACKOFFS);
    // Set MAC MAX Frame Retries 
    ApiMac_mlmeSetReqUint8(ApiMac_attribute_maxFrameRetries,
                              (uint8_t)CONFIG_MAX_RETRIES);

    //Display_printf(displayHandle, 0, 0, "CommonShim intialized!");

}






 




/******************************************************************************
 Local Functions
 *****************************************************************************/


#ifdef IEEE_COEX_TEST
static void calcLatency(void)
{
    if(Clock_getTicks() < startTrackMsgTimeStamp)
    {
        endToEndDelay = Clock_getTicks() +
                        (0xFFFFFFFF-startTrackMsgTimeStamp);
    }
    else
    {
        endToEndDelay = Clock_getTicks() - startTrackMsgTimeStamp;
    }
    endToEndDelay = (endToEndDelay + TICKPERIOD_MS_US - 1)/TICKPERIOD_MS_US;
    if ( (totalE2EDelaySum + endToEndDelay ) < totalE2EDelaySum)
    {
        /* totalE2EDelaySum is wrapped around,reset the sent count 1 */
        totalE2EDelaySum = endToEndDelay;
        TrackMsgsSent = 1;
    }
    else
    {
        totalE2EDelaySum += endToEndDelay;
    }

    worstCaseE2EDelay =
       (worstCaseE2EDelay > endToEndDelay) ?
        worstCaseE2EDelay:endToEndDelay;

    //avgE2EDelay=totalE2EDelaySum/TrackMsgsSent;
    avgE2EDelay=totalE2EDelaySum/Collector_statistics.trackingRequestAttempts;
}
#endif // IEEE_COEX_TEST

void DebugPrint(const char *format, ...)
{
    // Safety check: ensure UART is initialized
    if (uartHandle == NULL) 
    {
        return;
    }

    va_list args;
    va_start(args, format);

    // vsnprintf is safer than vsprintf as it prevents buffer overflows
    int length = vsnprintf(debugBuf, DEBUG_BUF_SIZE, format, args);

    va_end(args);

    // If formatting was successful and there's content to send
    if (length > 0)
    {
        // In Callback mode, this returns immediately.
        // The driver manages the transmission in the background.
        UART2_write(uartHandle, debugBuf, length, NULL);
    }
}

void 
SendBytes(uint8_t *bytes, uint8_t size)
{
    if (uartHandle == NULL || size == 0)
    {
        return;
    }
    
    size_t bytesWritten = 0;
    UART2_write(uartHandle, bytes, size, &bytesWritten);
}

void 
ProcessRxData()
{
    if (m_primitiveGroup == MLME_PRIMITIVE)
    {
        switch (m_mlmeReqRspType)
        {
        case MAC_MLME_REQ_ASSOCIATE:
            //AssociateRequest();
            break;
        case MAC_MLME_REQ_DISASSOCIATE:
            // TODO
            break;
        case MAC_MLME_REQ_GET:
            GetRequest();
            break;
        case MAC_MLME_REQ_GTS:
            // TODO
            break;
        case MAC_MLME_REQ_RESET:
            // TODO
            break;
        case MAC_MLME_REQ_RX_ENABLE:
            // TODO
            break;
        case MAC_MLME_REQ_SCAN:
            ScanRequest();
            break;
        case MAC_MLME_REQ_SET:
            SetRequest();
            break;
        case MAC_MLME_REQ_START:
            StartRequest();
            break;
        case MAC_MLME_REQ_SYNC:
            // TODO
            break;
        case MAC_MLME_REQ_POLL:
            // TODO
            break;
        case MAC_MLME_RSP_ASSOCIATE:
            //AssociateResponse();
            break;
        case MAC_MLME_RSP_ORPHAN:
            OrphanResponse();
            break;
        case MAC_MLME_REQ_VS_EXTADDR:
            // TODO
            break;
        default:
            // The primitive is not in the list of
            // standard IEEE 802.15.4 primitives
            if (m_mlmeReqRspType == 99)
            {
                //SensorRequest();
            }
            break;
        }
    }
    else if (m_primitiveGroup == MCPS_PRIMITIVE)
    {
        if (m_mcpsReqRspType == MAC_MCPS_REQ_DATA)
        {
            //DataRequest();
        }
    }
}


void 
ReceiveByte(UART2_Handle handle, 
            void *buffer, 
            size_t count, 
            void *userArg, 
            int_fast16_t status)
{
    if (status != UART2_STATUS_SUCCESS)
    {
        // Prepare UART2 for the next read of a single byte
        UART2_read(handle, uartRxBuffer, 1, NULL);
        return;
    }

    uint8_t rxByte = ((uint8_t*)buffer)[0];
    switch(m_state)
    {
        case START:
           if(rxByte == 0xAA)
           {
               m_state = PRIMITIVE_TYPE1;
               m_primitiveGroup = MLME_PRIMITIVE;
           }
           else if (rxByte == 0xBB)
           {
               m_state = PRIMITIVE_TYPE2;
               m_primitiveGroup = MCPS_PRIMITIVE;
           }
           break;
        case PRIMITIVE_TYPE1:
           // For MLME primitives 
           m_mlmeReqRspType = rxByte;
           m_state = PARAMETERS_SIZE;
           break;
        case PRIMITIVE_TYPE2:
           // For MCPS primitives
           m_mcpsReqRspType = rxByte;
           m_state = PARAMETERS_SIZE;
           break;
        case PARAMETERS_SIZE:
           m_primitiveMaxSize = rxByte;
           m_state = WAIT_DATA;
           break;
        case WAIT_DATA:
           m_rxBuffer[m_rxByteCount] = rxByte;
           m_rxByteCount++;
           if (m_rxByteCount == m_primitiveMaxSize)
           {
               ProcessRxData();
               m_state = START;
               m_primitiveGroup = NONE;
               m_rxByteCount = 0;
               memset(m_rxBuffer, 0, sizeof(m_rxBuffer));
           }
           break;
    }
        
        //const char helloMsg[] = "hello\n";
        //UART2_write(handle, helloMsg, 6, NULL);
    
    // Prepare UART2 for the next read of a single byte
    UART2_read(handle, uartRxBuffer, 1, NULL);
}

void 
ScanRequest(void)
{
  
   uint16_t panId =0xCAFE;
uint16_t shortAddr=0xCAFE;
uint16_t shortAddr2=0xCACA;
ApiMac_mlmeSetReqUint16(ApiMac_attribute_coordShortAddress,
                                         shortAddr2);
ApiMac_mlmeSetReqUint16(ApiMac_attribute_panId, panId);
ApiMac_mlmeSetReqUint16(ApiMac_attribute_shortAddress, shortAddr);
 ApiMac_mlmeSetReqBool(ApiMac_attribute_RxOnWhenIdle, true);
  ApiMac_mlmeSetReqBool(ApiMac_attribute_associatedPanCoord ,false);


    ApiMac_mlmeScanReq_t scanReq;
    memset(&scanReq, 0, sizeof(ApiMac_mlmeScanReq_t));

    // Note: Regardless of the scan parameters, phyID and channelPage are
    // fixed, and cannot be changed via parameter. This is because diffent
    // PHYs require flashing different compiled files and values, all which must 
    // match the values of whatever is configured in commonShim.syscfg
    scanReq.phyID = CONFIG_PHY_ID;
    scanReq.channelPage = CONFIG_CHANNEL_PAGE;

    memset(scanReq.scanChannels, 0, sizeof(scanReq.scanChannels)); // Clear all first
    // TODO: For the moment, we only support scanning the first 32 channels(0-31)
    scanReq.scanChannels[0] = m_rxBuffer[0];
    scanReq.scanChannels[1] = m_rxBuffer[1];
    scanReq.scanChannels[2] = m_rxBuffer[2];
    scanReq.scanChannels[3] = m_rxBuffer[3];
    scanReq.scanChannels[4] = 0;
    scanReq.scanChannels[5] = 0;
    scanReq.scanChannels[6] = 0;
    scanReq.scanChannels[7] = 0;
    scanReq.scanChannels[8] = 0;
    scanReq.scanChannels[9] = 0;
    scanReq.scanChannels[10] = 0;
    scanReq.scanChannels[11] = 0;
    scanReq.scanChannels[12] = 0;
    scanReq.scanChannels[13] = 0;
    scanReq.scanChannels[14] = 0;
    scanReq.scanChannels[15] = 0;
    scanReq.scanChannels[16] = 0;

    // You can use the following to set the Channels submask directly
    // from the configured values of the commonShim.syscfgfile. However we want
    // the channel bit mask to be provided by the next layer, therefore we use
    // the array shown above.

    /* STATIC uint8_t defaultChannelMask[APIMAC_154G_CHANNEL_BITMAP_SIZ] =
                CONFIG_CHANNEL_MASK;
     memcpy(scanReq.scanChannels,
            defaultChannelMask,
            APIMAC_154G_CHANNEL_BITMAP_SIZ);*/


    scanReq.scanType = m_rxBuffer[4];
    scanReq.scanDuration = m_rxBuffer[5];

    // TODO: This parameter is part of IEEE 802.15.4-2015 onwards,
    // add it to the list of parameters when 2015 support is added.
    scanReq.maxResults = 0; 
    scanReq.permitJoining = false;
    scanReq.linkQuality = false;
    scanReq.percentFilter = 255;

    memset(&scanReq.sec, 0, sizeof(ApiMac_sec_t)); // no security

    ApiMac_mlmeScanReq(&scanReq);
}

void
OrphanResponse()
{
    uint16_t pos = 0;

    ApiMac_mlmeOrphanRsp_t orphanRsp;
    memset(&orphanRsp, 0, sizeof(ApiMac_mlmeOrphanRsp_t));

    orphanRsp.orphanAddress[0] = m_rxBuffer[pos++];
    orphanRsp.orphanAddress[1] = m_rxBuffer[pos++];
    orphanRsp.orphanAddress[2] = m_rxBuffer[pos++];
    orphanRsp.orphanAddress[3] = m_rxBuffer[pos++];

    orphanRsp.orphanAddress[4] = m_rxBuffer[pos++];
    orphanRsp.orphanAddress[5] = m_rxBuffer[pos++];
    orphanRsp.orphanAddress[6] = m_rxBuffer[pos++];
    orphanRsp.orphanAddress[7] = m_rxBuffer[pos++];

    orphanRsp.shortAddress = m_rxBuffer[pos++];
    orphanRsp.shortAddress |= ((m_rxBuffer[pos++]) << 8);
    
    // TODO: CC1352R1 includes parameter "associatedMember" which is
    // not part of IEEE 802.15.4 until 2015 revision. For now, we 
    // do not include it to align to the 2011 revision.
    // orphanRsp.associatedMember

    // TODO: Add security when supported
    memset(&orphanRsp.sec, 0, sizeof(ApiMac_sec_t)); // no security

    ApiMac_status_t status =  ApiMac_mlmeOrphanRsp(&orphanRsp);
    if (status != ApiMac_status_success)
    {
        DebugPrint("Error in OrphanRsp with status: %x\n",status);
    } 
}

void
OrphanIndication(ApiMac_mlmeOrphanInd_t *params)
{
    uint8_t orphanIndParams[11];
    uint16_t pos = 0;

    orphanIndParams[pos++] = 0xAA;
    orphanIndParams[pos++] = ORPHAN_IND;
    // Parameter Size = OrphanAddress (8)
    orphanIndParams[pos++] = 8; // size in bytes (extAddr)

    orphanIndParams[pos++] = params->orphanAddress[0];
    orphanIndParams[pos++] = params->orphanAddress[1];
    orphanIndParams[pos++] = params->orphanAddress[2];
    orphanIndParams[pos++] = params->orphanAddress[3];

    orphanIndParams[pos++] = params->orphanAddress[4];
    orphanIndParams[pos++] = params->orphanAddress[5];
    orphanIndParams[pos++] = params->orphanAddress[6];
    orphanIndParams[pos++] = params->orphanAddress[7];

    // Note: Add security information when supported
    // params->sec

    SendBytes(orphanIndParams, pos);
}

void 
ScanConfirm(ApiMac_mlmeScanCnf_t *params)
{   DebugPrint("scanCfirm status: %u Type %u\n",params->status, params->scanType);
     
     /* uint8_t totalScannedChannels = 0;
    uint8_t paramsSize = 10;

    // Fixed Size parameters to send via UART
    // Initial 0xAA byte (1) + Primitive Type (1) + ParamSize(1) + Status (1) + ScanType (1)
    // UnscannedChannels (4) + ResultListSize (1) = 10 bytes

    if (params->status == ApiMac_status_success)
    {
        switch(params->scanType)
        {
            case ApiMac_scantype_energyDetect:
            {
               // In TI CC1352R1, Regardless the PHY, the resultListSize is always 129 
               // (The maximum of channels supported by the 902 Mhz band), therefore,
               // we manually count the channels to return this instead in the resultListSize
               // and be consistent with other microcontroller vendors like NXP.
               
               for (int ch=0; ch < params->resultListSize; ch++)
               {
                  // 255 = Not scanned channel or invalid
                  if (params->result.pEnergyDetect[ch] != 255)
                  {
                      totalScannedChannels++;
                  }
               }
               paramsSize += totalScannedChannels;
               break;
            }
            case ApiMac_scantype_active:
               break;
            case ApiMac_scantype_passive:
               break;
            case ApiMac_scantype_orphan:
               break;
            case ApiMac_scantype_activeEnhanced:
               break;
        }
    }

    static uint8_t scanParams[512];
    uint16_t pos = 0;
    scanParams[pos++] = 0xAA;
    scanParams[pos++] = SCAN_CFM;
    // The size in bytes of the parameters (excluding 0xAA byte, the primitive type, and this value)
    scanParams[pos++] = paramsSize - 3;
    scanParams[pos++] = params->status;
    scanParams[pos++] = params->scanType;
    // TODO: We report only the results of the first 32 channels (0-31)
    // however in CC1352, the bitmask is of 17 bytes not 4 bytes. We need to add additional bytes
    // to support bitmasks of PHYs other than 250Kbps O-QPSK. 
    scanParams[pos++] = params->unscannedChannels[0];
    scanParams[pos++] = params->unscannedChannels[1];
    scanParams[pos++] = params->unscannedChannels[2];
    scanParams[pos++] = params->unscannedChannels[3];
 
    scanParams[pos++] = totalScannedChannels;
    
    if (params->status == ApiMac_status_success)
    {
        switch(params->scanType)
        {
            case ApiMac_scantype_energyDetect:
            {
               for (int ch=0; ch < params->resultListSize; ch++)
               {
                  // 255 = Not scanned channel or invalid
                  if (params->result.pEnergyDetect[ch] != 255)
                  {
                      scanParams[pos++] = params->result.pEnergyDetect[ch];
                  }
               }
               break;
            }
            case ApiMac_scantype_active:
               break;
            case ApiMac_scantype_passive:
               break;
            case ApiMac_scantype_orphan:
               break;
            case ApiMac_scantype_activeEnhanced:
               break;
        }
    }
    
    SendBytes(scanParams, pos);*/

}

void
StartRequest()
{
    ApiMac_mlmeStartReq_t startReq;
    memset(&startReq, 0, sizeof(ApiMac_mlmeStartReq_t));

    // PhyID and channel page are fixed in CC1352, they depend on
    // the options chosen in the commonShim.syscfg file.
    startReq.phyID = CONFIG_PHY_ID;
    startReq.channelPage = CONFIG_CHANNEL_PAGE;
    startReq.panId = m_rxBuffer[0] + (m_rxBuffer[1] << 8);
    startReq.logicalChannel = m_rxBuffer[2];
    startReq.startTime = 
       m_rxBuffer[4] + (m_rxBuffer[5] << 8) + (m_rxBuffer[6] << 16) + (m_rxBuffer[7] << 24);
    startReq.beaconOrder = m_rxBuffer[8];
    startReq.superframeOrder = m_rxBuffer[9];
    startReq.panCoordinator = m_rxBuffer[10];
    startReq.batteryLifeExt = m_rxBuffer[11];
    startReq.coordRealignment = m_rxBuffer[12];
    // No security option in the Mlme-start of CC352

    ApiMac_status_t status =  ApiMac_mlmeStartReq(&startReq);
    if (status != ApiMac_status_success)
    {
        DebugPrint("Error in StartReq with status: %x\n",status);
    }  
}

void 
StartConfirm(ApiMac_mlmeStartCnf_t *params)
{
    uint8_t pos = 0;
    uint8_t startParams[4];
    startParams[pos++] = 0xAA;
    startParams[pos++] = START_CFM;
    startParams[pos++] = 1; // start Confirm returns only a status (1 byte parameter)
    startParams[pos++] = params->status;
    SendBytes(startParams, pos);
}

void
SetRequest()
{     
    uint8_t pos = 0;
    uint8_t attributeId = m_rxBuffer[pos++];
    ApiMac_status_t status = ApiMac_status_unsupportedAttribute;

    switch (attributeId)
    {                        
    case 0: { //Note: Logical Channel does not have a standard ID in IEEE 802.15.4-2006
        ApiMac_mlmeSetReqUint8(ApiMac_attribute_logicalChannel,
                               m_rxBuffer[pos++]);
        break;
    }  
    case 0x04: //Note: Channel Page does not have a standard ID IEEE 802.15.4-2006
    {
        ApiMac_mlmeSetReqUint8(ApiMac_attribute_channelPage,
                               m_rxBuffer[pos++]);
        break;
    }   
    case ApiMac_attribute_ackWaitDuration:
        ApiMac_mlmeSetReqUint8(ApiMac_attribute_ackWaitDuration,
                               m_rxBuffer[pos++]);
        break;
    case ApiMac_attribute_associatePermit: 
        ApiMac_mlmeSetReqBool(ApiMac_attribute_associatePermit,
                              (bool) m_rxBuffer[pos++]);
        break;
    case ApiMac_attribute_autoRequest: 
        ApiMac_mlmeSetReqBool(ApiMac_attribute_autoRequest,
                              (bool) m_rxBuffer[pos++]);
        break;
    case ApiMac_attribute_battLifeExt: 
        ApiMac_mlmeSetReqBool(ApiMac_attribute_battLifeExt,
                              (bool) m_rxBuffer[pos++]);
        break;
    case ApiMac_attribute_battLifeExtPeriods: 
        ApiMac_mlmeSetReqUint8(ApiMac_attribute_battLifeExtPeriods,
                               m_rxBuffer[pos++]);
        break;
    case ApiMac_attribute_beaconPayload: {    
  
        uint8_t beaconPayloadLength = 0;
        ApiMac_mlmeGetReqUint8(ApiMac_attribute_beaconPayloadLength,
                               &beaconPayloadLength);

        uint8_t beaconPayload[beaconPayloadLength];
        for (int i = 0; i < beaconPayloadLength; i++)
        {
            beaconPayload[i] = m_rxBuffer[pos++];
        }
        ApiMac_mlmeSetReqArray(ApiMac_attribute_beaconPayload, beaconPayload);
        break;
    }
    case ApiMac_attribute_beaconPayloadLength: 
        status = ApiMac_mlmeSetReqUint8(ApiMac_attribute_beaconPayloadLength,
                                        m_rxBuffer[pos++]);
        break;
    case ApiMac_attribute_beaconOrder: 
        status = ApiMac_mlmeSetReqUint8(ApiMac_attribute_beaconOrder,
                                        m_rxBuffer[pos++]);
        break;
    case ApiMac_attribute_beaconTxTime: { 
        uint32_t txTime;
        txTime = m_rxBuffer[pos++];
        txTime |= ((m_rxBuffer[pos++]) << 8);
        txTime |= ((m_rxBuffer[pos++]) << 16);
        txTime |= ((m_rxBuffer[pos++]) << 24);
        status = ApiMac_mlmeSetReqUint32(ApiMac_attribute_beaconTxTime,
                                         txTime);
        break;
    }
    case ApiMac_attribute_bsn:  
        status = ApiMac_mlmeSetReqUint8(ApiMac_attribute_bsn,
                                        m_rxBuffer[pos++]);
        break;
    case ApiMac_attribute_coordExtendedAddress: { 
        uint8_t coordExtAddr[8];
        for (int i =0; i<8; i++)
        {
            coordExtAddr[i] = m_rxBuffer[pos++];
        }
        ApiMac_mlmeSetReqArray(ApiMac_attribute_coordExtendedAddress,
                               coordExtAddr);
        break;
    }
    case ApiMac_attribute_coordShortAddress: { 
        uint16_t coordShortAddr;
        coordShortAddr = m_rxBuffer[pos++];
        coordShortAddr |= ((m_rxBuffer[pos++]) << 8);
        status = ApiMac_mlmeSetReqUint16(ApiMac_attribute_coordShortAddress,
                                         coordShortAddr);
        break;
    }
    case ApiMac_attribute_dsn: 
        status = ApiMac_mlmeSetReqUint8(ApiMac_attribute_dsn,
                               m_rxBuffer[pos++]);
        break;
    case ApiMac_attribute_gtsPermit: 
        status = ApiMac_mlmeSetReqBool(ApiMac_attribute_gtsPermit,
                              (bool) m_rxBuffer[pos++]);
        break;
    case ApiMac_attribute_maxCsmaBackoffs: 
        status = ApiMac_mlmeSetReqUint8(ApiMac_attribute_maxCsmaBackoffs,
                               m_rxBuffer[pos++]);
        break;
    case ApiMac_attribute_backoffExponent: 
        status = ApiMac_mlmeSetReqUint8(ApiMac_attribute_backoffExponent,
                               m_rxBuffer[pos++]);
        break;
    case ApiMac_attribute_panId: { 
        uint16_t panId;
        panId = m_rxBuffer[pos++];
        panId |= ((m_rxBuffer[pos++]) << 8);
        status = ApiMac_mlmeSetReqUint16(ApiMac_attribute_panId,
                                panId);
        break;
    }
    case ApiMac_attribute_promiscuousMode: 
        status = ApiMac_mlmeSetReqBool(ApiMac_attribute_promiscuousMode,
                              (bool) m_rxBuffer[pos++]);
        break;
    case ApiMac_attribute_RxOnWhenIdle: 
        status = ApiMac_mlmeSetReqBool(ApiMac_attribute_RxOnWhenIdle,
                              (bool) m_rxBuffer[pos++]);
        break;
    case ApiMac_attribute_shortAddress: { 
        uint16_t shortAddress;
        shortAddress = m_rxBuffer[pos++];
        shortAddress |= ((m_rxBuffer[pos++]) << 8);
        status = ApiMac_mlmeSetReqUint16(ApiMac_attribute_shortAddress,
                                shortAddress);
        break;
    }
    case ApiMac_attribute_superframeOrder: 
        status = ApiMac_mlmeSetReqUint8(ApiMac_attribute_superframeOrder,
                               m_rxBuffer[pos++]);
        break;
    case ApiMac_attribute_transactionPersistenceTime: { 
        uint16_t persistenceTime;
        persistenceTime = m_rxBuffer[pos++];
        persistenceTime |= ((m_rxBuffer[pos++]) << 8);
        status = ApiMac_mlmeSetReqUint16(ApiMac_attribute_transactionPersistenceTime,
                                persistenceTime);
        break;
    }
    case ApiMac_attribute_maxFrameRetries: 
        status = ApiMac_mlmeSetReqUint8(ApiMac_attribute_maxFrameRetries,
                               m_rxBuffer[pos++]);
        break;
    case ApiMac_attribute_responseWaitTime: {
        status = ApiMac_mlmeSetReqUint8(ApiMac_attribute_responseWaitTime,
                               m_rxBuffer[pos++]);
        break;
    }
    default:
        status = ApiMac_status_unsupportedAttribute;
        break;
    }

    // CC1352 do not have a designated Set Confirm
    // as described by the IEEE 802.15.4,  the following 
    // provides such functionality.
    uint8_t setCfmParams[5];
    setCfmParams[0] = 0xAA;
    setCfmParams[1] = SET_CFM;
    setCfmParams[2] = 2; // size of parameters (2 bytes)
    setCfmParams[3] = attributeId;
    setCfmParams[4] = (uint8_t)status;
    SendBytes(setCfmParams, 5);
}

void GetRequest()
{
     
    uint8_t u8intAttributeValue = 0;
    uint16_t u16intAttributeValue = 0;
    uint32_t u32intAttributeValue = 0;
    bool boolAttributeValue = false;
    uint8_t u8arrayAttributeValue[255];
    enum TypeRequest{u8,
                     u16,
                     u32,
                     boolReq,
                     u8array,
                     payload,
                     unsupported} typeRequest;
    ApiMac_status_t status;
     
    uint8_t pos = 0;
    uint8_t getCfmParams[255];

    uint8_t attributeId = m_rxBuffer[0]; //receive the attribute ID from UART

    getCfmParams[pos++] = 0xAA;
    getCfmParams[pos++] = GET_CFM;

    switch (attributeId)
    {
    //Note: Logical Channel does not have a standard ID in IEEE 802.15.4-2006
    case 0: 
        status = ApiMac_mlmeGetReqUint8(ApiMac_attribute_logicalChannel, &u8intAttributeValue);
        typeRequest = u8;
        break;
    //Note: Channel Page does not have a standard ID IEEE 802.15.4-2006
    case 0x04:
        status = ApiMac_mlmeGetReqUint8(ApiMac_attribute_channelPage, &u8intAttributeValue);
        typeRequest = u8;
        break;
    case 0x6f: // Extended Address  
        // Received a request for extended address
        // This attribute is not compliant for 2003 and 2006 versions of the standard
        // but it was later on added to 2011 edition. The id also does not match the 
        // value of ApiMac_attribute_extendedAddress which uses 0xE2 id in CC1352       
        status = ApiMac_mlmeGetReqArray(ApiMac_attribute_extendedAddress, &u8intAttributeValue);
        typeRequest = u8array;
        break;
    case ApiMac_attribute_ackWaitDuration:
        status = ApiMac_mlmeGetReqUint8(ApiMac_attribute_ackWaitDuration, &u8intAttributeValue);
        typeRequest = u8;
        break;
    case ApiMac_attribute_associatePermit: 
        status = ApiMac_mlmeGetReqBool(ApiMac_attribute_associatePermit, &boolAttributeValue);
        typeRequest = boolReq;
        break;
    case ApiMac_attribute_autoRequest:
        status = ApiMac_mlmeGetReqBool(ApiMac_attribute_autoRequest, &boolAttributeValue);
        typeRequest = u8;
        break;
    case ApiMac_attribute_battLifeExt:
        status = ApiMac_mlmeGetReqBool(ApiMac_attribute_battLifeExt, &boolAttributeValue);
        typeRequest = boolReq;
        break;
    case ApiMac_attribute_battLifeExtPeriods:
        status = ApiMac_mlmeGetReqUint8(ApiMac_attribute_battLifeExtPeriods, &u8intAttributeValue);
        typeRequest = u8;
        break;
    case ApiMac_attribute_beaconPayload:
        status = ApiMac_mlmeGetReqArray(ApiMac_attribute_beaconPayload, u8arrayAttributeValue);
        typeRequest = payload;
    case ApiMac_attribute_beaconPayloadLength: 
        status = ApiMac_mlmeGetReqUint8(ApiMac_attribute_beaconPayloadLength, &u8intAttributeValue);
        typeRequest = u8;
        break;    
    case ApiMac_attribute_beaconOrder: 
        status = ApiMac_mlmeGetReqUint8(ApiMac_attribute_beaconOrder, &u8intAttributeValue);
        typeRequest = u8;
        break; 
    case ApiMac_attribute_beaconTxTime:
        status = ApiMac_mlmeGetReqUint32(ApiMac_attribute_beaconTxTime, &u32intAttributeValue);
        typeRequest = u32;
        break; 
    case ApiMac_attribute_bsn:
        status = ApiMac_mlmeGetReqUint8(ApiMac_attribute_bsn, &u8intAttributeValue);
        typeRequest = u8;
        break;
    case ApiMac_attribute_coordExtendedAddress: 
        status = ApiMac_mlmeGetReqArray(ApiMac_attribute_coordExtendedAddress, 
                                        u8arrayAttributeValue);
        typeRequest = u8array;
        break;
    case ApiMac_attribute_coordShortAddress:
        status = ApiMac_mlmeGetReqUint16(ApiMac_attribute_coordShortAddress, 
                                         &u16intAttributeValue);
        typeRequest = u16;
        break;
    case ApiMac_attribute_dsn:
        status = ApiMac_mlmeGetReqUint8(ApiMac_attribute_dsn, &u8intAttributeValue);
        typeRequest = u8;
        break;
    case ApiMac_attribute_maxCsmaBackoffs:
        status = ApiMac_mlmeGetReqUint8(ApiMac_attribute_maxCsmaBackoffs, &u8intAttributeValue);
        typeRequest = u8;
        break;
    case ApiMac_attribute_backoffExponent:
        status = ApiMac_mlmeGetReqUint8(ApiMac_attribute_backoffExponent, &u8intAttributeValue);
        typeRequest = u8;
        break;
    case ApiMac_attribute_panId:
        status = ApiMac_mlmeGetReqUint16(ApiMac_attribute_panId, &u16intAttributeValue);
        typeRequest = u16;
        break;
    case ApiMac_attribute_promiscuousMode: 
        status = ApiMac_mlmeGetReqBool(ApiMac_attribute_promiscuousMode, &boolAttributeValue);
        typeRequest = boolReq;
        break;
    case ApiMac_attribute_RxOnWhenIdle:
        status = ApiMac_mlmeGetReqBool(ApiMac_attribute_RxOnWhenIdle, &boolAttributeValue);
        typeRequest = boolReq;
        break;
    case ApiMac_attribute_shortAddress:
        status = ApiMac_mlmeGetReqUint16(ApiMac_attribute_shortAddress, &u16intAttributeValue);
        typeRequest = u16;
        break;
    case ApiMac_attribute_superframeOrder:
        status = ApiMac_mlmeGetReqUint8(ApiMac_attribute_superframeOrder, &u8intAttributeValue);
        typeRequest = u8;
        break;
    case ApiMac_attribute_transactionPersistenceTime:
        status = ApiMac_mlmeGetReqUint16(ApiMac_attribute_transactionPersistenceTime, 
                                         &u16intAttributeValue);
        typeRequest = u16;
        break;
    case ApiMac_attribute_maxFrameRetries:
        status = ApiMac_mlmeGetReqUint8(ApiMac_attribute_maxFrameRetries, &u8intAttributeValue);
        typeRequest = u8;
        break;
    case ApiMac_attribute_responseWaitTime:
        status = ApiMac_mlmeGetReqUint8(ApiMac_attribute_responseWaitTime, &u8intAttributeValue);
        typeRequest = u8;
        break;
    default:
        status = ApiMac_status_unsupported;
        typeRequest = unsupported;
        break;
    }



    switch(typeRequest)
    {
        case u8:
           getCfmParams[pos++] = 3;
           getCfmParams[pos++] = (uint8_t) status;
           getCfmParams[pos++] = attributeId;
           getCfmParams[pos++] = u8intAttributeValue;
           break;
        case u16:
           getCfmParams[pos++] = 4;
           getCfmParams[pos++] = (uint8_t) status;
           getCfmParams[pos++] = attributeId;
           getCfmParams[pos++] = (u16intAttributeValue & 0xFF);
           getCfmParams[pos++] = (u16intAttributeValue >> 8) & 0xFF;
           break;
        case u32:
           getCfmParams[pos++] = 6;
           getCfmParams[pos++] = (uint8_t) status;
           getCfmParams[pos++] = attributeId;
           getCfmParams[pos++] = (u32intAttributeValue & 0xFF);
           getCfmParams[pos++] = (u32intAttributeValue >> 8) & 0xFF;
           getCfmParams[pos++] = (u32intAttributeValue >> 16) & 0xFF;
           getCfmParams[pos++] = (u32intAttributeValue >> 24) & 0xFF;
           break;
        case boolReq:
           getCfmParams[pos++] = 3;
           getCfmParams[pos++] = (uint8_t) status;
           getCfmParams[pos++] = attributeId;
           getCfmParams[pos++] = (uint8_t) boolAttributeValue;
           break;
        case u8array:
           getCfmParams[pos++] = 10;
           getCfmParams[pos++] = (uint8_t) status;
           getCfmParams[pos++] = attributeId;
           for (int i = 0; i < 8; i++)
           {
               getCfmParams[pos++] = u8arrayAttributeValue[i];
           }
           break;
        case payload:
        {
            uint8_t beaconPayloadLength = 0;
            ApiMac_mlmeGetReqUint8(ApiMac_attribute_beaconPayloadLength, 
                                   &beaconPayloadLength);

            getCfmParams[pos++] = beaconPayloadLength + 2;
            getCfmParams[pos++] = (uint8_t) status;
            getCfmParams[pos++] = attributeId;                     
            for (int i = 0; i < beaconPayloadLength; i++)
            {
                getCfmParams[pos++] = u8arrayAttributeValue[i];
            }
            break;
        }
        case unsupported:
           getCfmParams[pos++] = 2;
           getCfmParams[pos++] = (uint8_t) status;
           getCfmParams[pos++] = attributeId;
           break;
    }

    SendBytes(getCfmParams, pos);
}


void ProcessData(void)
{
    /* 1. Handle Application Events 
       (Simplified: only check for data-related or start events) */
    if (Collector_events & COLLECTOR_START_EVT) 
    {
        Util_clearEvent(&Collector_events, COLLECTOR_START_EVT);
    }

    /* 2. Run Sub-module State Machines 
       Required to keep the network and link layer alive */
    //Cllc_process();
   // Csf_processEvents();

    /* 3. Process Incoming MAC Data 
       This triggers the dataIndCB (Data Indication Callback) 
       where your actual sensor payload is usually parsed. */
    if (Collector_events == 0) 
    {
        ApiMac_processIncoming();
    }
}













#ifdef TX_POWER_TEST
uint32_t txPowerLimitTest = 0;
uint8_t txTestPower1 = 0;
uint8_t txTestPower2 = 5;

#endif


/*!
 * @brief      Send MAC broadcast data request.
 *             This function can be used to send broadcast messages
 *             in all modes for non sleepy devices only.
 *
 * @param      type - message type
 * @param      len - length of payload
 * @param      pData - pointer to the buffer
 */
static void sendBroadcastMsg(Smsgs_cmdIds_t type, uint16_t len,
                    uint8_t *pData)
{
    ApiMac_mcpsDataReq_t dataReq;

    /* Current example is only implemented for FH mode */
    if(!fhEnabled)
    {
        return;
    }
    /* Fill the data request field */
    memset(&dataReq, 0, sizeof(ApiMac_mcpsDataReq_t));

    dataReq.dstAddr.addrMode = ApiMac_addrType_none;
    dataReq.srcAddrMode = ApiMac_addrType_short;

    dataReq.dstPanId = devicePanId;

    dataReq.msduHandle =  0;

    dataReq.txOptions.ack = false;
    dataReq.txOptions.indirect = false;


    dataReq.msdu.len = len;
    dataReq.msdu.p = pData;

    /* Send the message */
    ApiMac_mcpsDataReq(&dataReq);
}


#ifdef FEATURE_SECURE_COMMISSIONING

/*!
 * @brief      Security manager failure processing function
 */
void smFailCMProcessCb(ApiMac_deviceDescriptor_t *devInfo, bool rxOnIdle,
                       bool keyRefreshment, SMMsgs_errorCode_t smErrorCode)
{
    /* Duration value for re-opening network */
    uint32_t duration = 0xFFFFFFFF;

    /* Process SM failure */
    if (keyRefreshment == true)
    {
        /* Device failed key refreshment process. Key not refreshed */

        /* Re-enable joining if it was enabled prior to key refreshment process */
        if (permitJoining) {
            Cllc_setJoinPermit(duration);
        }

#ifdef USE_DMM
        DMMPolicy_updateApplicationState(DMMPolicy_StackRole_154Collector, DMMPOLICY_154_UNINIT);
        RemoteDisplay_updateSmState(SMCOMMISSIONSTATE_FAIL);
#endif /* USE_DMM */
    }
    else if ((smErrorCode == SMMsgs_errorCode_noMatchAuthVal) ||
             (smErrorCode == SMMsgs_errorCode_noMatchKeyConfirm) ||
             (smErrorCode == SMMsgs_errorCode_unsupportedAuthMethod) ||
             (SM_cmAttempts >= SM_CM_MAX_RETRY_ATTEMPTS))
    {
        /* Device failed authentication, exceeded max commissioning attempts,
         * or user has not allowed commissioning retry */

        /* Send a disassociation request to the device */
        Cllc_sendDisassociationRequest(devInfo->shortAddress, rxOnIdle);
        /* Remove device from the NV list when receiving disassocCnfCb */

        if (SM_cmAttempts >= SM_CM_MAX_RETRY_ATTEMPTS)
        {
          SM_cmAttempts = 0;
        }

        Util_setEvent(&Collector_events, COLLECTOR_CONFIG_EVT);

        /* Re-enable joining if commissioning was a result of device
         * association as network must have already been open for
         * association to occur
         */
        if (!fCommissionRequired) {
            Cllc_setJoinPermit(duration);
        }

#ifdef USE_DMM
        DMMPolicy_updateApplicationState(DMMPolicy_StackRole_154Collector, DMMPOLICY_154_UNINIT);
        RemoteDisplay_updateSmState(SMCOMMISSIONSTATE_FAIL);
#endif /* USE_DMM */
    }
    else
    {
        /* sensor not responding to process start message in key recovery mode */
        if ((fCommissionRequired) && (smErrorCode == SMMsgs_errorCode_reComm_sensor_notResp))
        {
            int8_t i = 0;

            /* find the index of the device with the above short address*/
            for(i = 0; i < CONFIG_MAX_DEVICES; i++)
            {
                if(Cllc_associatedDevList[i].shortAddr == devInfo->shortAddress)
                {
                    /* set the reCM_status to pending*/
                    Cllc_associatedDevList[i].reCM_status = SM_RE_CM_PENDING;

                    /* mark the device not alive*/
                    Cllc_associatedDevList[i].status &=
                                            ~(CLLC_ASSOC_STATUS_ALIVE| ASSOC_CONFIG_SENT | ASSOC_CONFIG_RSP);
                    /* found the index; so break */
                    break;
                }
            }
        }
        else
        {
            ApiMac_sec_t devSec;

            /* Obtain MAC level security information */
            Cllc_securityFill(&devSec);

            /* Kick off commissioning process to obtain security information */
            SM_startCMProcess(devInfo, &devSec, CONFIG_FH_ENABLE,
                                          rxOnIdle, SM_type_coordinator, SM_COLLECTOR_AUTH_METHODS);

        }
    }
}

/*!
 * @brief      Security manager success processing function
 */
void smSuccessCMProcessCb(ApiMac_deviceDescriptor_t *devInfo, bool keyRefreshment)
{
    /* Re-enable joining if it was enabled prior to key refreshment process, or
     * if commissioning was a result of device association as network must have
     * been open for association to occur
     */
    if (keyRefreshment) {

        if (permitJoining) {
            // the permitJoining was allowed before, so let's allow it
            uint32_t duration = 0xFFFFFFFF;
            Cllc_setJoinPermit(duration);
        }
    }
    else if (fCommissionRequired == false) {
        // secure commissioning. The permitJoining was allowed before, so let's allow it
        uint32_t duration = 0xFFFFFFFF;
        Cllc_setJoinPermit(duration);
    }

    if (keyRefreshment != true)
    {
        Util_setEvent(&Collector_events, COLLECTOR_CONFIG_EVT);
    }
#ifdef USE_DMM
    DMMPolicy_updateApplicationState(DMMPolicy_StackRole_154Collector, DMMPOLICY_154_CONNECTED);
    RemoteDisplay_updateSmState(SMCOMMISSIONSTATE_SUCCESS);
#endif /* USE_DMM */
}
#endif /* FEATURE_SECURE_COMMISSIONING */



#ifdef DMM_OAD

/*********************************************************************
 * @fn      Collector_dmmPausePolicyCb
 *
 * @brief   DMM Policy callback to pause 154 Stack
 */
static void Collector_dmmPausePolicyCb(uint16_t pause)
{
    if (pause)
    {   //pause 154sensor
        Util_setEvent(&Collector_events, COLLECTOR_PAUSE_EVT);
    }
    else
    {   //unpause 154sensor
        Util_setEvent(&Collector_events, COLLECTOR_RESUME_EVT);
    }

    // Wake up the application thread when it waits for clock event
    sem_post(sem);
}

#endif
