dc876e5f0063266d73d67f7e9c2f089b03bda86a
[apps/tidep0084.git] / example / collector / collector.c
1 /******************************************************************************
3  @file collector.c
5  @brief TIMAC 2.0 Collector Example Application
7  Group: WCS LPC
8  $Target Devices: Linux: AM335x, Embedded Devices: CC1310, CC1350$
10  ******************************************************************************
11  $License: BSD3 2016 $
13    Copyright (c) 2015, Texas Instruments Incorporated
14    All rights reserved.
16    Redistribution and use in source and binary forms, with or without
17    modification, are permitted provided that the following conditions
18    are met:
20    *  Redistributions of source code must retain the above copyright
21       notice, this list of conditions and the following disclaimer.
23    *  Redistributions in binary form must reproduce the above copyright
24       notice, this list of conditions and the following disclaimer in the
25       documentation and/or other materials provided with the distribution.
27    *  Neither the name of Texas Instruments Incorporated nor the names of
28       its contributors may be used to endorse or promote products derived
29       from this software without specific prior written permission.
31    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
32    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
33    THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
34    PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
35    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
36    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
37    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
38    OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
39    WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
40    OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
41    EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42  ******************************************************************************
43  $Release Name: TI-15.4Stack Linux x64 SDK$
44  $Release Date: Jun 28, 2017 (2.02.00.03)$
45  *****************************************************************************/
47 /******************************************************************************
48  Includes
49  *****************************************************************************/
50 #include <string.h>
51 #include <stdint.h>
52 #include <stdio.h>
54 #include "util.h"
55 #include "api_mac.h"
56 #include "cllc.h"
57 #include "csf.h"
58 #include "smsgs.h"
59 #include "collector.h"
61 #include "log.h"
63 #include <oad_protocol.h>
65 /******************************************************************************
66  Constants and definitions
67  *****************************************************************************/
69 #if !defined(CONFIG_AUTO_START)
70 #if defined(AUTO_START)
71 #define CONFIG_AUTO_START 1
72 #else
73 #define CONFIG_AUTO_START 0
74 #endif
75 #endif
77 /* Beacon order for non beacon network */
78 #define NON_BEACON_ORDER      15
80 /* Default MSDU Handle rollover */
81 #define MSDU_HANDLE_MAX 0x3F
83 /* App marker in MSDU handle */
84 #define APP_MARKER_MSDU_HANDLE 0x80
86 /* App Config request marker for the MSDU handle */
87 #define APP_CONFIG_MSDU_HANDLE 0x40
89 /* Default configuration frame control */
90 #define CONFIG_FRAME_CONTROL (Smsgs_dataFields_tempSensor | \
91                               Smsgs_dataFields_lightSensor | \
92                               Smsgs_dataFields_humiditySensor | \
93                               Smsgs_dataFields_msgStats | \
94                               Smsgs_dataFields_configSettings | \
95                               Smsgs_dataFields_pressureSensor | \
96                               Smsgs_dataFields_motionSensor | \
97                               Smsgs_dataFields_batterySensor | \
98                               Smsgs_dataFields_hallEffectSensor | \
99                               Smsgs_dataFields_fanSensor | \
100                               Smsgs_dataFields_doorLockSensor)
102 #if ((CONFIG_PHY_ID >= APIMAC_MRFSK_STD_PHY_ID_BEGIN) && (CONFIG_PHY_ID <= APIMAC_MRFSK_GENERIC_PHY_ID_BEGIN))
103 /* MAC Indirect Persistent Timeout */
104 #define INDIRECT_PERSISTENT_TIME 750
105 /* Default configuration reporting interval, in milliseconds */
106 #define CONFIG_REPORTING_INTERVAL_DEFAULT 90000
108 /* Default configuration polling interval, in milliseconds */
109 #define CONFIG_POLLING_INTERVAL_DEFAULT 6000
111 /* Delay for config request retry in busy network */
112 #define CONFIG_DELAY 1000
113 #define CONFIG_RESPONSE_DELAY 3*CONFIG_DELAY
114 /* Tracking timeouts */
115 #define TRACKING_CNF_DELAY_TIME 2000 /* in milliseconds */
116 #define TRACKING_DELAY_TIME 60000 /* in milliseconds */
117 #define TRACKING_TIMEOUT_TIME (CONFIG_POLLING_INTERVAL * 2) /*in milliseconds*/
118 #else
119 /* MAC Indirect Persistent Timeout
120  * This is in units of aBaseSuperframeDuration.
121  * It will be scaled accordingly for beacon mode.
122  * */
123 #define INDIRECT_PERSISTENT_TIME 3750
124 /* Default configuration reporting interval, in milliseconds */
125 #define CONFIG_REPORTING_INTERVAL_DEFAULT 300000
127 /* Default configuration polling interval, in milliseconds */
128 #define CONFIG_POLLING_INTERVAL_DEFAULT 60000
130 /* Delay for config request retry in busy network */
131 #define CONFIG_DELAY 5000
132 #define CONFIG_RESPONSE_DELAY 3*CONFIG_DELAY
133 /* Tracking timeouts */
134 #define TRACKING_CNF_DELAY_TIME 10000 /* in milliseconds */
135 #define TRACKING_DELAY_TIME 300000 /* in milliseconds */
136 #define TRACKING_TIMEOUT_TIME (CONFIG_POLLING_INTERVAL_DEFAULT * 2) /*in milliseconds*/
137 #endif
139 int linux_CONFIG_REPORTING_INTERVAL = CONFIG_REPORTING_INTERVAL_DEFAULT;
140 #define CONFIG_REPORTING_INTERVAL linux_CONFIG_REPORTING_INTERVAL
141 int linux_CONFIG_POLLING_INTERVAL = CONFIG_POLLING_INTERVAL_DEFAULT;
142 #define CONFIG_POLLING_INTERVAL linux_CONFIG_POLLING_INTERVAL
144 /* Assoc Table (CLLC) status settings */
145 #define ASSOC_CONFIG_SENT       0x0100    /* Config Req sent */
146 #define ASSOC_CONFIG_RSP        0x0200    /* Config Rsp received */
147 #define ASSOC_CONFIG_MASK       0x0300    /* Config mask */
148 #define ASSOC_TRACKING_SENT     0x1000    /* Tracking Req sent */
149 #define ASSOC_TRACKING_RSP      0x2000    /* Tracking Rsp received */
150 #define ASSOC_TRACKING_RETRY    0x4000    /* Tracking Req retried */
151 #define ASSOC_TRACKING_ERROR    0x8000    /* Tracking Req error */
152 #define ASSOC_TRACKING_MASK     0xF000    /* Tracking mask  */
154 #define MAX_OAD_FILES           10
156 #ifdef TIRTOS_IN_ROM
157 #define IMG_HDR_ADDR            0x04F0
158 #else
159 #define IMG_HDR_ADDR            0x0000
160 #endif
162 typedef struct
164     uint8_t oad_file_id;
165     char oad_file[256];
166 }oadFile_t;
168 /******************************************************************************
169  Global variables
170  *****************************************************************************/
172 /* Task pending events */
173 uint16_t Collector_events = 0;
175 /*! Collector statistics */
176 Collector_statistics_t Collector_statistics;
178 /******************************************************************************
179  Local variables
180  *****************************************************************************/
182 static void *sem;
184 /*! true if the device was restarted */
185 static bool restarted = false;
187 /*! CLLC State */
188 static Cllc_states_t cllcState = Cllc_states_initWaiting;
190 /*! Device's PAN ID */
191 static uint16_t devicePanId = 0xFFFF;
193 /*! Device's Outgoing MSDU Handle values */
194 static uint8_t deviceTxMsduHandle = 0;
196 static bool fhEnabled = false;
198 static oadFile_t oad_file_list[MAX_OAD_FILES] = {{0}};
199 static uint16_t oadBNumBlocks;
201 /******************************************************************************
202  Local function prototypes
203  *****************************************************************************/
204 static void initializeClocks(void);
205 static void cllcStartedCB(Llc_netInfo_t *pStartedInfo);
206 static ApiMac_assocStatus_t cllcDeviceJoiningCB(
207                 ApiMac_deviceDescriptor_t *pDevInfo,
208                 ApiMac_capabilityInfo_t *pCapInfo);
209 static void cllcStateChangedCB(Cllc_states_t state);
210 static void dataCnfCB(ApiMac_mcpsDataCnf_t *pDataCnf);
211 static void dataIndCB(ApiMac_mcpsDataInd_t *pDataInd);
212 static void disassocIndCB(ApiMac_mlmeDisassociateInd_t *pDisassocInd);
213 static void disassocCnfCB(ApiMac_mlmeDisassociateCnf_t *pDisassocCnf);
214 static void processStartEvent(void);
215 static void processConfigResponse(ApiMac_mcpsDataInd_t *pDataInd);
216 static void processTrackingResponse(ApiMac_mcpsDataInd_t *pDataInd);
217 static void processToggleLedResponse(ApiMac_mcpsDataInd_t *pDataInd);
218 static void processSensorData(ApiMac_mcpsDataInd_t *pDataInd);
219 static void processOadData(ApiMac_mcpsDataInd_t *pDataInd);
220 static Cllc_associated_devices_t *findDevice(ApiMac_sAddr_t *pAddr);
221 static Cllc_associated_devices_t *findDeviceStatusBit(uint16_t mask, uint16_t statusBit);
222 static uint8_t getMsduHandle(Smsgs_cmdIds_t msgType);
223 static bool sendMsg(Smsgs_cmdIds_t type, uint16_t dstShortAddr, bool rxOnIdle,
224                     uint16_t len,
225                     uint8_t *pData);
226 static void generateConfigRequests(void);
227 static void generateTrackingRequests(void);
228 static void sendTrackingRequest(Cllc_associated_devices_t *pDev);
229 static void commStatusIndCB(ApiMac_mlmeCommStatusInd_t *pCommStatusInd);
230 static void pollIndCB(ApiMac_mlmePollInd_t *pPollInd);
231 static void processDataRetry(ApiMac_sAddr_t *pAddr);
232 static void processConfigRetry(void);
234 static void oadFwVersionRspCb(void* pSrcAddr, char *fwVersionStr);
235 static void oadImgIdentifyRspCb(void* pSrcAddr, uint8_t status);
236 static void oadBlockReqCb(void* pSrcAddr, uint8_t imgId, uint16_t blockNum, uint16_t multiBlockSize);
238 static void* oadRadioAccessAllocMsg(uint32_t size);
239 static OADProtocol_Status_t oadRadioAccessPacketSend(void* pDstAddr, uint8_t *pMsg, uint32_t msgLen);
241 /******************************************************************************
242  Callback tables
243  *****************************************************************************/
245 /*! API MAC Callback table */
246 ApiMac_callbacks_t Collector_macCallbacks =
247     {
248       /*! Associate Indicated callback */
249       NULL,
250       /*! Associate Confirmation callback */
251       NULL,
252       /*! Disassociate Indication callback */
253       disassocIndCB,
254       /*! Disassociate Confirmation callback */
255       disassocCnfCB,
256       /*! Beacon Notify Indication callback */
257       NULL,
258       /*! Orphan Indication callback */
259       NULL,
260       /*! Scan Confirmation callback */
261       NULL,
262       /*! Start Confirmation callback */
263       NULL,
264       /*! Sync Loss Indication callback */
265       NULL,
266       /*! Poll Confirm callback */
267       NULL,
268       /*! Comm Status Indication callback */
269       commStatusIndCB,
270       /*! Poll Indication Callback */
271       pollIndCB,
272       /*! Data Confirmation callback */
273       dataCnfCB,
274       /*! Data Indication callback */
275       dataIndCB,
276       /*! Purge Confirm callback */
277       NULL,
278       /*! WiSUN Async Indication callback */
279       NULL,
280       /*! WiSUN Async Confirmation callback */
281       NULL,
282       /*! Unprocessed message callback */
283       NULL
284     };
286 static Cllc_callbacks_t cllcCallbacks =
287     {
288       /*! Coordinator Started Indication callback */
289       cllcStartedCB,
290       /*! Device joining callback */
291       cllcDeviceJoiningCB,
292       /*! The state has changed callback */
293       cllcStateChangedCB
294     };
296 static OADProtocol_RadioAccessFxns_t  oadRadioAccessFxns =
297     {
298       oadRadioAccessAllocMsg,
299       oadRadioAccessPacketSend
300     };
302 static OADProtocol_MsgCBs_t oadMsgCallbacks =
303     {
304       /*! Incoming FW Req */
305       NULL,
306       /*! Incoming FW Version Rsp */
307       oadFwVersionRspCb,
308       /*! Incoming Image Identify Req */
309       NULL,
310       /*! Incoming Image Identify Rsp */
311       oadImgIdentifyRspCb,
312       /*! Incoming OAD Block Req */
313       oadBlockReqCb,
314       /*! Incoming OAD Block Rsp */
315       NULL
316     };
318 /******************************************************************************
319  Public Functions
320  *****************************************************************************/
322 /*!
323  Initialize this application.
325  Public function defined in collector.h
326  */
327 void Collector_init(void)
329     OADProtocol_Params_t OADProtocol_params;
331     /* Initialize the collector's statistics */
332     memset(&Collector_statistics, 0, sizeof(Collector_statistics_t));
334     /* Initialize the MAC */
335     sem = ApiMac_init(CONFIG_FH_ENABLE);
337     /* Initialize the Coordinator Logical Link Controller */
338     Cllc_init(&Collector_macCallbacks, &cllcCallbacks);
340     /* Register the MAC Callbacks */
341     ApiMac_registerCallbacks(&Collector_macCallbacks);
343     /* Initialize the platform specific functions */
344     Csf_init(sem);
346     /* Set the indirect persistent timeout */
347     if(CONFIG_MAC_BEACON_ORDER != NON_BEACON_ORDER)
348     {
349         ApiMac_mlmeSetReqUint16(ApiMac_attribute_transactionPersistenceTime, (INDIRECT_PERSISTENT_TIME >> CONFIG_MAC_BEACON_ORDER));
350     }
351     else
352     {
353         ApiMac_mlmeSetReqUint16(ApiMac_attribute_transactionPersistenceTime, INDIRECT_PERSISTENT_TIME);
354     }
356     ApiMac_mlmeSetReqUint8(ApiMac_attribute_phyTransmitPowerSigned,
357                            (uint8_t)CONFIG_TRANSMIT_POWER);
359 #ifdef FCS_TYPE16
360     /* Set the fcs type */
361     ApiMac_mlmeSetReqBool(ApiMac_attribute_fcsType,
362                           (bool)1);
363 #endif
365     /* Initialize the app clocks */
366     initializeClocks();
368     if(CONFIG_AUTO_START)
369     {
370         /* Start the device */
371         Util_setEvent(&Collector_events, COLLECTOR_START_EVT);
372     }
374     OADProtocol_Params_init(&OADProtocol_params);
375     OADProtocol_params.pRadioAccessFxns = &oadRadioAccessFxns;
376     OADProtocol_params.pProtocolMsgCallbacks = &oadMsgCallbacks;
378     OADProtocol_open(&OADProtocol_params);
382 /*!
383  Application task processing.
385  Public function defined in collector.h
386  */
387 void Collector_process(void)
389     /* Start the collector device in the network */
390     if(Collector_events & COLLECTOR_START_EVT)
391     {
392         if(cllcState == Cllc_states_initWaiting)
393         {
394             processStartEvent();
395         }
397         /* Clear the event */
398         Util_clearEvent(&Collector_events, COLLECTOR_START_EVT);
399     }
401     /* Is it time to send the next tracking message? */
402     if(Collector_events & COLLECTOR_TRACKING_TIMEOUT_EVT)
403     {
404         /* Process Tracking Event */
405         generateTrackingRequests();
407         /* Clear the event */
408         Util_clearEvent(&Collector_events, COLLECTOR_TRACKING_TIMEOUT_EVT);
409     }
411     /*
412      The generate a config request for all associated devices that need one
413      */
414     if(Collector_events & COLLECTOR_CONFIG_EVT)
415     {
416         generateConfigRequests();
418         /* Clear the event */
419         Util_clearEvent(&Collector_events, COLLECTOR_CONFIG_EVT);
420     }
422     /* Process LLC Events */
423     Cllc_process();
425     /* Allow the Specific functions to process */
426     Csf_processEvents();
428     /*
429      Don't process ApiMac messages until all of the collector events
430      are processed.
431      */
432     if(Collector_events == 0)
433     {
434         /* Wait for response message or events */
435         ApiMac_processIncoming();
436     }
439 /*!
440  Build and send the configuration message to a device.
442  Public function defined in collector.h
443  */
444 Collector_status_t Collector_sendConfigRequest(ApiMac_sAddr_t *pDstAddr,
445                                                uint16_t frameControl,
446                                                uint32_t reportingInterval,
447                                                uint32_t pollingInterval)
449     Collector_status_t status = Collector_status_invalid_state;
451     /* Are we in the right state? */
452     if(cllcState >= Cllc_states_started)
453     {
454         Llc_deviceListItem_t item;
456         /* Is the device a known device? */
457         if(Csf_getDevice(pDstAddr, &item))
458         {
459             uint8_t buffer[SMSGS_CONFIG_REQUEST_MSG_LENGTH];
460             uint8_t *pBuf = buffer;
462             /* Build the message */
463             *pBuf++ = (uint8_t)Smsgs_cmdIds_configReq;
464             *pBuf++ = Util_loUint16(frameControl);
465             *pBuf++ = Util_hiUint16(frameControl);
466             *pBuf++ = Util_breakUint32(reportingInterval, 0);
467             *pBuf++ = Util_breakUint32(reportingInterval, 1);
468             *pBuf++ = Util_breakUint32(reportingInterval, 2);
469             *pBuf++ = Util_breakUint32(reportingInterval, 3);
470             *pBuf++ = Util_breakUint32(pollingInterval, 0);
471             *pBuf++ = Util_breakUint32(pollingInterval, 1);
472             *pBuf++ = Util_breakUint32(pollingInterval, 2);
473             *pBuf = Util_breakUint32(pollingInterval, 3);
475             if((sendMsg(Smsgs_cmdIds_configReq, item.devInfo.shortAddress,
476                         item.capInfo.rxOnWhenIdle,
477                         (SMSGS_CONFIG_REQUEST_MSG_LENGTH),
478                          buffer)) == true)
479             {
480                 status = Collector_status_success;
481                 Collector_statistics.configRequestAttempts++;
482                 /* set timer for retry in case response is not received */
483                 Csf_setConfigClock(CONFIG_DELAY);
484             }
485             else
486             {
487                 processConfigRetry();
488             }
489         }
490     }
492     return (status);
495 /*!
496  Update the collector statistics
498  Public function defined in collector.h
499  */
500 void Collector_updateStats( void )
502     /* update the stats from the MAC */
503     ApiMac_mlmeGetReqUint32(ApiMac_attribute_diagRxSecureFail,
504                             &Collector_statistics.rxDecryptFailures);
506     ApiMac_mlmeGetReqUint32(ApiMac_attribute_diagTxSecureFail,
507                             &Collector_statistics.txEncryptFailures);
510 /*!
511  Build and send the toggle led message to a device.
513  Public function defined in collector.h
514  */
515 Collector_status_t Collector_sendToggleLedRequest(ApiMac_sAddr_t *pDstAddr)
517     Collector_status_t status = Collector_status_invalid_state;
519     /* Are we in the right state? */
520     if(cllcState >= Cllc_states_started)
521     {
522         Llc_deviceListItem_t item;
524         /* Is the device a known device? */
525         if(Csf_getDevice(pDstAddr, &item))
526         {
527             uint8_t buffer[SMSGS_TOGGLE_LED_REQUEST_MSG_LEN];
529             /* Build the message */
530             buffer[0] = (uint8_t)Smsgs_cmdIds_toggleLedReq;
532             sendMsg(Smsgs_cmdIds_toggleLedReq, item.devInfo.shortAddress,
533                     item.capInfo.rxOnWhenIdle,
534                     SMSGS_TOGGLE_LED_REQUEST_MSG_LEN,
535                     buffer);
537             status = Collector_status_success;
538         }
539         else
540         {
541             status = Collector_status_deviceNotFound;
542         }
543     }
545     return(status);
548 /*!
549  updates the FW list.
551  Public function defined in collector.h
552  */
553 uint32_t Collector_updateFwList(char *new_oad_file)
555     uint32_t oad_file_idx;
556     uint32_t oad_file_id;
557     bool found = false;
559     LOG_printf( LOG_ALWAYS, "Collector_updateFwList: new oad file: %s\n",
560                           new_oad_file);
562     /* Does OAD file exist */
563     for(oad_file_idx = 0; oad_file_idx < MAX_OAD_FILES; oad_file_idx++)
564     {
565         if(strcmp(new_oad_file, oad_file_list[oad_file_idx].oad_file) == 0)
566         {
567             LOG_printf( LOG_ALWAYS, "Collector_updateFwList: found ID: %d\n",
568                           oad_file_list[oad_file_idx].oad_file_id);
569             oad_file_id = oad_file_list[oad_file_idx].oad_file_id;
570             found = true;
571             break;
572         }
573     }
575     if(!found)
576     {
577         static uint32_t latest_oad_file_idx = 0;
578         static uint32_t latest_oad_file_id = 0;
580         oad_file_id = latest_oad_file_id;
582         oad_file_list[latest_oad_file_idx].oad_file_id = oad_file_id;
583         strncpy(oad_file_list[latest_oad_file_idx].oad_file, new_oad_file, 256);
585         LOG_printf( LOG_ALWAYS, "Collector_updateFwList: Added %s, ID %d\n",
586               oad_file_list[latest_oad_file_idx].oad_file,
587               oad_file_list[latest_oad_file_idx].oad_file_id);
589         latest_oad_file_id++;
590         latest_oad_file_idx++;
591         if(latest_oad_file_idx == MAX_OAD_FILES)
592         {
593             latest_oad_file_idx = 0;
594         }
595     }
597     return oad_file_id;
601 /*!
602  Send OAD version request message.
604  Public function defined in collector.h
605  */
606 Collector_status_t Collector_sendFwVersionRequest(ApiMac_sAddr_t *pDstAddr)
608     Collector_status_t status = Collector_status_invalid_state;
610     if(OADProtocol_sendFwVersionReq((void*) pDstAddr) == OADProtocol_Status_Success)
611     {
612         status = Collector_status_success;
613     }
615     return status;
618 /*!
619  Send OAD version request message.
621  Public function defined in collector.h
622  */
623 Collector_status_t Collector_startFwUpdate(ApiMac_sAddr_t *pDstAddr, uint32_t oad_file_id)
625     Collector_status_t status = Collector_status_invalid_state;
626     uint8_t imgInfoData[16];
627     uint32_t oad_file_idx;
628     FILE *oadFile;
630     for(oad_file_idx = 0; oad_file_idx < MAX_OAD_FILES; oad_file_idx++)
631     {
632         if(oad_file_list[oad_file_idx].oad_file_id == oad_file_id)
633         {
634           LOG_printf( LOG_ALWAYS, "Collector_startFwUpdate: opening file: %s\n",
635                           oad_file_list[oad_file_idx].oad_file);
637           oadFile = fopen(oad_file_list[oad_file_idx].oad_file, "r");
638           break;
639         }
640     }
642     if(oadFile)
643     {
644         fseek(oadFile, IMG_HDR_ADDR, SEEK_SET);
646         if(fread(imgInfoData, 1, 16, oadFile) == 16)
647         {
648             LOG_printf( LOG_ALWAYS, "Collector_startFwUpdate: sending ImgIdentifyReq\n");
650             oadBNumBlocks = ((imgInfoData[6]) | (imgInfoData[7] << 8) ) / (OAD_BLOCK_SIZE / 4);
652             if(OADProtocol_sendImgIdentifyReq((void*) pDstAddr, oad_file_id, imgInfoData) == OADProtocol_Status_Success)
653             {
654                 status = Collector_status_success;
655             }
656         }
658         fclose(oadFile);
659     }
660     else
661     {
662         LOG_printf( LOG_ALWAYS, "Collector_startFwUpdate: could not open file: %s\n",
663                         oad_file_list[oad_file_idx].oad_file);
664         status = Collector_status_invalid_file;
665     }
667     return status;
670 /*!
671  Find if a device is present.
673  Public function defined in collector.h
674  */
675 Collector_status_t Collector_findDevice(ApiMac_sAddr_t *pAddr)
677     Collector_status_t status = Collector_status_deviceNotFound;
679     if(findDevice(pAddr))
680     {
681         status = Collector_status_success;
682     }
684     return status;
687 /******************************************************************************
688  Local Functions
689  *****************************************************************************/
691 /*!
692  * @brief       Initialize the clocks.
693  */
694 static void initializeClocks(void)
696     /* Initialize the tracking clock */
697     Csf_initializeTrackingClock();
698     Csf_initializeConfigClock();
701 /*!
702  * @brief      CLLC Started callback.
703  *
704  * @param      pStartedInfo - pointer to network information
705  */
706 static void cllcStartedCB(Llc_netInfo_t *pStartedInfo)
708     devicePanId = pStartedInfo->devInfo.panID;
709     if(pStartedInfo->fh == true)
710     {
711         fhEnabled = true;
712     }
714     /* updated the user */
715     Csf_networkUpdate(restarted, pStartedInfo);
717     /* Start the tracking clock */
718     Csf_setTrackingClock(TRACKING_DELAY_TIME);
721 /*!
722  * @brief      Device Joining callback from the CLLC module (ref.
723  *             Cllc_deviceJoiningFp_t in cllc.h).  This function basically
724  *             gives permission that the device can join with the return
725  *             value.
726  *
727  * @param      pDevInfo - device information
728  * @param      capInfo - device's capability information
729  *
730  * @return     ApiMac_assocStatus_t
731  */
732 static ApiMac_assocStatus_t cllcDeviceJoiningCB(
733                 ApiMac_deviceDescriptor_t *pDevInfo,
734                 ApiMac_capabilityInfo_t *pCapInfo)
736     ApiMac_assocStatus_t status;
738     /* Make sure the device is in our PAN */
739     if(pDevInfo->panID == devicePanId)
740     {
741         /* Update the user that a device is joining */
742         status = Csf_deviceUpdate(pDevInfo, pCapInfo);
743         if(status==ApiMac_assocStatus_success)
744         {
745 #ifdef FEATURE_MAC_SECURITY
746             /* Add device to security device table */
747             Cllc_addSecDevice(pDevInfo->panID,
748                               pDevInfo->shortAddress,
749                               &pDevInfo->extAddress, 0);
750 #endif /* FEATURE_MAC_SECURITY */
752             Util_setEvent(&Collector_events, COLLECTOR_CONFIG_EVT);
753         }
754     }
755     else
756     {
757         status = ApiMac_assocStatus_panAccessDenied;
758     }
759     return (status);
762 /*!
763  * @brief     CLLC State Changed callback.
764  *
765  * @param     state - CLLC new state
766  */
767 static void cllcStateChangedCB(Cllc_states_t state)
769     /* Save the state */
770     cllcState = state;
772     /* Notify the user interface */
773     Csf_stateChangeUpdate(cllcState);
776 /*!
777  * @brief      MAC Data Confirm callback.
778  *
779  * @param      pDataCnf - pointer to the data confirm information
780  */
781 static void dataCnfCB(ApiMac_mcpsDataCnf_t *pDataCnf)
783     /* Record statistics */
784     if(pDataCnf->status == ApiMac_status_channelAccessFailure)
785     {
786         Collector_statistics.channelAccessFailures++;
787     }
788     else if(pDataCnf->status == ApiMac_status_noAck)
789     {
790         Collector_statistics.ackFailures++;
791     }
792     else if(pDataCnf->status == ApiMac_status_transactionExpired)
793     {
794         Collector_statistics.txTransactionExpired++;
795     }
796     else if(pDataCnf->status == ApiMac_status_transactionOverflow)
797     {
798         Collector_statistics.txTransactionOverflow++;
799     }
800     else if(pDataCnf->status == ApiMac_status_success)
801     {
802         Csf_updateFrameCounter(NULL, pDataCnf->frameCntr);
803     }
804     else if(pDataCnf->status != ApiMac_status_success)
805     {
806         Collector_statistics.otherTxFailures++;
807     }
809     /* Make sure the message came from the app */
810     if(pDataCnf->msduHandle & APP_MARKER_MSDU_HANDLE)
811     {
812         /* What message type was the original request? */
813         if(pDataCnf->msduHandle & APP_CONFIG_MSDU_HANDLE)
814         {
815             /* Config Request */
816             Cllc_associated_devices_t *pDev;
817             pDev = findDeviceStatusBit(ASSOC_CONFIG_MASK, ASSOC_CONFIG_SENT);
818             if(pDev != NULL)
819             {
820                 if(pDataCnf->status != ApiMac_status_success)
821                 {
822                     /* Try to send again */
823                     pDev->status &= ~ASSOC_CONFIG_SENT;
824                     Csf_setConfigClock(CONFIG_DELAY);
825                 }
826                 else
827                 {
828                     pDev->status |= ASSOC_CONFIG_SENT;
829                     pDev->status |= ASSOC_CONFIG_RSP;
830                     pDev->status |= CLLC_ASSOC_STATUS_ALIVE;
831                     Csf_setConfigClock(CONFIG_RESPONSE_DELAY);
832                 }
833             }
835             /* Update stats */
836             if(pDataCnf->status == ApiMac_status_success)
837             {
838                 Collector_statistics.configReqRequestSent++;
839             }
840         }
841         else
842         {
843             /* Tracking Request */
844             Cllc_associated_devices_t *pDev;
845             pDev = findDeviceStatusBit(ASSOC_TRACKING_SENT,
846                                        ASSOC_TRACKING_SENT);
847             if(pDev != NULL)
848             {
849                 if(pDataCnf->status == ApiMac_status_success)
850                 {
851                     /* Make sure the retry is clear */
852                     pDev->status &= ~ASSOC_TRACKING_RETRY;
853                 }
854                 else
855                 {
856                     if(pDev->status & ASSOC_TRACKING_RETRY)
857                     {
858                         /* We already tried to resend */
859                         pDev->status &= ~ASSOC_TRACKING_RETRY;
860                         pDev->status |= ASSOC_TRACKING_ERROR;
861                     }
862                     else
863                     {
864                         /* Go ahead and retry */
865                         pDev->status |= ASSOC_TRACKING_RETRY;
866                     }
868                     pDev->status &= ~ASSOC_TRACKING_SENT;
870                     /* Try to send again or another */
871                     Csf_setTrackingClock(TRACKING_CNF_DELAY_TIME);
872                 }
873             }
875             /* Update stats */
876             if(pDataCnf->status == ApiMac_status_success)
877             {
878                 Collector_statistics.trackingReqRequestSent++;
879             }
880         }
881     }
884 /*!
885  * @brief      MAC Data Indication callback.
886  *
887  * @param      pDataInd - pointer to the data indication information
888  */
889 static void dataIndCB(ApiMac_mcpsDataInd_t *pDataInd)
891     if((pDataInd != NULL) && (pDataInd->msdu.p != NULL)
892        && (pDataInd->msdu.len > 0))
893     {
894         Smsgs_cmdIds_t cmdId = (Smsgs_cmdIds_t)*(pDataInd->msdu.p);
896 #ifdef FEATURE_MAC_SECURITY
897         if(Cllc_securityCheck(&(pDataInd->sec)) == false)
898         {
899             /* Reject the message */
900             return;
901         }
902 #endif /* FEATURE_MAC_SECURITY */
904         if(pDataInd->srcAddr.addrMode == ApiMac_addrType_extended)
905         {
906             uint16_t shortAddr = Csf_getDeviceShort(
907                             &pDataInd->srcAddr.addr.extAddr);
908             if(shortAddr != CSF_INVALID_SHORT_ADDR)
909             {
910                 /* Switch to the short address for internal tracking */
911                 pDataInd->srcAddr.addrMode = ApiMac_addrType_short;
912                 pDataInd->srcAddr.addr.shortAddr = shortAddr;
913             }
914             else
915             {
916                 /* Can't accept the message - ignore it */
917                 return;
918             }
919         }
921         switch(cmdId)
922         {
923             case Smsgs_cmdIds_configRsp:
924                 processConfigResponse(pDataInd);
925                 break;
927             case Smsgs_cmdIds_trackingRsp:
928                 processTrackingResponse(pDataInd);
929                 break;
931             case Smsgs_cmdIds_toggleLedRsp:
932                 processToggleLedResponse(pDataInd);
933                 break;
935             case Smsgs_cmdIds_sensorData:
936                 processSensorData(pDataInd);
937                 break;
939             case Smsgs_cmdIds_rampdata:
940                 Collector_statistics.sensorMessagesReceived++;
941                 break;
943             case Smsgs_cmdIds_oad:
944                 processOadData(pDataInd);
945                 break;
947             default:
948                 /* Should not receive other messages */
949                 break;
950         }
951     }
954 /*!
955  * @brief      Process the start event
956  */
957 static void processStartEvent(void)
959     Llc_netInfo_t netInfo;
960     uint32_t frameCounter = 0;
962     Csf_getFrameCounter(NULL, &frameCounter);
963     /* See if there is existing network information */
964     if(Csf_getNetworkInformation(&netInfo))
965     {
966         Llc_deviceListItem_t *pDevList = NULL;
967         uint16_t numDevices = 0;
969 #ifdef FEATURE_MAC_SECURITY
970         /* Initialize the MAC Security */
971         Cllc_securityInit(frameCounter);
972 #endif /* FEATURE_MAC_SECURITY */
974         numDevices = Csf_getNumDeviceListEntries();
975         if (numDevices > 0)
976         {
977             /* Allocate enough memory for all know devices */
978             pDevList = (Llc_deviceListItem_t *)Csf_malloc(
979                             sizeof(Llc_deviceListItem_t) * numDevices);
980             if(pDevList)
981             {
982                 uint8_t i = 0;
984                 /* Use a temp pointer to cycle through the list */
985                 Llc_deviceListItem_t *pItem = pDevList;
986                 for(i = 0; i < numDevices; i++, pItem++)
987                 {
988                     Csf_getDeviceItem(i, pItem);
990 #ifdef FEATURE_MAC_SECURITY
991                     /* Add device to security device table */
992                     Cllc_addSecDevice(pItem->devInfo.panID,
993                                       pItem->devInfo.shortAddress,
994                                       &pItem->devInfo.extAddress,
995                                       pItem->rxFrameCounter);
996 #endif /* FEATURE_MAC_SECURITY */
997                 }
998             }
999             else
1000             {
1001                 numDevices = 0;
1002             }
1003         }
1005         /* Restore with the network and device information */
1006         Cllc_restoreNetwork(&netInfo, (uint8_t)numDevices, pDevList);
1008         if (pDevList)
1009         {
1010             Csf_free(pDevList);
1011         }
1013         restarted = true;
1014     }
1015     else
1016     {
1017         restarted = false;
1019 #ifdef FEATURE_MAC_SECURITY
1020         /* Initialize the MAC Security */
1021         Cllc_securityInit(frameCounter);
1022 #endif /* FEATURE_MAC_SECURITY */
1024         /* Start a new netork */
1025         Cllc_startNetwork();
1026     }
1029 /*!
1030  * @brief      Process the Config Response message.
1031  *
1032  * @param      pDataInd - pointer to the data indication information
1033  */
1034 static void processConfigResponse(ApiMac_mcpsDataInd_t *pDataInd)
1036     /* Make sure the message is the correct size */
1037     if(pDataInd->msdu.len == SMSGS_CONFIG_RESPONSE_MSG_LENGTH)
1038     {
1039         Cllc_associated_devices_t *pDev;
1040         Smsgs_configRspMsg_t configRsp;
1041         uint8_t *pBuf = pDataInd->msdu.p;
1043         /* Parse the message */
1044         configRsp.cmdId = (Smsgs_cmdIds_t)*pBuf++;
1046         configRsp.status = (Smsgs_statusValues_t)Util_buildUint16(pBuf[0],
1047                                                                   pBuf[1]);
1048         pBuf += 2;
1050         configRsp.frameControl = Util_buildUint16(pBuf[0], pBuf[1]);
1051         pBuf += 2;
1053         configRsp.reportingInterval = Util_buildUint32(pBuf[0], pBuf[1],
1054                                                        pBuf[2],
1055                                                        pBuf[3]);
1056         pBuf += 4;
1058         configRsp.pollingInterval = Util_buildUint32(pBuf[0], pBuf[1], pBuf[2],
1059                                                      pBuf[3]);
1061         pDev = findDevice(&pDataInd->srcAddr);
1062         if(pDev != NULL)
1063         {
1064             /* Clear the sent flag and set the response flag */
1065             pDev->status &= ~ASSOC_CONFIG_SENT;
1066             pDev->status |= ASSOC_CONFIG_RSP;
1067         }
1069         /* Report the config response */
1070         Csf_deviceConfigUpdate(&pDataInd->srcAddr, pDataInd->rssi,
1071                                &configRsp);
1073         Util_setEvent(&Collector_events, COLLECTOR_CONFIG_EVT);
1075         Collector_statistics.configResponseReceived++;
1076     }
1079 /*!
1080  * @brief      Process the Tracking Response message.
1081  *
1082  * @param      pDataInd - pointer to the data indication information
1083  */
1084 static void processTrackingResponse(ApiMac_mcpsDataInd_t *pDataInd)
1086     /* Make sure the message is the correct size */
1087     if(pDataInd->msdu.len == SMSGS_TRACKING_RESPONSE_MSG_LENGTH)
1088     {
1089         Cllc_associated_devices_t *pDev;
1091         pDev = findDevice(&pDataInd->srcAddr);
1092         if(pDev != NULL)
1093         {
1094             if(pDev->status & ASSOC_TRACKING_SENT)
1095             {
1096                 pDev->status &= ~ASSOC_TRACKING_SENT;
1097                 pDev->status |= ASSOC_TRACKING_RSP;
1099                 /* Setup for next tracking */
1100                 Csf_setTrackingClock( TRACKING_DELAY_TIME);
1102                 /* Retry config request */
1103                 processConfigRetry();
1104             }
1105         }
1107         /* Update stats */
1108         Collector_statistics.trackingResponseReceived++;
1109     }
1112 /*!
1113  * @brief      Process the Toggle Led Response message.
1114  *
1115  * @param      pDataInd - pointer to the data indication information
1116  */
1117 static void processToggleLedResponse(ApiMac_mcpsDataInd_t *pDataInd)
1119     /* Make sure the message is the correct size */
1120     if(pDataInd->msdu.len == SMSGS_TOGGLE_LED_RESPONSE_MSG_LEN)
1121     {
1122         bool ledState;
1123         uint8_t *pBuf = pDataInd->msdu.p;
1125         /* Skip past the command ID */
1126         pBuf++;
1128         ledState = (bool)*pBuf;
1130         /* Notify the user */
1131         Csf_toggleResponseReceived(&pDataInd->srcAddr, ledState);
1132     }
1135 /*!
1136  * @brief      Process the Sensor Data message.
1137  *
1138  * @param      pDataInd - pointer to the data indication information
1139  */
1140 static void processSensorData(ApiMac_mcpsDataInd_t *pDataInd)
1142     Smsgs_sensorMsg_t sensorData;
1143     uint8_t *pBuf = pDataInd->msdu.p;
1145     memset(&sensorData, 0, sizeof(Smsgs_sensorMsg_t));
1147     /* Parse the message */
1148     sensorData.cmdId = (Smsgs_cmdIds_t)*pBuf++;
1150     memcpy(sensorData.extAddress, pBuf, SMGS_SENSOR_EXTADDR_LEN);
1151     pBuf += SMGS_SENSOR_EXTADDR_LEN;
1153     sensorData.frameControl = Util_buildUint16(pBuf[0], pBuf[1]);
1154     pBuf += 2;
1156     if(sensorData.frameControl & Smsgs_dataFields_tempSensor)
1157     {
1158         sensorData.tempSensor.ambienceTemp = Util_buildUint16(pBuf[0], pBuf[1]);
1159         pBuf += 2;
1160         sensorData.tempSensor.objectTemp = Util_buildUint16(pBuf[0], pBuf[1]);
1161         pBuf += 2;
1162     }
1164     if(sensorData.frameControl & Smsgs_dataFields_lightSensor)
1165     {
1166         sensorData.lightSensor.rawData = Util_buildUint16(pBuf[0], pBuf[1]);
1167         pBuf += 2;
1168     }
1170     if(sensorData.frameControl & Smsgs_dataFields_humiditySensor)
1171     {
1172         sensorData.humiditySensor.temp = Util_buildUint16(pBuf[0], pBuf[1]);
1173         pBuf += 2;
1174         sensorData.humiditySensor.humidity = Util_buildUint16(pBuf[0], pBuf[1]);
1175         pBuf += 2;
1176     }
1178     if(sensorData.frameControl & Smsgs_dataFields_msgStats)
1179     {
1180         sensorData.msgStats.joinAttempts = Util_buildUint16(pBuf[0], pBuf[1]);
1181         pBuf += 2;
1182         sensorData.msgStats.joinFails = Util_buildUint16(pBuf[0], pBuf[1]);
1183         pBuf += 2;
1184         sensorData.msgStats.msgsAttempted = Util_buildUint16(pBuf[0], pBuf[1]);
1185         pBuf += 2;
1186         sensorData.msgStats.msgsSent = Util_buildUint16(pBuf[0], pBuf[1]);
1187         pBuf += 2;
1188         sensorData.msgStats.trackingRequests = Util_buildUint16(pBuf[0],
1189                                                                 pBuf[1]);
1190         pBuf += 2;
1191         sensorData.msgStats.trackingResponseAttempts = Util_buildUint16(
1192                         pBuf[0],
1193                         pBuf[1]);
1194         pBuf += 2;
1195         sensorData.msgStats.trackingResponseSent = Util_buildUint16(pBuf[0],
1196                                                                     pBuf[1]);
1197         pBuf += 2;
1198         sensorData.msgStats.configRequests = Util_buildUint16(pBuf[0],
1199                                                               pBuf[1]);
1200         pBuf += 2;
1201         sensorData.msgStats.configResponseAttempts = Util_buildUint16(
1202                         pBuf[0],
1203                         pBuf[1]);
1204         pBuf += 2;
1205         sensorData.msgStats.configResponseSent = Util_buildUint16(pBuf[0],
1206                                                                   pBuf[1]);
1207         pBuf += 2;
1208         sensorData.msgStats.channelAccessFailures = Util_buildUint16(pBuf[0],
1209                                                                      pBuf[1]);
1210         pBuf += 2;
1211         sensorData.msgStats.macAckFailures = Util_buildUint16(pBuf[0], pBuf[1]);
1212         pBuf += 2;
1213         sensorData.msgStats.otherDataRequestFailures = Util_buildUint16(
1214                         pBuf[0],
1215                         pBuf[1]);
1216         pBuf += 2;
1217         sensorData.msgStats.syncLossIndications = Util_buildUint16(pBuf[0],
1218                                                                    pBuf[1]);
1219         pBuf += 2;
1220         sensorData.msgStats.rxDecryptFailures = Util_buildUint16(pBuf[0],
1221                                                                  pBuf[1]);
1222         pBuf += 2;
1223         sensorData.msgStats.txEncryptFailures = Util_buildUint16(pBuf[0],
1224                                                                  pBuf[1]);
1225         pBuf += 2;
1226         sensorData.msgStats.resetCount = Util_buildUint16(pBuf[0],
1227                                                           pBuf[1]);
1228         pBuf += 2;
1229         sensorData.msgStats.lastResetReason = Util_buildUint16(pBuf[0],
1230                                                                pBuf[1]);
1231         pBuf += 2;
1232         sensorData.msgStats.joinTime = Util_buildUint16(pBuf[0],
1233                                                         pBuf[1]);
1234         pBuf += 2;
1235         sensorData.msgStats.interimDelay = Util_buildUint16(pBuf[0],
1236                                                             pBuf[1]);
1237         pBuf += 2;
1238     }
1240     if(sensorData.frameControl & Smsgs_dataFields_configSettings)
1241     {
1242         sensorData.configSettings.reportingInterval = Util_buildUint32(pBuf[0],
1243                                                                        pBuf[1],
1244                                                                        pBuf[2],
1245                                                                        pBuf[3]);
1246         pBuf += 4;
1247         sensorData.configSettings.pollingInterval = Util_buildUint32(pBuf[0],
1248                                                                      pBuf[1],
1249                                                                      pBuf[2],
1250                                                                      pBuf[3]);
1251         pBuf += 4;
1252     }
1254     if(sensorData.frameControl & Smsgs_dataFields_pressureSensor)
1255     {
1256         sensorData.pressureSensor.pressureValue = Util_buildUint32(pBuf[0],
1257                                                                     pBuf[1],
1258                                                                     pBuf[2],
1259                                                                     pBuf[3]);
1260         pBuf += 4;
1261         sensorData.pressureSensor.tempValue =  Util_buildUint32(pBuf[0],
1262                                                                 pBuf[1],
1263                                                                 pBuf[2],
1264                                                                 pBuf[3]);
1265         pBuf += 4;
1266     }
1268     if(sensorData.frameControl & Smsgs_dataFields_motionSensor)
1269     {
1270       sensorData.motionSensor.isMotion = *pBuf++;
1271     }
1273     if(sensorData.frameControl & Smsgs_dataFields_batterySensor)
1274     {
1276       sensorData.batterySensor.voltageValue = Util_buildUint32(pBuf[0],
1277                                                                      pBuf[1],
1278                                                                      pBuf[2],
1279                                                                      pBuf[3]);
1280       pBuf +=4;
1281     }
1283     if(sensorData.frameControl & Smsgs_dataFields_hallEffectSensor)
1284     {
1285       sensorData.hallEffectSensor.isOpen = *pBuf++;
1286       sensorData.hallEffectSensor.isTampered = *pBuf++;
1287     }
1289     if(sensorData.frameControl & Smsgs_dataFields_fanSensor)
1290     {
1291       sensorData.fanSensor.fanSpeed = *pBuf++;
1292     }
1294     if(sensorData.frameControl & Smsgs_dataFields_doorLockSensor)
1295     {
1296       sensorData.doorLockSensor.isLocked = *pBuf++;
1297     }
1299     Collector_statistics.sensorMessagesReceived++;
1301     /* Report the sensor data */
1302     Csf_deviceSensorDataUpdate(&pDataInd->srcAddr, pDataInd->rssi,
1303                                &sensorData);
1305     processDataRetry(&(pDataInd->srcAddr));
1308 /*!
1309  * @brief      Process the OAD Data message.
1310  *
1311  * @param      pDataInd - pointer to the data indication information
1312  */
1313 static void processOadData(ApiMac_mcpsDataInd_t *pDataInd)
1315     //Index past the Smsgs_cmdId
1316     OADProtocol_ParseIncoming((void*) &(pDataInd->srcAddr), &(pDataInd->msdu.p[1]));
1318     Collector_statistics.sensorMessagesReceived++;
1321 /*!
1322  * @brief      Find the associated device table entry matching pAddr.
1323  *
1324  * @param      pAddr - pointer to device's address
1325  *
1326  * @return     pointer to the associated device table entry,
1327  *             NULL if not found.
1328  */
1329 static Cllc_associated_devices_t *findDevice(ApiMac_sAddr_t *pAddr)
1331     int x;
1332     Cllc_associated_devices_t *pItem = NULL;
1334     /* Check for invalid parameters */
1335     if((pAddr == NULL) || (pAddr->addrMode == ApiMac_addrType_none))
1336     {
1337         return (NULL);
1338     }
1340     for(x = 0; x < CONFIG_MAX_DEVICES; x++)
1341     {
1342         /* Make sure the entry is valid. */
1343         if(Cllc_associatedDevList[x].shortAddr != CSF_INVALID_SHORT_ADDR)
1344         {
1345             if(pAddr->addrMode == ApiMac_addrType_short)
1346             {
1347                 if(pAddr->addr.shortAddr == Cllc_associatedDevList[x].shortAddr)
1348                 {
1349                     pItem = &Cllc_associatedDevList[x];
1350                     break;
1351                 }
1352             }
1353         }
1354     }
1356     return (pItem);
1359 /*!
1360  * @brief      Find the associated device table entry matching status bit.
1361  *
1362  * @param      statusBit - what status bit to find
1363  *
1364  * @return     pointer to the associated device table entry,
1365  *             NULL if not found.
1366  */
1367 static Cllc_associated_devices_t *findDeviceStatusBit(uint16_t mask, uint16_t statusBit)
1369     int x;
1370     Cllc_associated_devices_t *pItem = NULL;
1372     for(x = 0; x < CONFIG_MAX_DEVICES; x++)
1373     {
1374         /* Make sure the entry is valid. */
1375         if(Cllc_associatedDevList[x].shortAddr != CSF_INVALID_SHORT_ADDR)
1376         {
1377             if((Cllc_associatedDevList[x].status & mask) == statusBit)
1378             {
1379                 pItem = &Cllc_associatedDevList[x];
1380                 break;
1381             }
1382         }
1383     }
1385     return (pItem);
1388 /*!
1389  * @brief      Get the next MSDU Handle
1390  *             <BR>
1391  *             The MSDU handle has 3 parts:<BR>
1392  *             - The MSBit(7), when set means the the application sent the message
1393  *             - Bit 6, when set means that the app message is a config request
1394  *             - Bits 0-5, used as a message counter that rolls over.
1395  *
1396  * @param      msgType - message command id needed
1397  *
1398  * @return     msdu Handle
1399  */
1400 static uint8_t getMsduHandle(Smsgs_cmdIds_t msgType)
1402     uint8_t msduHandle = deviceTxMsduHandle;
1404     /* Increment for the next msdu handle, or roll over */
1405     if(deviceTxMsduHandle >= MSDU_HANDLE_MAX)
1406     {
1407         deviceTxMsduHandle = 0;
1408     }
1409     else
1410     {
1411         deviceTxMsduHandle++;
1412     }
1414     /* Add the App specific bit */
1415     msduHandle |= APP_MARKER_MSDU_HANDLE;
1417     /* Add the message type bit */
1418     if(msgType == Smsgs_cmdIds_configReq)
1419     {
1420         msduHandle |= APP_CONFIG_MSDU_HANDLE;
1421     }
1423     return (msduHandle);
1426 /*!
1427  * @brief      Send MAC data request
1428  *
1429  * @param      type - message type
1430  * @param      dstShortAddr - destination short address
1431  * @param      rxOnIdle - true if not a sleepy device
1432  * @param      len - length of payload
1433  * @param      pData - pointer to the buffer
1434  *
1435  * @return  true if sent, false if not
1436  */
1437 static bool sendMsg(Smsgs_cmdIds_t type, uint16_t dstShortAddr, bool rxOnIdle,
1438                     uint16_t len,
1439                     uint8_t *pData)
1441     ApiMac_mcpsDataReq_t dataReq;
1443     /* Fill the data request field */
1444     memset(&dataReq, 0, sizeof(ApiMac_mcpsDataReq_t));
1446     dataReq.dstAddr.addrMode = ApiMac_addrType_short;
1447     dataReq.dstAddr.addr.shortAddr = dstShortAddr;
1448     dataReq.srcAddrMode = ApiMac_addrType_short;
1450     if(fhEnabled && !LRM_MODE)
1451     {
1452         Llc_deviceListItem_t item;
1454         if(Csf_getDevice(&(dataReq.dstAddr), &item))
1455         {
1456             /* Switch to the long address */
1457             dataReq.dstAddr.addrMode = ApiMac_addrType_extended;
1458             memcpy(&dataReq.dstAddr.addr.extAddr, &item.devInfo.extAddress,
1459                    (APIMAC_SADDR_EXT_LEN));
1460             dataReq.srcAddrMode = ApiMac_addrType_extended;
1461         }
1462         else
1463         {
1464             /* Can't send the message */
1465             return (false);
1466         }
1467     }
1469     dataReq.dstPanId = devicePanId;
1471     dataReq.msduHandle = getMsduHandle(type);
1473     dataReq.txOptions.ack = true;
1474     if(rxOnIdle == false)
1475     {
1476         dataReq.txOptions.indirect = true;
1477     }
1479     dataReq.msdu.len = len;
1480     dataReq.msdu.p = pData;
1482 #ifdef FEATURE_MAC_SECURITY
1483     /* Fill in the appropriate security fields */
1484     Cllc_securityFill(&dataReq.sec);
1485 #endif /* FEATURE_MAC_SECURITY */
1487     /* Send the message */
1488     if(ApiMac_mcpsDataReq(&dataReq) != ApiMac_status_success)
1489     {
1490         /*  Transaction overflow occurred */
1491         return (false);
1492     }
1493     else
1494     {
1495         return (true);
1496     }
1499 /*!
1500  * @brief      Generate Config Requests for all associate devices
1501  *             that need one.
1502  */
1503 static void generateConfigRequests(void)
1505     int x;
1507     if(CERTIFICATION_TEST_MODE)
1508     {
1509         /* In Certification mode only back to back uplink
1510          * data traffic shall be supported*/
1511         return;
1512     }
1514     /* Clear any timed out transactions */
1515     for(x = 0; x < CONFIG_MAX_DEVICES; x++)
1516     {
1517         if((Cllc_associatedDevList[x].shortAddr != CSF_INVALID_SHORT_ADDR)
1518            && (Cllc_associatedDevList[x].status & CLLC_ASSOC_STATUS_ALIVE))
1519         {
1520             if((Cllc_associatedDevList[x].status &
1521                (ASSOC_CONFIG_SENT | ASSOC_CONFIG_RSP))
1522                == (ASSOC_CONFIG_SENT | ASSOC_CONFIG_RSP))
1523             {
1524                 Cllc_associatedDevList[x].status &= ~(ASSOC_CONFIG_SENT
1525                                 | ASSOC_CONFIG_RSP);
1526             }
1527         }
1528     }
1530     /* Make sure we are only sending one config request at a time */
1531     if(findDeviceStatusBit(ASSOC_CONFIG_MASK, ASSOC_CONFIG_SENT) == NULL)
1532     {
1533         /* Run through all of the devices */
1534         for(x = 0; x < CONFIG_MAX_DEVICES; x++)
1535         {
1536             /* Make sure the entry is valid. */
1537             if((Cllc_associatedDevList[x].shortAddr != CSF_INVALID_SHORT_ADDR)
1538                && (Cllc_associatedDevList[x].status & CLLC_ASSOC_STATUS_ALIVE))
1539             {
1540                 uint16_t status = Cllc_associatedDevList[x].status;
1542                 /*
1543                  Has the device been sent or already received a config request?
1544                  */
1545                 if(((status & (ASSOC_CONFIG_SENT | ASSOC_CONFIG_RSP)) == 0))
1546                 {
1547                     ApiMac_sAddr_t dstAddr;
1548                     Collector_status_t stat;
1550                     /* Set up the destination address */
1551                     dstAddr.addrMode = ApiMac_addrType_short;
1552                     dstAddr.addr.shortAddr =
1553                         Cllc_associatedDevList[x].shortAddr;
1555                     /* Send the Config Request */
1556                     stat = Collector_sendConfigRequest(
1557                                     &dstAddr, (CONFIG_FRAME_CONTROL),
1558                                     (CONFIG_REPORTING_INTERVAL),
1559                                     (CONFIG_POLLING_INTERVAL));
1560                     if(stat == Collector_status_success)
1561                     {
1562                         /*
1563                          Mark as the message has been sent and expecting a response
1564                          */
1565                         Cllc_associatedDevList[x].status |= ASSOC_CONFIG_SENT;
1566                         Cllc_associatedDevList[x].status &= ~ASSOC_CONFIG_RSP;
1567                     }
1569                     /* Only do one at a time */
1570                     break;
1571                 }
1572             }
1573         }
1574     }
1578 /*!
1579  * @brief      Generate Config Requests for all associate devices
1580  *             that need one.
1581  */
1582 static void generateTrackingRequests(void)
1584     int x;
1586     /* Run through all of the devices, looking for previous activity */
1587     for(x = 0; x < CONFIG_MAX_DEVICES; x++)
1588     {
1589         if(CERTIFICATION_TEST_MODE)
1590         {
1591             /* In Certification mode only back to back uplink
1592              * data traffic shall be supported*/
1593             return;
1594         }
1595         /* Make sure the entry is valid. */
1596         if((Cllc_associatedDevList[x].shortAddr != CSF_INVALID_SHORT_ADDR)
1597              && (Cllc_associatedDevList[x].status & CLLC_ASSOC_STATUS_ALIVE))
1598         {
1599             uint16_t status = Cllc_associatedDevList[x].status;
1601             /*
1602              Has the device been sent a tracking request or received a
1603              tracking response?
1604              */
1605             if(status & ASSOC_TRACKING_RETRY)
1606             {
1607                 sendTrackingRequest(&Cllc_associatedDevList[x]);
1608                 return;
1609             }
1610             else if((status & (ASSOC_TRACKING_SENT | ASSOC_TRACKING_RSP
1611                                | ASSOC_TRACKING_ERROR)))
1612             {
1613                 Cllc_associated_devices_t *pDev = NULL;
1614                 int y;
1616                 if(status & (ASSOC_TRACKING_SENT | ASSOC_TRACKING_ERROR))
1617                 {
1618                     ApiMac_deviceDescriptor_t devInfo;
1619                     Llc_deviceListItem_t item;
1620                     ApiMac_sAddr_t devAddr;
1622                     /*
1623                      Timeout occured, notify the user that the tracking
1624                      failed.
1625                      */
1626                     memset(&devInfo, 0, sizeof(ApiMac_deviceDescriptor_t));
1628                     devAddr.addrMode = ApiMac_addrType_short;
1629                     devAddr.addr.shortAddr =
1630                         Cllc_associatedDevList[x].shortAddr;
1632                     if(Csf_getDevice(&devAddr, &item))
1633                     {
1634                         memcpy(&devInfo.extAddress,
1635                                &item.devInfo.extAddress,
1636                                sizeof(ApiMac_sAddrExt_t));
1637                     }
1638                     devInfo.shortAddress = Cllc_associatedDevList[x].shortAddr;
1639                     devInfo.panID = devicePanId;
1640                     Csf_deviceNotActiveUpdate(&devInfo,
1641                         ((status & ASSOC_TRACKING_SENT) ? true : false));
1643                     /* Not responding, so remove the alive marker */
1644                     Cllc_associatedDevList[x].status
1645                             &= ~(CLLC_ASSOC_STATUS_ALIVE
1646                                 | ASSOC_CONFIG_SENT | ASSOC_CONFIG_RSP);
1647                 }
1649                 /* Clear the tracking bits */
1650                 Cllc_associatedDevList[x].status  &= ~(ASSOC_TRACKING_ERROR
1651                                 | ASSOC_TRACKING_SENT | ASSOC_TRACKING_RSP);
1653                 /* Find the next valid device */
1654                 y = x;
1655                 while(pDev == NULL)
1656                 {
1657                     /* Check for rollover */
1658                     if(y == (CONFIG_MAX_DEVICES-1))
1659                     {
1660                         /* Move to the beginning */
1661                         y = 0;
1662                     }
1663                     else
1664                     {
1665                         /* Move the the next device */
1666                         y++;
1667                     }
1669                     if(y == x)
1670                     {
1671                         /* We've come back around */
1672                         break;
1673                     }
1675                     /*
1676                      Is the entry valid and active */
1677                     if((Cllc_associatedDevList[y].shortAddr
1678                                     != CSF_INVALID_SHORT_ADDR)
1679                          && (Cllc_associatedDevList[y].status
1680                                    & CLLC_ASSOC_STATUS_ALIVE))
1681                     {
1682                         pDev = &Cllc_associatedDevList[y];
1683                     }
1684                 }
1686                 if(pDev == NULL)
1687                 {
1688                     /* Another device wasn't found, send to same device */
1689                     pDev = &Cllc_associatedDevList[x];
1690                 }
1692                 sendTrackingRequest(pDev);
1694                 /* Only do one at a time */
1695                 return;
1696             }
1697         }
1698     }
1700     /* If no activity found, find the first active device */
1701     for(x = 0; x < CONFIG_MAX_DEVICES; x++)
1702     {
1703         /* Make sure the entry is valid. */
1704         if((Cllc_associatedDevList[x].shortAddr != CSF_INVALID_SHORT_ADDR)
1705               && (Cllc_associatedDevList[x].status & CLLC_ASSOC_STATUS_ALIVE))
1706         {
1707             sendTrackingRequest(&Cllc_associatedDevList[x]);
1708             break;
1709         }
1710     }
1712     if(x == CONFIG_MAX_DEVICES)
1713     {
1714         /* No device found, Setup delay for next tracking message */
1715         Csf_setTrackingClock(TRACKING_DELAY_TIME);
1716     }
1719 /*!
1720  * @brief      Generate Tracking Requests for a device
1721  *
1722  * @param      pDev - pointer to the device's associate device table entry
1723  */
1724 static void sendTrackingRequest(Cllc_associated_devices_t *pDev)
1726     uint8_t cmdId = Smsgs_cmdIds_trackingReq;
1728     /* Send the Tracking Request */
1729    if((sendMsg(Smsgs_cmdIds_trackingReq, pDev->shortAddr,
1730             pDev->capInfo.rxOnWhenIdle,
1731             (SMSGS_TRACKING_REQUEST_MSG_LENGTH),
1732             &cmdId)) == true)
1733     {
1734         /* Mark as Tracking Request sent */
1735         pDev->status |= ASSOC_TRACKING_SENT;
1737         /* Setup Timeout for response */
1738         Csf_setTrackingClock(TRACKING_TIMEOUT_TIME);
1740         /* Update stats */
1741         Collector_statistics.trackingRequestAttempts++;
1742     }
1743     else
1744     {
1745         ApiMac_sAddr_t devAddr;
1746         devAddr.addrMode = ApiMac_addrType_short;
1747         devAddr.addr.shortAddr = pDev->shortAddr;
1748         processDataRetry(&devAddr);
1749     }
1752 /*!
1753  * @brief      Process the MAC Comm Status Indication Callback
1754  *
1755  * @param      pCommStatusInd - Comm Status indication
1756  */
1757 static void commStatusIndCB(ApiMac_mlmeCommStatusInd_t *pCommStatusInd)
1759     if(pCommStatusInd->reason == ApiMac_commStatusReason_assocRsp)
1760     {
1761         if(pCommStatusInd->status != ApiMac_status_success)
1762         {
1763             Cllc_associated_devices_t *pDev;
1765             pDev = findDevice(&pCommStatusInd->dstAddr);
1766             if(pDev)
1767             {
1768                 /* Mark as inactive and clear config and tracking states */
1769                 pDev->status = 0;
1770             }
1771         }
1772     }
1775 /*!
1776  * @brief      Process the MAC Poll Indication Callback
1777  *
1778  * @param      pPollInd - poll indication
1779  */
1780 static void pollIndCB(ApiMac_mlmePollInd_t *pPollInd)
1782     ApiMac_sAddr_t addr;
1784     addr.addrMode = ApiMac_addrType_short;
1785     if (pPollInd->srcAddr.addrMode == ApiMac_addrType_short)
1786     {
1787         addr.addr.shortAddr = pPollInd->srcAddr.addr.shortAddr;
1788     }
1789     else
1790     {
1791         addr.addr.shortAddr = Csf_getDeviceShort(
1792                         &pPollInd->srcAddr.addr.extAddr);
1793     }
1795     processDataRetry(&addr);
1798 /*!
1799  * @brief      Process the disassoc Indication Callback
1800  *
1801  * @param      disassocIndCB - disassoc indication
1802  */
1803 static void disassocIndCB(ApiMac_mlmeDisassociateInd_t *pDisassocInd)
1805     ApiMac_sAddr_t addr;
1807     addr.addrMode = ApiMac_addrType_extended;
1808     memcpy(&addr.addr.extAddr, &pDisassocInd->deviceAddress,
1809                    (APIMAC_SADDR_EXT_LEN));
1811     Csf_deviceDisassocUpdate(&addr);
1814 /*!
1815  * @brief      Process the disassoc cofirmation Callback
1816  *
1817  * @param      disassocCnfCB - disassoc cofirmation
1818  */
1819 static void disassocCnfCB(ApiMac_mlmeDisassociateCnf_t *pDisassocCnf)
1821     Csf_deviceDisassocUpdate(&pDisassocCnf->deviceAddress);
1824 /*!
1825  * @brief      Process retries for config and tracking messages
1826  *
1827  * @param      addr - MAC address structure */
1828 static void processDataRetry(ApiMac_sAddr_t *pAddr)
1830     if(pAddr->addr.shortAddr != CSF_INVALID_SHORT_ADDR)
1831     {
1832         Cllc_associated_devices_t *pItem;
1833         pItem = findDevice(pAddr);
1834         if(pItem)
1835         {
1836             /* Set device status to alive */
1837             pItem->status |= CLLC_ASSOC_STATUS_ALIVE;
1839             /* Check to see if we need to send it a config */
1840             if((pItem->status & (ASSOC_CONFIG_RSP | ASSOC_CONFIG_SENT)) == 0)
1841             {
1842                 processConfigRetry();
1843             }
1844             /* Check to see if we need to send it a tracking message */
1845             if((pItem->status & (ASSOC_TRACKING_SENT| ASSOC_TRACKING_RETRY)) == 0)
1846             {
1847                 /* Make sure we aren't already doing a tracking message */
1848                 if(((Collector_events & COLLECTOR_TRACKING_TIMEOUT_EVT) == 0)
1849                     && (Csf_isTrackingTimerActive() == false)
1850                     && (findDeviceStatusBit(ASSOC_TRACKING_MASK,
1851                                             ASSOC_TRACKING_SENT) == NULL))
1852                 {
1853                     /* Setup for next tracking */
1854                     Csf_setTrackingClock(TRACKING_DELAY_TIME);
1855                 }
1856             }
1857         }
1858     }
1861 /*!
1862  * @brief      Process retries for config messages
1863  */
1864 static void processConfigRetry(void)
1866     /* Retry config request if not already sent */
1867     if(((Collector_events & COLLECTOR_CONFIG_EVT) == 0)
1868         && (Csf_isConfigTimerActive() == false))
1869     {
1870         /* Set config event */
1871         Csf_setConfigClock(CONFIG_DELAY);
1872     }
1875 /*!
1876  * @brief      Process FW version response
1877  */
1878 static void oadFwVersionRspCb(void* pSrcAddr, char *fwVersionStr)
1880     LOG_printf( LOG_ALWAYS, "oadFwVersionRspCb from %x\n", ((ApiMac_sAddr_t*)pSrcAddr)->addr.shortAddr);
1881     Csf_deviceSensorFwVerUpdate(((ApiMac_sAddr_t*)pSrcAddr)->addr.shortAddr, fwVersionStr);
1884 /*!
1885  * @brief      Process OAD image identify response
1886  */
1887 static void oadImgIdentifyRspCb(void* pSrcAddr, uint8_t status)
1892 static void oadBlockReqCb(void* pSrcAddr, uint8_t imgId, uint16_t blockNum, uint16_t multiBlockSize)
1894     uint8_t blockBuf[OAD_BLOCK_SIZE] = {0};
1895     int byteRead = 0;
1896     uint32_t oad_file_idx;
1897     FILE *oadFile = NULL;
1899     LOG_printf( LOG_ALWAYS, "oadBlockReqCb[%d:%x] from %x\n", imgId, blockNum, ((ApiMac_sAddr_t*)pSrcAddr)->addr.shortAddr);
1901     Csf_deviceSensorOadUpdate( ((ApiMac_sAddr_t*)pSrcAddr)->addr.shortAddr, imgId, blockNum, oadBNumBlocks);
1903     for(oad_file_idx = 0; oad_file_idx < MAX_OAD_FILES; oad_file_idx++)
1904     {
1905         if(oad_file_list[oad_file_idx].oad_file_id == imgId)
1906         {
1907             LOG_printf( LOG_ALWAYS, "oadBlockReqCb: openinging %d:%d:%s\n", oad_file_idx,
1908                                     oad_file_list[oad_file_idx].oad_file_id,
1909                                     oad_file_list[oad_file_idx].oad_file);
1911             oadFile = fopen(oad_file_list[oad_file_idx].oad_file, "r");
1913             break;
1914         }
1915     }
1917     if(oadFile != NULL)
1918     {
1919         fseek(oadFile, (blockNum * OAD_BLOCK_SIZE), SEEK_SET);
1920         byteRead = (int) fread(blockBuf, 1, OAD_BLOCK_SIZE, oadFile);
1922         LOG_printf( LOG_ALWAYS, "oadBlockReqCb: read %d bytes from position %d of %p\n",
1923                                                     byteRead, (blockNum * OAD_BLOCK_SIZE), oadFile);
1925         if(byteRead == 0)
1926         {
1927             LOG_printf( LOG_ERROR, "oadBlockReqCb: Read 0 Bytes");
1928         }
1930         fclose(oadFile);
1932         OADProtocol_sendOadImgBlockRsp(pSrcAddr, imgId, blockNum, blockBuf);
1933     }
1934     else
1935     {
1936       LOG_printf( LOG_ALWAYS, "imgId %d file not found\n", imgId);
1937     }
1940 /*!
1941  * @brief      Radio access function for OAD module to send messages
1942  */
1943 void* oadRadioAccessAllocMsg(uint32_t msgLen)
1945     uint8_t *msgBuffer;
1947     /* allocate buffer for CmdId + message */
1948     msgBuffer = malloc(msgLen + 1);
1950     return msgBuffer + 1;
1953 /*!
1954  * @brief      Radio access function for OAD module to send messages
1955  */
1956 static OADProtocol_Status_t oadRadioAccessPacketSend(void* pDstAddr, uint8_t *pMsg, uint32_t msgLen)
1958     OADProtocol_Status_t status = OADProtocol_Failed;
1959     uint8_t* pMsduPayload;
1960     Cllc_associated_devices_t* pDev;
1962     pDev  = findDevice(pDstAddr);
1964     if( (pDev) && (pMsg) )
1965     {
1966         /* Buffer should have been allocated with oadRadioAccessAllocMsg,
1967          * so 1 byte before the oad msg buffer was allocated for the Smsgs_cmdId
1968          */
1969         pMsduPayload = pMsg - 1;
1970         pMsduPayload[0] = Smsgs_cmdIds_oad;
1972         /* Send the Tracking Request */
1973        if((sendMsg(Smsgs_cmdIds_oad, ((ApiMac_sAddr_t*)pDstAddr)->addr.shortAddr,
1974                 pDev->capInfo.rxOnWhenIdle,
1975                 (msgLen + 1),
1976                 pMsduPayload)) == true)
1977        {
1978            status = OADProtocol_Status_Success;
1979        }
1980     }
1982     if( (pDev) && (pMsg) )
1983     {
1984         /* Free the memory allocated in oadRadioAccessAllocMsg. */
1985         free(pMsg - 1);
1986     }
1988     return status;
1990 /*
1991  *  ========================================
1992  *  Texas Instruments Micro Controller Style
1993  *  ========================================
1994  *  Local Variables:
1995  *  mode: c
1996  *  c-file-style: "bsd"
1997  *  tab-width: 4
1998  *  c-basic-offset: 4
1999  *  indent-tabs-mode: nil
2000  *  End:
2001  *  vim:set  filetype=c tabstop=4 shiftwidth=4 expandtab=true
2002  */