4a96130f3835b5e8cd8d582f413296d7ce33efd1
[apps/tidep0084.git] / example / collector / csf_linux.c
1 /******************************************************************************
3  @file csf_linux.c [Linux version of csf.c]
5  @brief Collector Specific Functions
7  Group: WCS LPC
8  $Target Devices: Linux: AM335x, Embedded Devices: CC1310, CC1350$
10  ******************************************************************************
11  $License: BSD3 2016 $
12   
13    Copyright (c) 2015, Texas Instruments Incorporated
14    All rights reserved.
15   
16    Redistribution and use in source and binary forms, with or without
17    modification, are permitted provided that the following conditions
18    are met:
19   
20    *  Redistributions of source code must retain the above copyright
21       notice, this list of conditions and the following disclaimer.
22   
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.
26   
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.
30   
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 #if (defined(_MSC_VER) || defined(__linux__))
48 #define IS_HLOS 1  /* compiler=non-embedded */
49 #else
50 #define IS_HLOS 0  /* compiler=embedded */
51 #endif
52 /******************************************************************************
53  Includes
54  *****************************************************************************/
56 #if IS_HLOS
57 #include <stdio.h>
58 #include <stdarg.h>
59 #include <string.h>
60 #include <stdlib.h>
61 #include <stdint.h>
62 /* #include <unistd.h> */
63 #include "nvintf.h"
64 #include "nv_linux.h"
66 #include "log.h"
67 #include "mutex.h"
68 #include "ti_semaphore.h"
69 #include "timer.h"
71 #include "appsrv.h"
73 #include "util.h"
75 #include "common/util/board_lcd.h"
77 #else /* (HLOS) */
78 #include <xdc/std.h>
79 #include <xdc/runtime/Error.h>
80 #include <xdc/runtime/System.h>
81 #include <ti/sysbios/BIOS.h>
82 #include <ti/sysbios/knl/Clock.h>
83 #include <ti/sysbios/family/arm/m3/Hwi.h>
84 #include <ti/sysbios/knl/Semaphore.h>
85 #include <ti/drivers/Power.h>
86 #include <ti/drivers/PIN.h>
87 #include <string.h>
88 #include <inc/hw_ints.h>
89 #include <aon_event.h>
90 #include <ioc.h>
92 #include "board.h"
93 #include "timer.h"
94 #include "util.h"
95 #include "board_key.h"
96 #include "board_led.h"
98 #include "macconfig.h"
100 #include "nvoctp.h"
102 #include "icall.h"
104 #endif /* (HLOS) */
105 #include "config.h"
106 #include "api_mac.h"
107 #if IS_HLOS
108 #include "api_mac_linux.h"
109 #endif
110 #include "collector.h"
111 #include "cllc.h"
112 #include "csf.h"
114 #if defined(MT_CSF)
115 #include "mt_csf.h"
116 #endif
118 #if IS_HLOS
119 /* additional linux information */
120 #include "csf_linux.h"
121 #endif
123 /******************************************************************************
124  Constants and definitions
125  *****************************************************************************/
127 /* Initial timeout value for the tracking clock */
128 #define TRACKING_INIT_TIMEOUT_VALUE 100
130 /* NV Item ID - the device's network information */
131 #define CSF_NV_NETWORK_INFO_ID 0x0001
132 /* NV Item ID - the number of black list entries */
133 #define CSF_NV_BLACKLIST_ENTRIES_ID 0x0002
134 /* NV Item ID - the black list, use sub ID for each record in the list */
135 #define CSF_NV_BLACKLIST_ID 0x0003
136 /* NV Item ID - the number of device list entries */
137 #define CSF_NV_DEVICELIST_ENTRIES_ID 0x0004
138 /* NV Item ID - the device list, use sub ID for each record in the list */
139 #define CSF_NV_DEVICELIST_ID 0x0005
140 /* NV Item ID - this devices frame counter */
141 #define CSF_NV_FRAMECOUNTER_ID 0x0006
142 /* NV Item ID - reset reason */
143 #define CSF_NV_RESET_REASON_ID 0x0007
145 /* Maximum number of black list entries */
146 #define CSF_MAX_BLACKLIST_ENTRIES 10
148 /* Maximum number of device list entries */
149 #define CSF_MAX_DEVICELIST_ENTRIES 50
151 /*
152  Maximum sub ID for a blacklist item, this is failsafe.  This is
153  not the maximum number of items in the list
154  */
155 #define CSF_MAX_BLACKLIST_IDS 100
157 /*
158  Maximum sub ID for a device list item, this is failsafe.  This is
159  not the maximum number of items in the list
160  */
161 #define CSF_MAX_DEVICELIST_IDS 100
163 /* timeout value for trickle timer initialization */
164 #define TRICKLE_TIMEOUT_VALUE       20
166 /* timeout value for join timer */
167 #define JOIN_TIMEOUT_VALUE       20
168 /* timeout value for config request delay */
169 #define CONFIG_TIMEOUT_VALUE 1000
171 /*
172  The increment value needed to save a frame counter. Example, setting this
173  constant to 100, means that the frame counter will be saved when the new
174  frame counter is 100 more than the last saved frame counter.  Also, when
175  the get frame counter function reads the value from NV it will add this value
176  to the read value.
177  */
178 #define FRAME_COUNTER_SAVE_WINDOW     25
180 /* Value returned from findDeviceListIndex() when not found */
181 #define DEVICE_INDEX_NOT_FOUND  -1
183 /*! NV driver item ID for reset reason */
184 #define NVID_RESET {NVINTF_SYSID_APP, CSF_NV_RESET_REASON_ID, 0}
186 #ifdef IS_HLOS
188 #define board_led_type_LED1 0
189 #define board_led_type_LED2 0
190 #define board_led_state_ON  0
191 #define Board_Led_toggle(led)(void)led;
192 #define Board_Led_control(led, action) \
193 (void)led; \
194 (void)action;
196 #include <termios.h>
198 #define KEY_PERMIT_JOIN 'o'
199 #define KEY_SELECT_DEVICE 's'
200 #define KEY_FW_VER_REQ 'v'
201 #define KEY_FW_UPDATE_REQ 'u'
202 #define KEY_GET_OAD_FILE 'f'
203 #define KEY_TOGGLE_REQ 't'
204 #define KEY_LIST_DEVICES 'l'
205 #define KEY_DISASSOCIATE_DEVICE 'd'
207 #define DEFUALT_OAD_FILE "../../firmware/oad/sensor_oad_cc13x0lp_app.bin"
208 #endif //IS_HLOS
210 /******************************************************************************
211  External variables
212  *****************************************************************************/
213 #if IS_HLOS
215 /* handle for tracking timeout */
216 static intptr_t trackingClkHandle;
217 /* handle for PA trickle timeout */
218 static intptr_t tricklePAClkHandle;
219 /* handle for PC timeout */
220 static intptr_t tricklePCClkHandle;
221 /* handle for join permit timeout */
222 static intptr_t joinClkHandle;
224 /* handle for config request delay */
225 static intptr_t configClkHandle;
227 extern intptr_t semaphore0;
228 /* Non-volatile function pointers */
229 NVINTF_nvFuncts_t nvFps;
231 #else
233 #ifdef NV_RESTORE
234 /*! MAC Configuration Parameters */
235 extern mac_Config_t Main_user1Cfg;
236 #endif
238 #endif /* IS_HLOS */
240 /******************************************************************************
241  Local variables
242  *****************************************************************************/
243 #if IS_HLOS
244 static intptr_t collectorSem;
245 #define Semaphore_post(S)  SEMAPHORE_put(S)
246 #else
247 /* The application's semaphore */
248 static ICall_Semaphore collectorSem;
250 /* Clock/timer resources */
251 static Clock_Struct trackingClkStruct;
252 static Clock_Handle trackingClkHandle;
254 /* Clock/timer resources for CLLC */
255 /* trickle timer */
256 STATIC Clock_Struct tricklePAClkStruct;
257 STATIC Clock_Handle tricklePAClkHandle;
258 STATIC Clock_Struct tricklePCClkStruct;
259 STATIC Clock_Handle tricklePCClkHandle;
261 /* timer for join permit */
262 STATIC Clock_Struct joinClkStruct;
263 STATIC Clock_Handle joinClkHandle;
265 /* timer for config request delay */
266 STATIC Clock_Struct configClkStruct;
267 STATIC Clock_Handle configClkHandle;
268 #endif /* (!IS_HLOS) */
270 /* NV Function Pointers */
271 static NVINTF_nvFuncts_t *pNV = NULL;
273 /* Permit join setting */
274 static bool permitJoining = false;
276 static bool started = false;
278 /* The last saved coordinator frame counter */
279 static uint32_t lastSavedCoordinatorFrameCounter = 0;
281 #if defined(MT_CSF)
282 /*! NV driver item ID for reset reason */
283 static const NVINTF_itemID_t nvResetId = NVID_RESET;
284 #endif
286 #ifndef IS_HEADLESS
287 enum {
288     DisplayLine_product = 0,
289     DisplayLine_nwk,
290     DisplayLine_sensorStart,
291     DisplayLine_sensorEnd = 6,
292     DisplayLine_info,
293     DisplayLine_cmd,
294 } DisplayLine;
295 #else
296 #endif //IS_HEADLESS
298 static uint32_t selected_oad_file_id = 0;
300 /******************************************************************************
301  Global variables
302  *****************************************************************************/
303 /* Key press parameters */
304 uint8_t Csf_keys;
306 /* pending Csf_events */
307 uint16_t Csf_events = 0;
309 /* Saved CLLC state */
310 Cllc_states_t savedCllcState = Cllc_states_initWaiting;
312 /******************************************************************************
313  Local function prototypes
314  *****************************************************************************/
315 #if IS_HLOS
317 static void processTackingTimeoutCallback_WRAPPER(intptr_t thandle, intptr_t cookie);
318 static void processPATrickleTimeoutCallback_WRAPPER(intptr_t thandle, intptr_t cookie);
319 static void processPCTrickleTimeoutCallback_WRAPPER(intptr_t thandle, intptr_t cookie);
320 static void processJoinTimeoutCallback_WRAPPER(intptr_t thandle, intptr_t cookie);
321 static void processConfigTimeoutCallback_WRAPPER(intptr_t thandle, intptr_t cookie);
323 #ifndef IS_HEADLESS
324 char* getConsoleCmd(void);
325 void initConsoleCmd(void);
326 #endif //!IS_HEADLESS
328 #endif
330 static void processTackingTimeoutCallback(UArg a0);
331 static void processKeyChangeCallback(uint8_t keysPressed);
332 static void processPATrickleTimeoutCallback(UArg a0);
333 static void processPCTrickleTimeoutCallback(UArg a0);
334 static void processJoinTimeoutCallback(UArg a0);
335 static void processConfigTimeoutCallback(UArg a0);
336 static bool addDeviceListItem(Llc_deviceListItem_t *pItem);
337 static void updateDeviceListItem(Llc_deviceListItem_t *pItem);
338 static int findDeviceListIndex(ApiMac_sAddrExt_t *pAddr);
339 static int findUnusedDeviceListIndex(void);
340 static void saveNumDeviceListEntries(uint16_t numEntries);
341 static int findBlackListIndex(ApiMac_sAddr_t *pAddr);
342 static int findUnusedBlackListIndex(void);
343 static uint16_t getNumBlackListEntries(void);
344 static void saveNumBlackListEntries(uint16_t numEntries);
345 void removeBlackListItem(ApiMac_sAddr_t *pAddr);
346 static bool removeDevice(ApiMac_sAddr_t addr);
348 #if defined(TEST_REMOVE_DEVICE)
349 static void removeTheFirstDevice(void);
350 #endif
351 #if !IS_HLOS
352 /* not used in hlos version */
353 static uint16_t getTheFirstDevice(void);
354 #endif
356 /******************************************************************************
357  Public Functions
358  *****************************************************************************/
360 /*!
361  The application calls this function during initialization
363  Public function defined in csf.h
364  */
365 void Csf_init(void *sem)
367     char default_oad_file[256] = DEFUALT_OAD_FILE;
369     /* Set defualt FW image */
370     selected_oad_file_id = Collector_updateFwList(default_oad_file);
372     /* Initialize the LCD */
373     Board_LCD_open();
375 #ifndef IS_HEADLESS
376     Board_Lcd_printf(DisplayLine_product, "TI Collector");
378 #if !defined(AUTO_START)
379     Board_Lcd_printf(DisplayLine_nwk, "Nwk: Starting");
380 #endif /* AUTO_START */
382 #endif //!IS_HEADLESS
384 #if IS_HLOS
386 #ifndef IS_HEADLESS
387     initConsoleCmd();
388 #endif //!HEADLESS
390     /* Save off the semaphore */
391     collectorSem = (intptr_t)sem;
393     /* save the application semaphore here */
394     /* load the NV function pointers */
395     // printf("   >> Initialize the NV Function pointers \n");
396     NVOCTP_loadApiPtrs(&nvFps);
398     /* Suyash - the code is using pNV var. Using that for now. */
399     /* config nv pointer will be read from the mac_config_t... */
400     pNV = &nvFps;
402     /* Init NV */
403     nvFps.initNV(NULL);
405 #else
406    /* Save off the NV Function Pointers */
407 #ifdef NV_RESTORE
408     /* Save off the NV Function Pointers */
409     pNV = &Main_user1Cfg.nvFps;
410 #endif
412     /* Save off the semaphore */
413     collectorSem = sem;
415     /* Initialize keys */
416     if(Board_Key_initialize(processKeyChangeCallback) == KEY_RIGHT)
417     {
418         /* Right key is pressed on power up, clear all NV */
419         Csf_clearAllNVItems();
420     }
422 #ifndef IS_HEADLESS
423     /* Initialize the LCD */
424     Board_LCD_open();
426 #if !defined(AUTO_START)
427     Board_Lcd_printf(DisplayLine_nwk, "Nwk: Starting");
428 #endif /* AUTO_START */
429 #endif //!IS_HEADLESS
431     Board_Led_initialize();
433 #if defined(MT_CSF)
434     {
435         uint8_t resetReseason = 0;
437         if(pNV != NULL)
438         {
439             if(pNV->readItem != NULL)
440             {
441                 /* Attempt to retrieve reason for the reset */
442                 (void)pNV->readItem(nvResetId, 0, 1, &resetReseason);
443             }
445             if(pNV->deleteItem != NULL)
446             {
447                 /* Only use this reason once */
448                 (void)pNV->deleteItem(nvResetId);
449             }
450         }
452         /* Start up the MT message handler */
453         MTCSF_init(resetReseason);
455         /* Did we reset because of assert? */
456         if(resetReseason > 0)
457         {
458 #if IS_HEADLESS
459             Board_Lcd_printf(DisplayLine_nwk, "Nwk: Restarting");
460 #endif //!IS_HEADLESS
462             /* Tell the collector to restart */
463             Csf_events |= CSF_KEY_EVENT;
464             Csf_keys |= KEY_LEFT;
465         }
466     }
467 #endif
468 #endif /* IS_HLOS */
471 /*!
472  The application must call this function periodically to
473  process any Csf_events that this module needs to process.
475  Public function defined in csf.h
476  */
477 void Csf_processEvents(void)
480 #if (!defined(IS_HEADLESS) && defined(IS_HLOS))
482     char *cmdBuff;
483     static uint16_t selected_device = 0;
485     cmdBuff = getConsoleCmd();
487     if(cmdBuff)
488     {
489         Csf_keys = cmdBuff[0];
491         if(Csf_keys == KEY_PERMIT_JOIN)
492         {
493             uint32_t duration;
494             /* Toggle the permit joining */
495             if (permitJoining == true)
496             {
497                 permitJoining = false;
498                 duration = 0;
499                 Board_Lcd_printf(DisplayLine_info, "Info: PermitJoin-OFF");
500             }
501             else
502             {
503                 permitJoining = true;
504                 duration = 0xFFFFFFFF;
505                 Board_Lcd_printf(DisplayLine_info, "Info: PermitJoin-ON ");
506             }
508             /* Set permit joining */
509             Cllc_setJoinPermit(duration);
510         }
512         if(Csf_keys == KEY_SELECT_DEVICE)
513         {
514             if(sscanf(cmdBuff, "s0x%hx", &selected_device) < 1)
515             {
516                 sscanf(cmdBuff, "s%hd", &selected_device);
517             }
519             Board_Lcd_printf(DisplayLine_info, "Info: Selected device 0x%04x", selected_device);
520         }
522         if(Csf_keys == KEY_FW_VER_REQ)
523         {
524             ApiMac_sAddr_t sAddr;
526             Board_Lcd_printf(DisplayLine_info, "Info: Sending 0x%04x FW version req", selected_device);
528             sAddr.addr.shortAddr = selected_device;
529             sAddr.addrMode = ApiMac_addrType_short;
530             Collector_sendFwVersionRequest(&sAddr);
531         }
533         if(Csf_keys == KEY_FW_UPDATE_REQ)
534         {
535             ApiMac_sAddr_t sAddr;
536             Collector_status_t status;
538             Board_Lcd_printf(DisplayLine_info, "Info: Sending 0x%04x FW Update Req", selected_device);
540             sAddr.addr.shortAddr = selected_device;
541             sAddr.addrMode = ApiMac_addrType_short;
542             status = Collector_startFwUpdate(&sAddr, selected_oad_file_id);
544             if(status == Collector_status_invalid_file)
545             {
546                 Board_Lcd_printf(DisplayLine_info, "Info: Update req file not found ID:%d", selected_oad_file_id);
547             }
548             else if(status != Collector_status_success)
549             {
550                 Board_Lcd_printf(DisplayLine_info, "Info: Update req failed");
551             }
552         }
554         if(Csf_keys == KEY_GET_OAD_FILE)
555         {
556             static char new_oad_file[256] = DEFUALT_OAD_FILE;
558             if(sscanf(cmdBuff, "f %s", new_oad_file))
559             {
560                 selected_oad_file_id = Collector_updateFwList(new_oad_file);
561             }
563             Board_Lcd_printf(DisplayLine_info, "Info: OAD file %s", new_oad_file);
564         }
566         if(Csf_keys == KEY_TOGGLE_REQ)
567         {
568             ApiMac_sAddr_t sAddr;
569             Collector_status_t status;
571             Board_Lcd_printf(DisplayLine_info, "Info: Sending 0x%04x LED toggle req", selected_device);
573             sAddr.addr.shortAddr = selected_device;
574             sAddr.addrMode = ApiMac_addrType_short;
575             status = Csf_sendToggleLedRequest(&sAddr);
577             if(status == Collector_status_deviceNotFound)
578             {
579                 Board_Lcd_printf(DisplayLine_info, "Info: Toggle Req device 0x%04x not found", selected_device);
580             }
581             else if(status != Collector_status_success)
582             {
583                 Board_Lcd_printf(DisplayLine_info, "Info: Update Req failed");
584             }
585         }
587         if(Csf_keys == KEY_LIST_DEVICES)
588         {
589             ApiMac_sAddr_t sAddr;
590             uint32_t devIdx;
592             for(devIdx = 1; devIdx < CONFIG_MAX_DEVICES; devIdx++)
593             {
594                 sAddr.addr.shortAddr = devIdx;
595                 sAddr.addrMode = ApiMac_addrType_short;
597                 if(Collector_findDevice(&sAddr) == Collector_status_success)
598                 {
599                     Board_Lcd_printf(DisplayLine_info, "Info: Device 0x%04x found", devIdx);
600                 }
601             }
602         }
604         if(Csf_keys == KEY_DISASSOCIATE_DEVICE)
605         {
606             ApiMac_sAddr_t sAddr;
608             Board_Lcd_printf(DisplayLine_info, "Info: Sending 0x%04x disassociation req", selected_device);
610             sAddr.addr.shortAddr = selected_device;
611             sAddr.addrMode = ApiMac_addrType_short;
613             if(!removeDevice(sAddr))
614             {
615                 Board_Lcd_printf(DisplayLine_info, "Info: disassociation req device 0x%04x not found", selected_device);
616             }
617         }
619         /* Clear the key press indication */
620         Csf_keys = 0;
621     }
623     /* Clear the event */
624     Util_clearEvent(&Csf_events, CSF_KEY_EVENT);
626 #endif /* (!defined(IS_HEADLESS) && defined(IS_HLOS)) */
628 #if defined(MT_CSF)
629     MTCSF_displayStatistics();
630 #endif
633 #if (!defined(IS_HEADLESS) && defined(IS_HLOS))
634 void initConsoleCmd(void)
636     struct termios term_attr;
638     /* set the terminal to raw mode */
639     tcgetattr(fileno(stdin), &term_attr);
640     term_attr.c_lflag &= ~(ECHO|ICANON);
641     term_attr.c_cc[VTIME] = 0;
642     term_attr.c_cc[VMIN] = 0;
643     tcsetattr(fileno(stdin), TCSANOW, &term_attr);
647 char* getConsoleCmd(void)
649     static bool cmdComplete = false;
650     static char cmd[256] = {0};
651     static int ch;
652     static uint8_t cmdIdx = 0;
654     if(cmdComplete)
655     {
656         memset(cmd, 0, 256);
657         cmdIdx = 0;
658         cmdComplete = false;
659     }
661     /* read a character from the stdin stream without blocking */
662     /*   returns EOF (-1) if no character is available */
663     ch = getchar();
665     if(ch != -1)
666     {
667          /* Discard non-ascii characters except new lines */
668         if(ch == 0xa || (ch >= 0x20 && ch < 0x7F))
669         {
670             cmd[cmdIdx] = ch;
671         }
673         Board_Lcd_printf(DisplayLine_cmd, "cmd: %s", cmd)
674         //cmdIdx will wrap arounf for the 256Byte buffer
675         if(cmd[cmdIdx] == 0xa)
676         {
677             cmdComplete = true;
678         }
679         else
680         {
681             cmdIdx++;
682         }
683     }
685     if(cmdComplete)
686     {
687         return cmd;
688     }
689     else
690     {
691         return 0;
692     }
694 #endif //(!defined(HEADLESS) && defined(IS_HLOS))
696 /*!
697  The application calls this function to retrieve the stored
698  network information.
700  Public function defined in csf.h
701  */
702 bool Csf_getNetworkInformation(Llc_netInfo_t *pInfo)
704     if((pNV != NULL) && (pNV->readItem != NULL) && (pInfo != NULL))
705     {
706         NVINTF_itemID_t id;
708         /* Setup NV ID */
709         id.systemID = NVINTF_SYSID_APP;
710         id.itemID = CSF_NV_NETWORK_INFO_ID;
711         id.subID = 0;
713         /* Read Network Information from NV */
714         if(pNV->readItem(id, 0, sizeof(Llc_netInfo_t), pInfo) == NVINTF_SUCCESS)
715         {
716             return(true);
717         }
718     }
719     return(false);
722 /*!
723  The application calls this function to indicate that it has
724  started or restored the device in a network
726  Public function defined in csf.h
727  */
728 void Csf_networkUpdate(bool restored, Llc_netInfo_t *pNetworkInfo)
730     /* check for valid structure ponter, ignore if not */
731     if(pNetworkInfo != NULL)
732     {
733         if((pNV != NULL) && (pNV->writeItem != NULL))
734         {
735             NVINTF_itemID_t id;
737             /* Setup NV ID */
738             id.systemID = NVINTF_SYSID_APP;
739             id.itemID = CSF_NV_NETWORK_INFO_ID;
740             id.subID = 0;
742             /* Write the NV item */
743             pNV->writeItem(id, sizeof(Llc_netInfo_t), pNetworkInfo);
744         }
747 #if IS_HLOS
748         /* Send info to appClient */
749         if(pNetworkInfo != NULL)
750         {
751              appsrv_networkUpdate(restored, pNetworkInfo);
752         }
753 #endif /* IS_HLOS */
755         started = true;
757 #ifndef IS_HEADLESS
758         if(restored == false)
759         {
760             Board_Lcd_printf(DisplayLine_nwk, "Nwk: Started");
761         }
762         else
763         {
764             Board_Lcd_printf(DisplayLine_nwk, "Nwk: Started");
765         }
767         if(pNetworkInfo->fh == false)
768         {
769             Board_Lcd_printf(DisplayLine_info, "Info: Channel %d", pNetworkInfo->channel);
770         }
771         else
772         {
773             Board_Lcd_printf(DisplayLine_info, "Info: Freq. Hopping");
774         }
775 #endif //!IS_HEADLESS
777         Board_Led_control(board_led_type_LED1, board_led_state_ON);
779 #if defined(MT_CSF)
780         MTCSF_networkUpdateIndCB();
781 #endif
782     }
785 /*!
786  The application calls this function to indicate that a device
787  has joined the network.
789  Public function defined in csf.h
790  */
791 ApiMac_assocStatus_t Csf_deviceUpdate(ApiMac_deviceDescriptor_t *pDevInfo,
792                                       ApiMac_capabilityInfo_t *pCapInfo)
794     ApiMac_assocStatus_t status = ApiMac_assocStatus_success;
795     ApiMac_sAddr_t shortAddr;
796     ApiMac_sAddr_t extAddr;
798     shortAddr.addrMode = ApiMac_addrType_short;
799     shortAddr.addr.shortAddr = pDevInfo->shortAddress;
801     extAddr.addrMode = ApiMac_addrType_extended;
802     memcpy(&extAddr.addr.extAddr, &pDevInfo->extAddress, APIMAC_SADDR_EXT_LEN);
804     /* Is the device in the black list? */
805     if((findBlackListIndex(&shortAddr) >= 0)
806        || (findBlackListIndex(&extAddr) >= 0))
807     {
808         /* Denied */
809         status = ApiMac_assocStatus_panAccessDenied;
811 #if IS_HLOS
812         LOG_printf(LOG_APPSRV_MSG_CONTENT,
813                    "Denied: 0x%04x\n",
814                    pDevInfo->shortAddress);
815 #endif /* IS_HLOS */
817 #ifndef IS_HEADLESS
818         Board_Lcd_printf(DisplayLine_info, "Info: Denied 0x%04x", pDevInfo->shortAddress);
819 #endif //IS_HEADLESS
820     }
821     else
822     {
823         /* Save the device information */
824         Llc_deviceListItem_t dev;
826         memcpy(&dev.devInfo, pDevInfo, sizeof(ApiMac_deviceDescriptor_t));
827         memcpy(&dev.capInfo, pCapInfo, sizeof(ApiMac_capabilityInfo_t));
828         dev.rxFrameCounter = 0;
830         if(addDeviceListItem(&dev) == false)
831         {
832 #ifdef NV_RESTORE
833             status = ApiMac_assocStatus_panAtCapacity;
835 #if IS_HLOS
836             LOG_printf(LOG_ERROR,"Failed: 0x%04x\n", pDevInfo->shortAddress);
837 #endif /* IS_HLOS */
839 #ifndef IS_HEADLESS
840             Board_Lcd_printf(DisplayLine_info, "Info: Join Failed 0x%04x", pDevInfo->shortAddress);
841 #endif //!IS_HEADLESS
843 #else /* NV_RESTORE */
844         status = ApiMac_assocStatus_success;
845 #if IS_HLOS
846         LOG_printf(LOG_ERROR,"Joined: 0x%04x\n", pDevInfo->shortAddress);
847 #endif /* IS_HLOS */
849 #ifndef IS_HEADLESS
850         Board_Lcd_printf(DisplayLine_info, "Info: Joined 0x%04x", pDevInfo->shortAddress);
851 #endif //!IS_HEADLESS
853 #endif /* NV_RESTORE */
854         }
855         else
856         {
857 #if IS_HLOS
858          /* Send update to the appClient */
859             LOG_printf(LOG_APPSRV_MSG_CONTENT,
860                        "sending device update info to appsrv \n");
861             appsrv_deviceUpdate(&dev);
862 #endif /* IS_HLOS */
864 #ifndef IS_HEADLESS
865             Board_Lcd_printf(DisplayLine_info, "Info: Joined 0x%04x", pDevInfo->shortAddress);
866 #endif //!IS_HEADLESS
867         }
868     }
870 #if defined(MT_CSF)
871     MTCSF_deviceUpdateIndCB(pDevInfo, pCapInfo);
872 #endif
874     /* Return the status of the joining device */
875     return (status);
878 /*!
879  The application calls this function to indicate that a device
880  is no longer active in the network.
882  Public function defined in csf.h
883  */
884 void Csf_deviceNotActiveUpdate(ApiMac_deviceDescriptor_t *pDevInfo,
885 bool timeout)
888 #if IS_HLOS
889     /* send update to the appClient */
890     LOG_printf(LOG_APPSRV_MSG_CONTENT,
891                "!Responding: 0x%04x\n",
892                pDevInfo->shortAddress);
893     appsrv_deviceNotActiveUpdate(pDevInfo, timeout);
894     LOG_printf( LOG_DBG_API_MAC_datastats,
895                 "inactive: pan: 0x%04x short: 0x%04x ext: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
896                 pDevInfo->panID,
897                 pDevInfo->shortAddress,
898                 pDevInfo->extAddress[0],
899                 pDevInfo->extAddress[1],
900                 pDevInfo->extAddress[2],
901                 pDevInfo->extAddress[3],
902                 pDevInfo->extAddress[4],
903                 pDevInfo->extAddress[5],
904                 pDevInfo->extAddress[6],
905                 pDevInfo->extAddress[7]);
906 #endif /* IS_HLOS */
908 #ifndef IS_HEADLESS
909     Board_Lcd_printf(DisplayLine_info, "Info: No response 0x%04x", pDevInfo->shortAddress);
910 #endif //IS_HEADLESS
912 #if defined(MT_CSF)
913     MTCSF_deviceNotActiveIndCB(pDevInfo, timeout);
914 #endif
918 /*!
919  The application calls this function to indicate that a device
920  has responded to a Config Request.
922  Public function defined in csf.h
923  */
924 void Csf_deviceConfigUpdate(ApiMac_sAddr_t *pSrcAddr, int8_t rssi,
925                             Smsgs_configRspMsg_t *pMsg)
927 #if IS_HLOS
928     /* send update to the appClient */
929     appsrv_deviceConfigUpdate(pSrcAddr,rssi,pMsg);
930     LOG_printf(LOG_APPSRV_MSG_CONTENT,
931                "ConfigRsp: 0x%04x\n",
932                pSrcAddr->addr.shortAddr);
933 #endif /* IS_HLOS */
935 #ifndef IS_HEADLESS
936     Board_Lcd_printf(DisplayLine_info, "Info: ConfigRsp 0x%04x", pSrcAddr->addr.shortAddr);
937 #endif //IS_HEADLESS
939 #if defined(MT_CSF)
940     MTCSF_configResponseIndCB(pSrcAddr, rssi, pMsg);
941 #endif
945 /*!
946  The application calls this function to indicate that a device
947  has reported sensor data.
949  Public function defined in csf.h
950  */
951 void Csf_deviceSensorDataUpdate(ApiMac_sAddr_t *pSrcAddr, int8_t rssi,
952                                 Smsgs_sensorMsg_t *pMsg)
954 #ifndef IS_HEADLESS
955     uint16_t sensorData = pMsg->tempSensor.ambienceTemp;
957     if((DisplayLine_sensorStart + (pSrcAddr->addr.shortAddr - 1)) < DisplayLine_sensorEnd)
958     {
959         Board_Lcd_printf(DisplayLine_sensorStart + (pSrcAddr->addr.shortAddr - 1), "Sensor 0x%04x: Temp %d, RSSI %d",
960                         pSrcAddr->addr.shortAddr, sensorData, rssi);
961     }
962     else
963     {
964         Board_Lcd_printf(DisplayLine_sensorEnd, "Sensor 0x%04x: Temp %d, RSSI %d",
965                         pSrcAddr->addr.shortAddr, sensorData, rssi);
966     }
967 #endif //!IS_HEADLESS
969 #if IS_HLOS
970     /* send data to the appClient */
971     LOG_printf(LOG_APPSRV_MSG_CONTENT,
972                "Sensor 0x%04x\n",
973                pSrcAddr->addr.shortAddr);
975     appsrv_deviceSensorDataUpdate(pSrcAddr, rssi, pMsg);
976 #endif /* IS_HLOS */
978     Board_Led_toggle(board_led_type_LED2);
980 #if defined(MT_CSF)
981     MTCSF_sensorUpdateIndCB(pSrcAddr, rssi, pMsg);
982 #endif
985 /*!
986  The application calls this function to indicate that a device
987  has disassociated.
989  Public function defined in csf.h
990  */
991 void Csf_deviceDisassocUpdate( ApiMac_sAddr_t *pSrcAddr )
993 #ifndef IS_HEADLESS
994     if(pSrcAddr->addrMode == ApiMac_addrType_extended)
995     {
996         Board_Lcd_printf(DisplayLine_info, "Info: Disassociate ind from %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
997                             pSrcAddr->addr.extAddr[7], pSrcAddr->addr.extAddr[6],
998                             pSrcAddr->addr.extAddr[5], pSrcAddr->addr.extAddr[4],
999                             pSrcAddr->addr.extAddr[3], pSrcAddr->addr.extAddr[2],
1000                             pSrcAddr->addr.extAddr[1], pSrcAddr->addr.extAddr[0]);
1001     }
1002     else //assume short addr
1003     {
1004         Board_Lcd_printf(DisplayLine_info, "Info: Disassociate ind from 0x%04x", pSrcAddr->addr.shortAddr);
1005     }
1006 #endif //!IS_HEADLESS
1009 /*!
1010  The application calls this function to indicate that a device
1011  has reported its FW version.
1013  Public function defined in csf.h
1014  */
1015 void Csf_deviceSensorFwVerUpdate( uint16_t srcAddr, char *fwVerStr)
1017     Board_Led_toggle(board_led_type_LED2);
1019 #ifndef IS_HEADLESS
1020     if((DisplayLine_sensorStart + (srcAddr - 1)) < DisplayLine_sensorEnd)
1021     {
1022         Board_Lcd_printf(DisplayLine_sensorStart + (srcAddr - 1), "Sensor 0x%04x: FW Ver %s",
1023                         srcAddr, fwVerStr);
1024     }
1025     else
1026     {
1027         Board_Lcd_printf(DisplayLine_sensorEnd, "Sensor 0x%04x: FW Ver %s",
1028                         srcAddr, fwVerStr);
1029     }
1030 #endif //!IS_HEADLESS
1033 /*!
1034  The application calls this function to indicate that a device
1035  has reported its FW version.
1037  Public function defined in csf.h
1038  */
1039 void Csf_deviceSensorOadUpdate( uint16_t srcAddr, uint16_t imgId, uint16_t blockNum, uint16_t NumBlocks)
1041     Board_Led_toggle(board_led_type_LED2);
1043 #ifndef IS_HEADLESS
1044     uint8_t displayLine = 0;
1045     
1046     if((DisplayLine_sensorStart + (srcAddr - 1)) < DisplayLine_sensorEnd)
1047     {
1048         displayLine = (DisplayLine_sensorStart + (srcAddr - 1));
1049     }
1050     else
1051     {
1052         displayLine = DisplayLine_sensorEnd;
1053     }
1054     
1055     if((blockNum + 1) == NumBlocks)
1056     {
1057         Board_Lcd_printf(displayLine, "Sensor 0x%04x: OAD completed, booting new image...", 
1058                         srcAddr);
1059     }
1060     else
1061     {
1062         Board_Lcd_printf(displayLine, "Sensor 0x%04x: OAD image %d, block %d of %d",
1063                 srcAddr, imgId, blockNum + 1, NumBlocks);
1064     }
1065 #endif //!IS_HEADLESS
1068 /*!
1069  The application calls this function to indicate that a device
1070  set a Toggle LED Response message.
1072  Public function defined in csf.h
1073  */
1074 void Csf_toggleResponseReceived(ApiMac_sAddr_t *pSrcAddr, bool ledState)
1076 #if defined(MT_CSF)
1077     uint16_t shortAddr = 0xFFFF;
1079     Board_Lcd_printf(DisplayLine_info, "Info: Device 0x%04x LED toggle rsp received", selected_device);
1081     if(pSrcAddr)
1082     {
1083         if(pSrcAddr->addrMode == ApiMac_addrType_short)
1084         {
1085             shortAddr = pSrcAddr->addr.shortAddr;
1086         }
1087         else
1088         {
1089             /* Convert extended to short addr */
1090             shortAddr = Csf_getDeviceShort(&pSrcAddr->addr.extAddr);
1091         }
1092     }
1093     MTCSF_deviceToggleIndCB(shortAddr, ledState);
1094 #endif
1097 /*!
1098  The application calls this function to indicate that the
1099  Coordinator's state has changed.
1101  Public function defined in csf.h
1102  */
1103 void Csf_stateChangeUpdate(Cllc_states_t state)
1105 #if !defined(IS_HLOS)
1106     if(started == true)
1107     {
1108         if(state == Cllc_states_joiningAllowed)
1109         {
1110             /* Flash LED1 while allowing joining */
1111             Board_Led_control(board_led_type_LED1, board_led_state_BLINKING);
1112         }
1113         else if(state == Cllc_states_joiningNotAllowed)
1114         {
1115             /* Don't flash when not allowing joining */
1116             Board_Led_control(board_led_type_LED1, board_led_state_ON);
1117         }
1118     }
1119 #endif
1120     /* Save the state to be used later */
1121     savedCllcState = state;
1123 #if defined(MT_CSF)
1124     MTCSF_stateChangeIndCB(state);
1125 #endif
1126 #if IS_HLOS
1127     /* Send the update to appClient */
1128     LOG_printf(LOG_APPSRV_MSG_CONTENT,
1129                "stateChangeUpdate, newstate: (%d) %s\n",
1130                (int)(state), CSF_cllc_statename(state));
1131     appsrv_stateChangeUpdate(state);
1132 #endif /* IS_HLOS */
1135 /* Wrappers for Callbacks*/
1136 #if IS_HLOS
1138 static void processConfigTimeoutCallback_WRAPPER(intptr_t timer_handle,
1139                          intptr_t cookie)
1141     (void)timer_handle;
1142     (void)cookie;
1143     processConfigTimeoutCallback(0);
1146 static void processJoinTimeoutCallback_WRAPPER(intptr_t timer_handle,
1147                                                intptr_t cookie)
1149     (void)timer_handle;
1150     (void)cookie;
1151     processJoinTimeoutCallback(0);
1154 static void processPATrickleTimeoutCallback_WRAPPER(intptr_t timer_handle,
1155                                                     intptr_t cookie)
1157     (void)timer_handle;
1158     (void)cookie;
1159     processPATrickleTimeoutCallback(0);
1162 static void processPCTrickleTimeoutCallback_WRAPPER(intptr_t timer_handle,
1163                                                     intptr_t cookie)
1165     (void)timer_handle;
1166     (void)cookie;
1167     processPCTrickleTimeoutCallback(0);
1170 /* Wrap HLOS to embedded callback */
1171 static void processTackingTimeoutCallback_WRAPPER(intptr_t timer_handle,
1172                                                   intptr_t cookie)
1174     (void)timer_handle;
1175     (void)cookie;
1176     processTackingTimeoutCallback(0);
1179 #endif
1181 /*!
1182  Initialize the tracking clock.
1184  Public function defined in csf.h
1185  */
1186 void Csf_initializeTrackingClock(void)
1188 #if IS_HLOS
1189     trackingClkHandle = TIMER_CB_create("trackingTimer",
1190         processTackingTimeoutCallback_WRAPPER,
1191         0,
1192         TRACKING_INIT_TIMEOUT_VALUE,
1193         false);
1194 #else
1195     /* Initialize the timers needed for this application */
1196     trackingClkHandle = Timer_construct(&trackingClkStruct,
1197                                         processTackingTimeoutCallback,
1198                                         TRACKING_INIT_TIMEOUT_VALUE,
1199                                         0,
1200                                         false,
1201                                         0);
1202 #endif
1205 /*!
1206  Initialize the trickle clock.
1208  Public function defined in csf.h
1209  */
1210 void Csf_initializeTrickleClock(void)
1212 #if IS_HLOS
1213     tricklePAClkHandle =
1214         TIMER_CB_create(
1215             "paTrickleTimer",
1216             processPATrickleTimeoutCallback_WRAPPER,
1217              0,
1218                 TRICKLE_TIMEOUT_VALUE,
1219                 false);
1221     tricklePCClkHandle =
1222         TIMER_CB_create(
1223             "pcTrickleTimer",
1224             processPCTrickleTimeoutCallback_WRAPPER,
1225              0,
1226             TRICKLE_TIMEOUT_VALUE,
1227         false);
1229 #else
1230     /* Initialize trickle timer */
1231     tricklePAClkHandle = Timer_construct(&tricklePAClkStruct,
1232                                          processPATrickleTimeoutCallback,
1233                                          TRICKLE_TIMEOUT_VALUE,
1234                                          0,
1235                                          false,
1236                                          0);
1238     tricklePCClkHandle = Timer_construct(&tricklePCClkStruct,
1239                                          processPCTrickleTimeoutCallback,
1240                                          TRICKLE_TIMEOUT_VALUE,
1241                                          0,
1242                                          false,
1243                                          0);
1244 #endif
1247 /*!
1248  Initialize the clock for join permit attribute.
1250  Public function defined in csf.h
1251  */
1252 void Csf_initializeJoinPermitClock(void)
1254 #if IS_HLOS
1255     /* Initialize join permit timer */
1256     joinClkHandle =
1257         TIMER_CB_create(
1258         "joinTimer",
1259         processJoinTimeoutCallback_WRAPPER,
1260         0,
1261         JOIN_TIMEOUT_VALUE,
1262         false);
1263 #else
1264     /* Initialize join permit timer */
1265     joinClkHandle = Timer_construct(&joinClkStruct,
1266                                     processJoinTimeoutCallback,
1267                                     JOIN_TIMEOUT_VALUE,
1268                                     0,
1269                                     false,
1270                                     0);
1271 #endif
1274 /*!
1275  Initialize the clock for config request delay
1277  Public function defined in csf.h
1278  */
1279 void Csf_initializeConfigClock(void)
1281 #if IS_HLOS
1282     configClkHandle =
1283         TIMER_CB_create(
1284             "configTimer",
1285             processConfigTimeoutCallback_WRAPPER,
1286             0,
1287             CONFIG_TIMEOUT_VALUE,
1288             false );
1289 #else
1290     /* Initialize join permit timer */
1291     configClkHandle = Timer_construct(&configClkStruct,
1292                                     processConfigTimeoutCallback,
1293                                     CONFIG_TIMEOUT_VALUE,
1294                                     0,
1295                                     false,
1296                                     0);
1297 #endif
1300 /*!
1301  Set the tracking clock.
1303  Public function defined in csf.h
1304  */
1305 void Csf_setTrackingClock(uint32_t trackingTime)
1307 #if IS_HLOS
1308     /* Stop the Tracking timer */
1310     TIMER_CB_destroy(trackingClkHandle);
1311     trackingClkHandle = 0;
1313     /* Setup timer */
1314     if(trackingTime != 0)
1315     {
1316         trackingClkHandle =
1317             TIMER_CB_create(
1318                 "trackingTimer",
1319                 processTackingTimeoutCallback_WRAPPER,
1320                 0,
1321                 trackingTime,
1322                 false);
1323     }
1324 #else
1325     /* Stop the Tracking timer */
1326     if(Timer_isActive(&trackingClkStruct) == true)
1327     {
1328         Timer_stop(&trackingClkStruct);
1329     }
1331     if(trackingTime)
1332     {
1333         /* Setup timer */
1334         Timer_setTimeout(trackingClkHandle, trackingTime);
1335         Timer_start(&trackingClkStruct);
1336     }
1337 #endif
1340 /*!
1341  Set the trickle clock.
1343  Public function defined in csf.h
1344  */
1345 void Csf_setTrickleClock(uint32_t trickleTime, uint8_t frameType)
1347     uint16_t randomNum = 0;
1348     uint16_t randomTime = 0;
1350     if(trickleTime > 0)
1351     {
1352         randomNum = ((ApiMac_randomByte() << 8) + ApiMac_randomByte());
1353         randomTime = (trickleTime >> 1) +
1354                       (randomNum % (trickleTime >> 1));
1355     }
1357     if(frameType == ApiMac_wisunAsyncFrame_advertisement)
1358     {
1359 #if IS_HLOS
1360         /* ALWAYS stop (avoid race conditions) */
1361         TIMER_CB_destroy(tricklePAClkHandle);
1362         tricklePAClkHandle = 0;
1364     /* then create new, only if needed */
1365         if(trickleTime > 0)
1366         {
1367             /* Setup timer */
1368             tricklePAClkHandle = TIMER_CB_create(
1369                 "paTrickleTimer",
1370                     processPATrickleTimeoutCallback_WRAPPER,
1371                     0,
1372                     randomTime,
1373                     false);
1374         }
1375 #else
1376         /* Stop the PA trickle timer */
1377         if(Timer_isActive(&tricklePAClkStruct) == true)
1378         {
1379             Timer_stop(&tricklePAClkStruct);
1380         }
1382         if(trickleTime > 0)
1383         {
1384             /* Setup timer */
1385             Timer_setTimeout(tricklePAClkHandle, randomTime);
1386             Timer_start(&tricklePAClkStruct);
1387         }
1388 #endif
1389     }
1390     else if(frameType == ApiMac_wisunAsyncFrame_config)
1391     {
1392 #if IS_HLOS
1393         /* Always stop */
1394         TIMER_CB_destroy(tricklePCClkHandle);
1395         tricklePCClkHandle = 0;
1396     /* and recreate only if needed */
1397         if(trickleTime > 0)
1398         {
1399             /* Setup timer */
1400             tricklePCClkHandle =
1401                 TIMER_CB_create(
1402                 "pcTrickleTimer",
1403                 processPCTrickleTimeoutCallback_WRAPPER,
1404                 0,
1405                 trickleTime, false);
1406         }
1407 #else
1408         /* Stop the PC trickle timer */
1409         if(Timer_isActive(&tricklePCClkStruct) == true)
1410         {
1411             Timer_stop(&tricklePCClkStruct);
1412         }
1414         if(trickleTime > 0)
1415         {
1416             /* Setup timer */
1417             Timer_setTimeout(tricklePCClkHandle, randomTime);
1418             Timer_start(&tricklePCClkStruct);
1419         }
1420 #endif
1421     }
1424 /*!
1425  Set the clock join permit attribute.
1427  Public function defined in csf.h
1428  */
1429 void Csf_setJoinPermitClock(uint32_t joinDuration)
1431 #if IS_HLOS
1432     /* Always stop the join timer */
1433     TIMER_CB_destroy(joinClkHandle);
1434     joinClkHandle = 0;
1436     /* Setup timer */
1437     if(joinDuration != 0)
1438     {
1439         joinClkHandle =
1440             TIMER_CB_create("joinTimer",
1441                 processJoinTimeoutCallback_WRAPPER,
1442                 0,
1443                 joinDuration, false);
1444     }
1445 #else
1446     /* Stop the join timer */
1447     if(Timer_isActive(&joinClkStruct) == true)
1448     {
1449         Timer_stop(&joinClkStruct);
1450     }
1452     if(joinDuration != 0)
1453     {
1454         /* Setup timer */
1455         Timer_setTimeout(joinClkHandle, joinDuration);
1456         Timer_start(&joinClkStruct);
1457     }
1458 #endif
1461 /*!
1462  Set the clock config request delay.
1464  Public function defined in csf.h
1465  */
1466 void Csf_setConfigClock(uint32_t delay)
1468 #if IS_HLOS
1469     /* Always destroy */
1470     TIMER_CB_destroy( configClkHandle );
1471     configClkHandle = 0;
1472     /* and create if needed */
1473     if( delay != 0 ){
1474         configClkHandle =
1475             TIMER_CB_create( "configClk",
1476                              processConfigTimeoutCallback_WRAPPER,
1477                              0,
1478                              delay,
1479                              false );
1480     }
1481 #else
1482     /* Stop the join timer */
1483     if(Timer_isActive(&configClkStruct) == true)
1484     {
1485         Timer_stop(&configClkStruct);
1486     }
1488     if(delay != 0)
1489     {
1490         /* Setup timer */
1491         Timer_setTimeout(configClkHandle, delay);
1492         Timer_start(&configClkStruct);
1493     }
1494 #endif
1497 /*!
1498  Read the number of device list items stored
1500  Public function defined in csf.h
1501  */
1502 uint16_t Csf_getNumDeviceListEntries(void)
1504     uint16_t numEntries = 0;
1506     if(pNV != NULL)
1507     {
1508         NVINTF_itemID_t id;
1509         uint8_t stat;
1511         /* Setup NV ID for the number of entries in the device list */
1512         id.systemID = NVINTF_SYSID_APP;
1513         id.itemID = CSF_NV_DEVICELIST_ENTRIES_ID;
1514         id.subID = 0;
1516         /* Read the number of device list items from NV */
1517         stat = pNV->readItem(id, 0, sizeof(uint16_t), &numEntries);
1518         if(stat != NVINTF_SUCCESS)
1519         {
1520             numEntries = 0;
1521         }
1522     }
1523     return (numEntries);
1526 /*!
1527  Find the short address from a given extended address
1529  Public function defined in csf.h
1530  */
1531 uint16_t Csf_getDeviceShort(ApiMac_sAddrExt_t *pExtAddr)
1533     Llc_deviceListItem_t item;
1534     ApiMac_sAddr_t devAddr;
1535     uint16_t shortAddr = CSF_INVALID_SHORT_ADDR;
1537     devAddr.addrMode = ApiMac_addrType_extended;
1538     memcpy(&devAddr.addr.extAddr, pExtAddr, sizeof(ApiMac_sAddrExt_t));
1540     if(Csf_getDevice(&devAddr,&item))
1541     {
1542         shortAddr = item.devInfo.shortAddress;
1543     }
1545     return(shortAddr);
1548 /*!
1549  Find entry in device list
1551  Public function defined in csf.h
1552  */
1553 bool Csf_getDevice(ApiMac_sAddr_t *pDevAddr, Llc_deviceListItem_t *pItem)
1555     if((pNV != NULL) && (pItem != NULL))
1556     {
1557         uint16_t numEntries;
1559         numEntries = Csf_getNumDeviceListEntries();
1561         if(numEntries > 0)
1562         {
1563             NVINTF_itemID_t id;
1564             uint8_t stat;
1565             int subId = 0;
1566             int readItems = 0;
1568             /* Setup NV ID for the device list records */
1569             id.systemID = NVINTF_SYSID_APP;
1570             id.itemID = CSF_NV_DEVICELIST_ID;
1572             while((readItems < numEntries) && (subId
1573                                                < CSF_MAX_DEVICELIST_IDS))
1574             {
1575                 Llc_deviceListItem_t item;
1577                 id.subID = (uint16_t)subId;
1579                 /* Read Network Information from NV */
1580                 stat = pNV->readItem(id, 0, sizeof(Llc_deviceListItem_t),
1581                                      &item);
1582                 if(stat == NVINTF_SUCCESS)
1583                 {
1584                     if(((pDevAddr->addrMode == ApiMac_addrType_short)
1585                         && (pDevAddr->addr.shortAddr
1586                             == item.devInfo.shortAddress))
1587                        || ((pDevAddr->addrMode == ApiMac_addrType_extended)
1588                            && (memcmp(&pDevAddr->addr.extAddr,
1589                                       &item.devInfo.extAddress,
1590                                       (APIMAC_SADDR_EXT_LEN))
1591                                == 0)))
1592                     {
1593                         memcpy(pItem, &item, sizeof(Llc_deviceListItem_t));
1594                         return (true);
1595                     }
1596                     readItems++;
1597                 }
1598                 subId++;
1599             }
1600         }
1601     }
1603     return (false);
1606 /*!
1607  Find entry in device list
1609  Public function defined in csf.h
1610  */
1611 bool Csf_getDeviceItem(uint16_t devIndex, Llc_deviceListItem_t *pItem)
1613     if((pNV != NULL) && (pItem != NULL))
1614     {
1615         uint16_t numEntries;
1617         numEntries = Csf_getNumDeviceListEntries();
1619         if(numEntries > 0)
1620         {
1621             NVINTF_itemID_t id;
1622             uint8_t stat;
1623             int subId = 0;
1624             int readItems = 0;
1626             /* Setup NV ID for the device list records */
1627             id.systemID = NVINTF_SYSID_APP;
1628             id.itemID = CSF_NV_DEVICELIST_ID;
1630             while((readItems < numEntries) && (subId
1631                                                < CSF_MAX_DEVICELIST_IDS))
1632             {
1633                 Llc_deviceListItem_t item;
1635                 id.subID = (uint16_t)subId;
1637                 /* Read Network Information from NV */
1638                 stat = pNV->readItem(id, 0, sizeof(Llc_deviceListItem_t),
1639                                      &item);
1640                 if(stat == NVINTF_SUCCESS)
1641                 {
1642                     if(readItems == devIndex)
1643                     {
1644                         memcpy(pItem, &item, sizeof(Llc_deviceListItem_t));
1645                         return (true);
1646                     }
1647                     readItems++;
1648                 }
1649                 subId++;
1650             }
1651         }
1652     }
1654     return (false);
1657 /*!
1658  Csf implementation for memory allocation
1660  Public function defined in csf.h
1661  */
1662 void *Csf_malloc(uint16_t size)
1664 #if IS_HLOS
1665     return malloc(size);
1666 #else
1667     return ICall_malloc(size);
1668 #endif
1671 /*!
1672  Csf implementation for memory de-allocation
1674  Public function defined in csf.h
1675  */
1676 void Csf_free(void *ptr)
1678 #if IS_HLOS
1679     free(ptr);
1680 #else
1681     ICall_free(ptr);
1682 #endif
1685 /*!
1686  Update the Frame Counter
1688  Public function defined in csf.h
1689  */
1690 void Csf_updateFrameCounter(ApiMac_sAddr_t *pDevAddr, uint32_t frameCntr)
1692     if((pNV != NULL) && (pNV->writeItem != NULL))
1693     {
1694         if(pDevAddr == NULL)
1695         {
1696             /* Update this device's frame counter */
1697             if((frameCntr >=
1698                 (lastSavedCoordinatorFrameCounter + FRAME_COUNTER_SAVE_WINDOW)))
1699             {
1700                 NVINTF_itemID_t id;
1702                 /* Setup NV ID */
1703                 id.systemID = NVINTF_SYSID_APP;
1704                 id.itemID = CSF_NV_FRAMECOUNTER_ID;
1705                 id.subID = 0;
1707                 /* Write the NV item */
1708                 if(pNV->writeItem(id, sizeof(uint32_t), &frameCntr)
1709                                 == NVINTF_SUCCESS)
1710                 {
1711                     lastSavedCoordinatorFrameCounter = frameCntr;
1712                 }
1713             }
1714         }
1715         else
1716         {
1717             /* Child frame counter update */
1718             Llc_deviceListItem_t devItem;
1720             /* Is the device in our database? */
1721             if(Csf_getDevice(pDevAddr, &devItem))
1722             {
1723                 /*
1724                  Don't save every update, only save if the new frame
1725                  counter falls outside the save window.
1726                  */
1727                 if((devItem.rxFrameCounter + FRAME_COUNTER_SAVE_WINDOW)
1728                                 <= frameCntr)
1729                 {
1730                     /* Update the frame counter */
1731                     devItem.rxFrameCounter = frameCntr;
1732                     updateDeviceListItem(&devItem);
1733                 }
1734             }
1735         }
1736     }
1739 /*!
1740  Get the Frame Counter
1742  Public function defined in csf.h
1743  */
1744 bool Csf_getFrameCounter(ApiMac_sAddr_t *pDevAddr, uint32_t *pFrameCntr)
1746     /* Check for valid pointer */
1747     if(pFrameCntr != NULL)
1748     {
1749         /*
1750          A pDevAddr that is null means to get the frame counter for this device
1751          */
1752         if(pDevAddr == NULL)
1753         {
1754             if((pNV != NULL) && (pNV->readItem != NULL))
1755             {
1756                 NVINTF_itemID_t id;
1758                 /* Setup NV ID */
1759                 id.systemID = NVINTF_SYSID_APP;
1760                 id.itemID = CSF_NV_FRAMECOUNTER_ID;
1761                 id.subID = 0;
1763                 /* Read Network Information from NV */
1764                 if(pNV->readItem(id, 0, sizeof(uint32_t), pFrameCntr)
1765                                 == NVINTF_SUCCESS)
1766                 {
1767                     /* Set to the next window */
1768                     *pFrameCntr += FRAME_COUNTER_SAVE_WINDOW;
1769                     return(true);
1770                 }
1771                 else
1772                 {
1773                     /*
1774                      Wasn't found, so write 0, so the next time it will be
1775                      greater than 0
1776                      */
1777                     uint32_t fc = 0;
1779                     /* Setup NV ID */
1780                     id.systemID = NVINTF_SYSID_APP;
1781                     id.itemID = CSF_NV_FRAMECOUNTER_ID;
1782                     id.subID = 0;
1784                     /* Write the NV item */
1785                     pNV->writeItem(id, sizeof(uint32_t), &fc);
1786                 }
1787             }
1788         }
1790         *pFrameCntr = 0;
1791     }
1792     return (false);
1796 /*!
1797  Delete an entry from the device list
1799  Public function defined in csf.h
1800  */
1801 void Csf_removeDeviceListItem(ApiMac_sAddrExt_t *pAddr)
1803     if((pNV != NULL) && (pNV->deleteItem != NULL))
1804     {
1805         int index;
1807         /* Does the item exist? */
1808         index = findDeviceListIndex(pAddr);
1809         if(index != DEVICE_INDEX_NOT_FOUND)
1810         {
1811             uint8_t stat;
1812             NVINTF_itemID_t id;
1814             /* Setup NV ID for the device list record */
1815             id.systemID = NVINTF_SYSID_APP;
1816             id.itemID = CSF_NV_DEVICELIST_ID;
1817             id.subID = (uint16_t)index;
1819             stat = pNV->deleteItem(id);
1820             if(stat == NVINTF_SUCCESS)
1821             {
1822                 /* Update the number of entries */
1823                 uint16_t numEntries = Csf_getNumDeviceListEntries();
1824                 if(numEntries > 0)
1825                 {
1826                     numEntries--;
1827                     saveNumDeviceListEntries(numEntries);
1828                 }
1829             }
1830         }
1831     }
1834 /*!
1835  Assert Indication
1837  Public function defined in csf.h
1838  */
1839 void Csf_assertInd(uint8_t reason)
1841 #if IS_HLOS
1842     LOG_printf( LOG_ERROR, "Assert Reason: %d\n", (int)(reason) );
1843 #endif
1844 #if defined(MT_CSF)
1845     if((pNV != NULL) && (pNV->writeItem != NULL))
1846     {
1847         /* Attempt to save reason to read after reset */
1848         (void)pNV->writeItem(nvResetId, 1, &reason);
1849     }
1850 #endif
1853 /*!
1854  Clear all the NV Items
1856  Public function defined in csf.h
1857  */
1858 void Csf_clearAllNVItems(void)
1860     if((pNV != NULL) && (pNV->deleteItem != NULL))
1861     {
1862         NVINTF_itemID_t id;
1863         uint16_t entries;
1865         /* Clear Network Information */
1866         id.systemID = NVINTF_SYSID_APP;
1867         id.itemID = CSF_NV_NETWORK_INFO_ID;
1868         id.subID = 0;
1869         pNV->deleteItem(id);
1871         /* Clear the black list entries number */
1872         id.systemID = NVINTF_SYSID_APP;
1873         id.itemID = CSF_NV_BLACKLIST_ENTRIES_ID;
1874         id.subID = 0;
1875         pNV->deleteItem(id);
1877         /*
1878          Clear the black list entries.  Brute force through
1879          every possible subID, if it doesn't exist that's fine,
1880          it will fail in deleteItem.
1881          */
1882         id.systemID = NVINTF_SYSID_APP;
1883         id.itemID = CSF_NV_BLACKLIST_ID;
1884         for(entries = 0; entries < CSF_MAX_BLACKLIST_IDS; entries++)
1885         {
1886             id.subID = entries;
1887             pNV->deleteItem(id);
1888         }
1890         /* Clear the device list entries number */
1891         id.systemID = NVINTF_SYSID_APP;
1892         id.itemID = CSF_NV_DEVICELIST_ENTRIES_ID;
1893         id.subID = 0;
1894         pNV->deleteItem(id);
1896         /*
1897          Clear the device list entries.  Brute force through
1898          every possible subID, if it doesn't exist that's fine,
1899          it will fail in deleteItem.
1900          */
1901         id.systemID = NVINTF_SYSID_APP;
1902         id.itemID = CSF_NV_DEVICELIST_ID;
1903         for(entries = 0; entries < CSF_MAX_DEVICELIST_IDS; entries++)
1904         {
1905             id.subID = entries;
1906             pNV->deleteItem(id);
1907         }
1909         /* Clear the device tx frame counter */
1910         id.systemID = NVINTF_SYSID_APP;
1911         id.itemID = CSF_NV_FRAMECOUNTER_ID;
1912         id.subID = 0;
1913         pNV->deleteItem(id);
1914     }
1918 /*!
1919  Add an entry into the black list
1921  Public function defined in csf.h
1922  */
1923 bool Csf_addBlackListItem(ApiMac_sAddr_t *pAddr)
1925     bool retVal = false;
1927     if((pNV != NULL) && (pAddr != NULL)
1928        && (pAddr->addrMode != ApiMac_addrType_none))
1929     {
1930         if(findBlackListIndex(pAddr))
1931         {
1932             retVal = true;
1933         }
1934         else
1935         {
1936             uint8_t stat;
1937             NVINTF_itemID_t id;
1938             uint16_t numEntries = getNumBlackListEntries();
1940             /* Check the maximum size */
1941             if(numEntries < CSF_MAX_BLACKLIST_ENTRIES)
1942             {
1943                 /* Setup NV ID for the black list record */
1944                 id.systemID = NVINTF_SYSID_APP;
1945                 id.itemID = CSF_NV_BLACKLIST_ID;
1946                 id.subID = (uint16_t)findUnusedBlackListIndex();
1948                 /* write the black list record */
1949                 stat = pNV->writeItem(id, sizeof(ApiMac_sAddr_t), pAddr);
1950                 if(stat == NVINTF_SUCCESS)
1951                 {
1952                     /* Update the number of entries */
1953                     numEntries++;
1954                     saveNumBlackListEntries(numEntries);
1955                     retVal = true;
1956                 }
1957             }
1958         }
1959     }
1961     return (retVal);
1964 /*!
1965  Check if config timer is active
1967  Public function defined in csf.h
1968  */
1969 bool Csf_isConfigTimerActive(void)
1971     bool b;
1972 #if IS_HLOS
1973     int r;
1974     /*
1975      * If the timer is not valid (ie: handle=0)
1976      * the 'getRemain()' will return negative
1977      * which is the same as expired.
1978      */
1979     r = TIMER_CB_getRemain(configClkHandle);
1980     if( r < 0 ){
1981         b = false;
1982     } else {
1983         b = true;
1984     }
1985 #else
1986     b = (Timer_isActive(&configClkStruct));
1987 #endif
1988     return b;
1991 /*!
1992  Check if tracking timer is active
1994  Public function defined in csf.h
1995 */
1996 bool Csf_isTrackingTimerActive(void)
1998     bool b;
1999 #if IS_HLOS
2000     int r;
2001     r = TIMER_CB_getRemain(trackingClkHandle);
2002     if( r < 0 ){
2003         b = false;
2004     } else {
2005         b = true;
2006     }
2007 #else
2008     b = (Timer_isActive(&trackingClkStruct));
2009 #endif
2010     return b;
2013 /******************************************************************************
2014  Local Functions
2015  *****************************************************************************/
2017 /*!
2018  * @brief       Tracking timeout handler function.
2019  *
2020  * @param       a0 - ignored
2021  */
2022 static void processTackingTimeoutCallback(UArg a0)
2024     (void)a0; /* Parameter is not used */
2026     Util_setEvent(&Collector_events, COLLECTOR_TRACKING_TIMEOUT_EVT);
2028     /* Wake up the application thread when it waits for clock event */
2029     Semaphore_post(collectorSem);
2032 /*!
2033  * @brief       Join permit timeout handler function.
2034  *
2035  * @param       a0 - ignored
2036  */
2037 static void processJoinTimeoutCallback(UArg a0)
2039     (void)a0; /* Parameter is not used */
2041     Util_setEvent(&Cllc_events, CLLC_JOIN_EVT);
2043     /* Wake up the application thread when it waits for clock event */
2044     Semaphore_post(collectorSem);
2047 /*!
2048  * @brief       Config delay timeout handler function.
2049  *
2050  * @param       a0 - ignored
2051  */
2052 static void processConfigTimeoutCallback(UArg a0)
2054     (void)a0; /* Parameter is not used */
2056     Util_setEvent(&Collector_events, COLLECTOR_CONFIG_EVT);
2058     /* Wake up the application thread when it waits for clock event */
2059     Semaphore_post(collectorSem);
2062 /*!
2063  * @brief       Trickle timeout handler function for PA .
2064  *
2065  * @param       a0 - ignored
2066  */
2067 static void processPATrickleTimeoutCallback(UArg a0)
2069     (void)a0; /* Parameter is not used */
2071     Util_setEvent(&Cllc_events, CLLC_PA_EVT);
2073     /* Wake up the application thread when it waits for clock event */
2074     Semaphore_post(collectorSem);
2077 /*!
2078  * @brief       Trickle timeout handler function for PC.
2079  *
2080  * @param       a0 - ignored
2081  */
2082 static void processPCTrickleTimeoutCallback(UArg a0)
2084     (void)a0; /* Parameter is not used */
2086     Util_setEvent(&Cllc_events, CLLC_PC_EVT);
2088     /* Wake up the application thread when it waits for clock event */
2089     Semaphore_post(collectorSem);
2092 /*!
2093  * @brief       Key event handler function
2094  *
2095  * @param       keysPressed - Csf_keys that are pressed
2096  */
2097 static void processKeyChangeCallback(uint8_t keysPressed)
2099     Csf_keys = keysPressed;
2101     Csf_events |= CSF_KEY_EVENT;
2103     /* Wake up the application thread when it waits for clock event */
2104     Semaphore_post(collectorSem);
2107 /*!
2108  * @brief       Add an entry into the device list
2109  *
2110  * @param       pItem - pointer to the device list entry
2111  *
2112  * @return      true if added or already existed, false if problem
2113  */
2114 static bool addDeviceListItem(Llc_deviceListItem_t *pItem)
2116     bool retVal = false;
2118     if((pNV != NULL) && (pItem != NULL))
2119     {
2120         if(findDeviceListIndex(&pItem->devInfo.extAddress)
2121                         != DEVICE_INDEX_NOT_FOUND)
2122         {
2123             retVal = true;
2124         }
2125         else
2126         {
2127             uint8_t stat;
2128             NVINTF_itemID_t id;
2129             uint16_t numEntries = Csf_getNumDeviceListEntries();
2131             /* Check the maximum size */
2132             if(numEntries < CSF_MAX_DEVICELIST_ENTRIES)
2133             {
2134                 /* Setup NV ID for the device list record */
2135                 id.systemID = NVINTF_SYSID_APP;
2136                 id.itemID = CSF_NV_DEVICELIST_ID;
2137                 id.subID = (uint16_t)findUnusedDeviceListIndex();
2139                 /* write the device list record */
2140                 stat = pNV->writeItem(id, sizeof(Llc_deviceListItem_t), pItem);
2141                 if(stat == NVINTF_SUCCESS)
2142                 {
2143                     /* Update the number of entries */
2144                     numEntries++;
2145                     saveNumDeviceListEntries(numEntries);
2146                     retVal = true;
2147                 }
2148             }
2149         }
2150     }
2152     return (retVal);
2155 /*!
2156  * @brief       Update an entry in the device list
2157  *
2158  * @param       pItem - pointer to the device list entry
2159  */
2160 static void updateDeviceListItem(Llc_deviceListItem_t *pItem)
2162     if((pNV != NULL) && (pItem != NULL))
2163     {
2164         int idx;
2166         idx = findDeviceListIndex(&pItem->devInfo.extAddress);
2167         if(idx != DEVICE_INDEX_NOT_FOUND)
2168         {
2169             NVINTF_itemID_t id;
2171             /* Setup NV ID for the device list record */
2172             id.systemID = NVINTF_SYSID_APP;
2173             id.itemID = CSF_NV_DEVICELIST_ID;
2174             id.subID = (uint16_t)idx;
2176             /* write the device list record */
2177             pNV->writeItem(id, sizeof(Llc_deviceListItem_t), pItem);
2178         }
2179     }
2182 /*!
2183  * @brief       Find entry in device list
2184  *
2185  * @param       pAddr - address to of device to find
2186  *
2187  * @return      sub index into the device list, -1 (DEVICE_INDEX_NOT_FOUND)
2188  *              if not found
2189  */
2190 static int findDeviceListIndex(ApiMac_sAddrExt_t *pAddr)
2192     if((pNV != NULL) && (pAddr != NULL))
2193     {
2194         uint16_t numEntries;
2196         numEntries = Csf_getNumDeviceListEntries();
2198         if(numEntries > 0)
2199         {
2200             NVINTF_itemID_t id;
2201             uint8_t stat;
2202             int subId = 0;
2203             int readItems = 0;
2205             /* Setup NV ID for the device list records */
2206             id.systemID = NVINTF_SYSID_APP;
2207             id.itemID = CSF_NV_DEVICELIST_ID;
2209             while((readItems < numEntries) && (subId
2210                                                < CSF_MAX_DEVICELIST_IDS))
2211             {
2212                 Llc_deviceListItem_t item;
2214                 id.subID = (uint16_t)subId;
2216                 /* Read Network Information from NV */
2217                 stat = pNV->readItem(id, 0, sizeof(Llc_deviceListItem_t),
2218                                      &item);
2219                 if(stat == NVINTF_SUCCESS)
2220                 {
2221                     /* Is the address the same */
2222                     if(memcmp(pAddr, &item.devInfo.extAddress,
2223                               (APIMAC_SADDR_EXT_LEN))
2224                        == 0)
2225                     {
2226                         return (subId);
2227                     }
2228                     readItems++;
2229                 }
2230                 subId++;
2231             }
2232         }
2233     }
2235     return (DEVICE_INDEX_NOT_FOUND);
2238 /*!
2239  * @brief       Find an unused device list index
2240  *
2241  * @return      index that is not in use
2242  */
2243 static int findUnusedDeviceListIndex(void)
2245     int subId = 0;
2247     if(pNV != NULL)
2248     {
2249         uint16_t numEntries;
2251         numEntries = Csf_getNumDeviceListEntries();
2253         if(numEntries > 0)
2254         {
2255             NVINTF_itemID_t id;
2257             int readItems = 0;
2258             /* Setup NV ID for the device list records */
2259             id.systemID = NVINTF_SYSID_APP;
2260             id.itemID = CSF_NV_DEVICELIST_ID;
2262             while((readItems < numEntries) && (subId
2263                                                < CSF_MAX_DEVICELIST_IDS))
2264             {
2265                 Llc_deviceListItem_t item;
2266                 uint8_t stat;
2268                 id.subID = (uint16_t)subId;
2270                 /* Read Network Information from NV */
2271                 stat = pNV->readItem(id, 0, sizeof(Llc_deviceListItem_t),
2272                                      &item);
2273                 if(stat == NVINTF_NOTFOUND)
2274                 {
2275                     /* Use this sub id */
2276                     break;
2277                 }
2278                 else if(stat == NVINTF_SUCCESS)
2279                 {
2280                     readItems++;
2281                 }
2282                 subId++;
2283             }
2284         }
2285     }
2287     return (subId);
2290 /*!
2291  * @brief       Read the number of device list items stored
2292  *
2293  * @param       numEntries - number of entries in the device list
2294  */
2295 static void saveNumDeviceListEntries(uint16_t numEntries)
2297     if(pNV != NULL)
2298     {
2299         NVINTF_itemID_t id;
2301         /* Setup NV ID for the number of entries in the device list */
2302         id.systemID = NVINTF_SYSID_APP;
2303         id.itemID = CSF_NV_DEVICELIST_ENTRIES_ID;
2304         id.subID = 0;
2306         /* Read the number of device list items from NV */
2307         pNV->writeItem(id, sizeof(uint16_t), &numEntries);
2308     }
2311 /*!
2312  * @brief       Find entry in black list
2313  *
2314  * @param       pAddr - address to add into the black list
2315  *
2316  * @return      sub index into the blacklist, -1 if not found
2317  */
2318 static int findBlackListIndex(ApiMac_sAddr_t *pAddr)
2320     if((pNV != NULL) && (pAddr != NULL)
2321        && (pAddr->addrMode != ApiMac_addrType_none))
2322     {
2323         uint16_t numEntries;
2325         numEntries = getNumBlackListEntries();
2327         if(numEntries > 0)
2328         {
2329             NVINTF_itemID_t id;
2330             uint8_t stat;
2331             int subId = 0;
2332             int readItems = 0;
2334             /* Setup NV ID for the black list records */
2335             id.systemID = NVINTF_SYSID_APP;
2336             id.itemID = CSF_NV_BLACKLIST_ID;
2338             while((readItems < numEntries) && (subId < CSF_MAX_BLACKLIST_IDS))
2339             {
2340                 ApiMac_sAddr_t item;
2342                 id.subID = (uint16_t)subId;
2344                 /* Read Network Information from NV */
2345                 stat = pNV->readItem(id, 0, sizeof(ApiMac_sAddr_t), &item);
2346                 if(stat == NVINTF_SUCCESS)
2347                 {
2348                     if(pAddr->addrMode == item.addrMode)
2349                     {
2350                         /* Is the address the same */
2351                         if(((pAddr->addrMode == ApiMac_addrType_short)
2352                             && (pAddr->addr.shortAddr == item.addr.shortAddr))
2353                            || ((pAddr->addrMode == ApiMac_addrType_extended)
2354                                && (memcmp(&pAddr->addr.extAddr,
2355                                           &item.addr.extAddr,
2356                                           APIMAC_SADDR_EXT_LEN)
2357                                    == 0)))
2358                         {
2359                             return (subId);
2360                         }
2361                     }
2362                     readItems++;
2363                 }
2364                 subId++;
2365             }
2366         }
2367     }
2369     return (-1);
2372 /*!
2373  * @brief       Find an unused blacklist index
2374  *
2375  * @return      index that is not in use
2376  */
2377 static int findUnusedBlackListIndex(void)
2379     int subId = 0;
2381     if(pNV != NULL)
2382     {
2383         uint16_t numEntries;
2385         numEntries = getNumBlackListEntries();
2387         if(numEntries > 0)
2388         {
2389             NVINTF_itemID_t id;
2391             int readItems = 0;
2392             /* Setup NV ID for the black list records */
2393             id.systemID = NVINTF_SYSID_APP;
2394             id.itemID = CSF_NV_BLACKLIST_ID;
2396             while((readItems < numEntries) && (subId < CSF_MAX_BLACKLIST_IDS))
2397             {
2398                 ApiMac_sAddr_t item;
2399                 uint8_t stat;
2401                 id.subID = (uint16_t)subId;
2403                 /* Read Network Information from NV */
2404                 stat = pNV->readItem(id, 0, sizeof(ApiMac_sAddr_t), &item);
2405                 if(stat == NVINTF_NOTFOUND)
2406                 {
2407                     /* Use this sub id */
2408                     break;
2409                 }
2410                 else if(stat == NVINTF_SUCCESS)
2411                 {
2412                     readItems++;
2413                 }
2414                 subId++;
2415             }
2416         }
2417     }
2419     return (subId);
2422 /*!
2423  * @brief       Read the number of black list items stored
2424  *
2425  * @return      number of entries in the black list
2426  */
2427 static uint16_t getNumBlackListEntries(void)
2429     uint16_t numEntries = 0;
2431     if(pNV != NULL)
2432     {
2433         NVINTF_itemID_t id;
2434         uint8_t stat;
2436         /* Setup NV ID for the number of entries in the black list */
2437         id.systemID = NVINTF_SYSID_APP;
2438         id.itemID = CSF_NV_BLACKLIST_ENTRIES_ID;
2439         id.subID = 0;
2441         /* Read the number of black list items from NV */
2442         stat = pNV->readItem(id, 0, sizeof(uint16_t), &numEntries);
2443         if(stat != NVINTF_SUCCESS)
2444         {
2445             numEntries = 0;
2446         }
2447     }
2448     return (numEntries);
2451 /*!
2452  * @brief       Read the number of black list items stored
2453  *
2454  * @param       numEntries - number of entries in the black list
2455  */
2456 static void saveNumBlackListEntries(uint16_t numEntries)
2458     if(pNV != NULL)
2459     {
2460         NVINTF_itemID_t id;
2462         /* Setup NV ID for the number of entries in the black list */
2463         id.systemID = NVINTF_SYSID_APP;
2464         id.itemID = CSF_NV_BLACKLIST_ENTRIES_ID;
2465         id.subID = 0;
2467         /* Read the number of black list items from NV */
2468         pNV->writeItem(id, sizeof(uint16_t), &numEntries);
2469     }
2472 /*!
2473  * @brief       Delete an address from the black list
2474  *
2475  * @param       pAddr - address to remove from black list.
2476  */
2477 void removeBlackListItem(ApiMac_sAddr_t *pAddr)
2479     if(pNV != NULL)
2480     {
2481         int index;
2483         /* Does the item exist? */
2484         index = findBlackListIndex(pAddr);
2485         if(index > 0)
2486         {
2487             uint8_t stat;
2488             NVINTF_itemID_t id;
2490             /* Setup NV ID for the black list record */
2491             id.systemID = NVINTF_SYSID_APP;
2492             id.itemID = CSF_NV_BLACKLIST_ID;
2493             id.subID = (uint16_t)index;
2495             stat = pNV->deleteItem(id);
2496             if(stat == NVINTF_SUCCESS)
2497             {
2498                 /* Update the number of entries */
2499                 uint16_t numEntries = getNumBlackListEntries();
2500                 if(numEntries > 0)
2501                 {
2502                     numEntries--;
2503                     saveNumBlackListEntries(numEntries);
2504                 }
2505             }
2506         }
2507     }
2510 /*!
2511  * @brief       This is an example function on how to remove a device
2512  *              from this network.
2513  *
2514  * @param       addr - device address
2515  *
2516  * @return      true if found, false if not
2517  */
2518 static bool removeDevice(ApiMac_sAddr_t addr)
2520     LOG_printf(LOG_ERROR, "removing device 0x%04x\n", addr.addr.shortAddr);
2522     LOG_printf(LOG_ERROR, "sending Disassociation request to device 0x%04x\n", addr.addr.shortAddr);
2524     /* Send a disassociate to the device */
2525     Cllc_sendDisassociationRequest(addr.addr.shortAddr,
2526                                      false);
2528     return 1;
2531 #if defined(TEST_REMOVE_DEVICE)
2532 /*!
2533  * @brief       This is an example function on how to remove a device
2534  *              from this network.
2535  */
2536 static void removeTheFirstDevice(void)
2538     if(pNV != NULL)
2539     {
2540         uint16_t numEntries;
2542         numEntries = Csf_getNumDeviceListEntries();
2544         if(numEntries > 0)
2545         {
2546             NVINTF_itemID_t id;
2547             uint16_t subId = 0;
2549             /* Setup NV ID for the device list records */
2550             id.systemID = NVINTF_SYSID_APP;
2551             id.itemID = CSF_NV_DEVICELIST_ID;
2553             while(subId < CSF_MAX_DEVICELIST_IDS)
2554             {
2555                 Llc_deviceListItem_t item;
2556                 uint8_t stat;
2558                 id.subID = (uint16_t)subId;
2560                 /* Read Network Information from NV */
2561                 stat = pNV->readItem(id, 0, sizeof(Llc_deviceListItem_t),
2562                                      &item);
2563                 if(stat == NVINTF_SUCCESS)
2564                 {
2565                     /* Found the first device in the list */
2566                     ApiMac_sAddr_t addr;
2568                     /* Send a disassociate to the device */
2569                     Cllc_sendDisassociationRequest(item.devInfo.shortAddress,
2570                                                    item.capInfo.rxOnWhenIdle);
2571                     /* Remove device from the NV list */
2572                     Cllc_removeDevice(&item.devInfo.extAddress);
2574                     /* Remove it from the Device list */
2575                     Csf_removeDeviceListItem(&item.devInfo.extAddress);
2577                     /* Add the device to the black list so it can't join again */
2578                     addr.addrMode = ApiMac_addrType_extended;
2579                     memcpy(&addr.addr.extAddr, &item.devInfo.extAddress,
2580                            (APIMAC_SADDR_EXT_LEN));
2581                     Csf_addBlackListItem(&addr);
2582                     break;
2583                 }
2584                 subId++;
2585             }
2586         }
2587     }
2589 #endif
2591 #if !IS_HLOS
2592 /*!
2593  * @brief       Retrieve the first device's short address
2594  *
2595  * @return      short address or 0xFFFF if not found
2596  */
2597 static uint16_t getTheFirstDevice(void)
2599     uint16_t found = CSF_INVALID_SHORT_ADDR;
2600     if(pNV != NULL)
2601     {
2602         uint16_t numEntries;
2604         numEntries = Csf_getNumDeviceListEntries();
2606         if(numEntries > 0)
2607         {
2608             NVINTF_itemID_t id;
2610             /* Setup NV ID for the device list records */
2611             id.systemID = NVINTF_SYSID_APP;
2612             id.itemID = CSF_NV_DEVICELIST_ID;
2613             id.subID = 0;
2615             while(id.subID < CSF_MAX_DEVICELIST_IDS)
2616             {
2617                 Llc_deviceListItem_t item;
2618                 uint8_t stat;
2620                 /* Read Network Information from NV */
2621                 stat = pNV->readItem(id, 0, sizeof(Llc_deviceListItem_t),
2622                                      &item);
2623                 if(stat == NVINTF_SUCCESS)
2624                 {
2625                     found = item.devInfo.shortAddress;
2626                     break;
2627                 }
2628                 id.subID++;
2629             }
2630         }
2631     }
2632     return(found);
2634 #endif
2636 /*!
2637  * @brief       Retrieve the first device's short address
2638  *
2639  * @return      short address or 0xFFFF if not found
2640  */
2641 void Csf_freeDeviceInformationList(size_t n, Csf_deviceInformation_t *p)
2643     (void)(n); /* not used */
2644     if(p)
2645     {
2646         free((void *)(p));
2647     }
2650 /*!
2651  The appSrv calls this function to get the list of connected
2652  devices
2654  Public function defined in csf_linux.h
2655  */
2656 int Csf_getDeviceInformationList(Csf_deviceInformation_t **ppDeviceInfo)
2658     Csf_deviceInformation_t *pThis;
2659     Llc_deviceListItem_t    tmp;
2660     uint16_t actual;
2661     uint16_t subId;
2662     int n;
2663     NVINTF_itemID_t id;
2665     /* get number of connected devices */
2666     n = Csf_getNumDeviceListEntries();
2667     /* initialize device list pointer */
2669     pThis = calloc(n+1, sizeof(*pThis));
2670     *ppDeviceInfo = pThis;
2671     if(pThis == NULL)
2672     {
2673         LOG_printf(LOG_ERROR, "No memory for device list\n");
2674         return 0;
2675     }
2677     /* Setup NV ID for the device list records */
2678     id.systemID = NVINTF_SYSID_APP;
2679     id.itemID = CSF_NV_DEVICELIST_ID;
2680     subId = 0;
2681     actual = 0;
2682     /* Read the Entries */
2683     while((subId < CSF_MAX_DEVICELIST_IDS) && (actual < n))
2684     {
2685         uint8_t stat;
2687         id.subID = subId;
2688         /* Read Device Information from NV */
2689         stat = pNV->readItem(id, 0,
2690                              sizeof(tmp),
2691                              &tmp);
2692         if(stat == NVINTF_SUCCESS)
2693         {
2694             pThis->devInfo = tmp.devInfo;
2695             pThis->capInfo = tmp.capInfo;
2696             actual++;
2697             pThis++;
2698         }
2699         subId++;
2700      }
2702     /* return actual number of devices connected */
2703     return actual;
2706 void CSF_LINUX_USE_THESE_FUNCTIONS(void);
2707 void CSF_LINUX_USE_THESE_FUNCTIONS(void)
2709     /* (void)started; */
2710 #if defined(TEST_REMOVE_DEVICE)
2711     (void)removeTheFirstDevice;
2712 #endif
2713     (void)removeBlackListItem;
2714     (void)processKeyChangeCallback;
2715     (void)permitJoining;
2718 const char *CSF_cllc_statename(Cllc_states_t s)
2720     const char *cp;
2721     switch(s)
2722     {
2723     default:
2724         cp = "unknown";
2725         break;
2726     case Cllc_states_initWaiting:
2727         cp = "initWaiting";
2728         break;
2729     case Cllc_states_startingCoordinator:
2730         cp = "startingCoordinator";
2731         break;
2732     case Cllc_states_initRestoringCoordinator:
2733         cp = "initRestoringCoordinator";
2734         break;
2735     case Cllc_states_started:
2736         cp = "started";
2737         break;
2738     case Cllc_states_restored:
2739         cp = "restored";
2740         break;
2741     case Cllc_states_joiningAllowed:
2742         cp = "joiningAllowed";
2743         break;
2744     case Cllc_states_joiningNotAllowed:
2745         cp = "joiningNotAllowed";
2746         break;
2747     }
2748     return cp;
2751 /*!
2752  The appsrv module calls this function to send config request
2753  to a device over the air
2755  Public function defined in csf_linux.h
2756  */
2757 extern uint8_t Csf_sendConfigRequest( ApiMac_sAddr_t *pDstAddr,
2758                 uint16_t frameControl,
2759                 uint32_t reportingInterval,
2760                 uint32_t pollingInterval)
2762     return Collector_sendConfigRequest( pDstAddr,
2763                 frameControl,
2764                 reportingInterval,
2765                 pollingInterval);
2768 /*!
2769  The appsrv module calls this function to send a led toggle request
2770  to a device over the air
2772  Public function defined in csf_linux.h
2773  */
2774 extern uint8_t Csf_sendToggleLedRequest(
2775                 ApiMac_sAddr_t *pDstAddr)
2777     return Collector_sendToggleLedRequest(pDstAddr);
2780 /*
2781  * Public function in csf_linux.h
2782  * Gateway front end uses this to get the current state.
2783  */
2784 Cllc_states_t Csf_getCllcState(void)
2786     return savedCllcState;
2789 /*
2790  *  ========================================
2791  *  Texas Instruments Micro Controller Style
2792  *  ========================================
2793  *  Local Variables:
2794  *  mode: c
2795  *  c-file-style: "bsd"
2796  *  tab-width: 4
2797  *  c-basic-offset: 4
2798  *  indent-tabs-mode: nil
2799  *  End:
2800  *  vim:set  filetype=c tabstop=4 shiftwidth=4 expandtab=true
2801  */