ZDNwkMgr.c 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063
  1. /**************************************************************************************************
  2. Filename: ZDNwkMgr.c
  3. Revised: $Date: 2007-10-17 15:38:45 -0700 (Wed, 17 Oct 2007) $
  4. Revision: $Revision: 15716 $
  5. Description: The ZigBee Network Manager.
  6. Copyright 2007 Texas Instruments Incorporated. All rights reserved.
  7. IMPORTANT: Your use of this Software is limited to those specific rights
  8. granted under the terms of a software license agreement between the user
  9. who downloaded the software, his/her employer (which must be your employer)
  10. and Texas Instruments Incorporated (the "License"). You may not use this
  11. Software unless you agree to abide by the terms of the License. The License
  12. limits your use, and you acknowledge, that the Software may not be modified,
  13. copied or distributed unless embedded on a Texas Instruments microcontroller
  14. or used solely and exclusively in conjunction with a Texas Instruments radio
  15. frequency transceiver, which is integrated into your product. Other than for
  16. the foregoing purpose, you may not use, reproduce, copy, prepare derivative
  17. works of, modify, distribute, perform, display or sell this Software and/or
  18. its documentation for any purpose.
  19. YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
  20. PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
  21. INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
  22. NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
  23. TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
  24. NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
  25. LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
  26. INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
  27. OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
  28. OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
  29. (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
  30. Should you have any questions regarding your right to use this Software,
  31. contact Texas Instruments Incorporated at www.TI.com.
  32. **************************************************************************************************/
  33. #ifdef __cplusplus
  34. extern "C"
  35. {
  36. #endif
  37. /******************************************************************************
  38. * INCLUDES
  39. */
  40. #include "ZComdef.h"
  41. #include "nwk_util.h"
  42. #include "ZDApp.h"
  43. #include "ZDObject.h"
  44. #include "ZGlobals.h"
  45. #include "ZDNwkMgr.h"
  46. #if defined( MT_ZDO_FUNC )
  47. #include "MT_ZDO.h"
  48. #endif
  49. #if defined ( LCD_SUPPORTED )
  50. #include "OnBoard.h"
  51. #endif
  52. /* HAL */
  53. #include "hal_lcd.h"
  54. /******************************************************************************
  55. * CONSTANTS
  56. */
  57. #define ONE_MINUTE 60000 // 1(m) * 60(s) * 1000(ms)
  58. #if defined ( LCD_SUPPORTED )
  59. const char NwkMgrStr_1[] = "NM-fail not hi";
  60. const char NwkMgrStr_2[] = "NM-cur<last fail";
  61. const char NwkMgrStr_3[] = "NM-energy too hi";
  62. const char NwkMgrStr_4[] = "NM-energy not up";
  63. #endif
  64. /******************************************************************************
  65. * TYPEDEFS
  66. */
  67. /*********************************************************************
  68. * GLOBAL VARIABLES
  69. */
  70. // Task ID for internal task/event processing. This variable will be
  71. // received when ZDNwkMgr_Init() is called.
  72. uint8 ZDNwkMgr_TaskID = 0;
  73. /******************************************************************************
  74. * LOCAL VARIABLES
  75. */
  76. // Frequency Agility variables
  77. uint8 ZDNwkMgr_MgmtNwkUpdateNotifyTransSeq = 0;
  78. zAddrType_t ZDNwkMgr_MgmtNwkUpdateNotifyAddr;
  79. uint16 ZDNwkMgr_UpdateNotifyTimer = 0;
  80. uint8 ZDNwkMgr_NumUpdateNotifySent = 0;
  81. uint8 ZDNwkMgr_WaitingForNotifyConfirm = FALSE;
  82. uint16 ZDNwkMgr_TotalTransmissions;
  83. uint16 ZDNwkMgr_TxFailures;
  84. ZDO_MgmtNwkUpdateReq_t ZDNwkMgr_MgmtNwkUpdateReq;
  85. #if defined ( NWK_MANAGER )
  86. uint16 ZDNwkMgr_UpdateRequestTimer = 0;
  87. uint8 ZDNwkMgr_LastChannelEnergy = 0;
  88. uint16 ZDNwkMgr_LastChannelFailureRate = 0;
  89. #endif // NWK_MANAGER
  90. uint8 ZDNwkMgr_NewChannel;
  91. // PAN ID Conflict variables
  92. #if defined ( NWK_MANAGER )
  93. uint8 ZDNwkMgr_PanIdUpdateInProgress = FALSE;
  94. #endif // NWK_MANAGER
  95. /*********************************************************************
  96. * GLOBAL FUNCTIONS
  97. */
  98. // Freguency Agility functions
  99. void (*pZDNwkMgr_ReportChannelInterference)( NLME_ChanInterference_t *chanInterference ) = NULL;
  100. void (*pZDNwkMgr_ProcessDataConfirm)( afDataConfirm_t *afDataConfirm ) = NULL;
  101. void (*pZDNwkMgr_EDScanConfirmCB)( NLME_EDScanConfirm_t *EDScanConfirm ) = NULL;
  102. // PAN ID Conflict functions
  103. void (*pZDNwkMgr_NetworkReportCB)( ZDNwkMgr_NetworkReport_t *pReport ) = NULL;
  104. void (*pZDNwkMgr_NetworkUpdateCB)( ZDNwkMgr_NetworkUpdate_t *pUpdate ) = NULL;
  105. /******************************************************************************
  106. * LOCAL FUNCTIONS
  107. */
  108. void ZDNwkMgr_ProcessServerDiscRsp( zdoIncomingMsg_t *inMsg );
  109. void ZDNwkMgr_SetNwkManagerAddr( uint16 nwkManagerAddr );
  110. // Frequency Agility functions
  111. static void ZDNwkMgr_ProcessMsgCBs( zdoIncomingMsg_t *inMsg );
  112. static void ZDNwkMgr_ProcessMgmtNwkUpdateReq( zdoIncomingMsg_t *inMsg );
  113. static void ZDNwkMgr_ProcessChannelInterference( ZDNwkMgr_ChanInterference_t *pChanInterference );
  114. static void ZDNwkMgr_ProcessEDScanConfirm( ZDNwkMgr_EDScanConfirm_t *pEDScanConfirm );
  115. static void ZDNwkMgr_CheckForChannelInterference( ZDNwkMgr_EDScanConfirm_t *pEDScanConfirm );
  116. static void ZDNwkMgr_BuildAndSendUpdateNotify( uint8 TransSeq, zAddrType_t *dstAddr,
  117. uint16 totalTransmissions, uint16 txFailures,
  118. ZDNwkMgr_EDScanConfirm_t *pEDScanConfirm, uint8 txOptions );
  119. void ZDNwkMgr_EDScanConfirmCB( NLME_EDScanConfirm_t *EDScanConfirm );
  120. void ZDNwkMgr_ProcessDataConfirm( afDataConfirm_t *afDataConfirm );
  121. void ZDNwkMgr_ReportChannelInterference( NLME_ChanInterference_t *chanInterference );
  122. #if defined ( NWK_MANAGER )
  123. static void ZDNwkMgr_ProcessMgmtNwkUpdateNotify( zdoIncomingMsg_t *inMsg );
  124. static void ZDNwkMgr_CheckForChannelChange( ZDO_MgmtNwkUpdateNotify_t *pNotify );
  125. #endif // NWK_MANAGER
  126. // PAN ID Conflict functions
  127. #if defined ( NWK_MANAGER )
  128. void ZDNwkMgr_NetworkReportCB( ZDNwkMgr_NetworkReport_t *pReport );
  129. void ZDNwkMgr_NetworkUpdateCB( ZDNwkMgr_NetworkUpdate_t *pUpdate );
  130. void ZDNwkMgr_ProcessNetworkReport( ZDNwkMgr_NetworkReport_t *pNetworkReport );
  131. void ZDNwkMgr_ProcessNetworkUpdate( ZDNwkMgr_NetworkUpdate_t *pNetworkUpdate );
  132. #endif // NWK_MANAGER
  133. /*********************************************************************
  134. * @fn ZDNwkMgr_Init
  135. *
  136. * @brief Initialization function for the Network Manager Task.
  137. * This is called during initialization and should contain
  138. * any application specific initialization (ie. hardware
  139. * initialization/setup, table initialization, power up
  140. * notificaiton ... ).
  141. *
  142. * @param task_id - the ID assigned by OSAL. This ID should be
  143. * used to send messages and set timers.
  144. *
  145. * @return none
  146. */
  147. void ZDNwkMgr_Init( byte task_id )
  148. {
  149. // Save the task ID
  150. ZDNwkMgr_TaskID = task_id;
  151. ZDO_RegisterForZDOMsg( ZDNwkMgr_TaskID, Server_Discovery_rsp );
  152. // Frequecy Agility initialization
  153. ZDO_RegisterForZDOMsg( ZDNwkMgr_TaskID, Mgmt_NWK_Update_req );
  154. #if defined ( NWK_MANAGER )
  155. ZDO_RegisterForZDOMsg( ZDNwkMgr_TaskID, Mgmt_NWK_Update_notify );
  156. #endif // NWK_MANAGER
  157. pZDNwkMgr_EDScanConfirmCB = ZDNwkMgr_EDScanConfirmCB;
  158. pZDNwkMgr_ProcessDataConfirm = ZDNwkMgr_ProcessDataConfirm;
  159. pZDNwkMgr_ReportChannelInterference = ZDNwkMgr_ReportChannelInterference;
  160. // PAN ID Conflict initialization
  161. #if defined ( NWK_MANAGER )
  162. pZDNwkMgr_NetworkReportCB = ZDNwkMgr_NetworkReportCB;
  163. pZDNwkMgr_NetworkUpdateCB = ZDNwkMgr_NetworkUpdateCB;
  164. #endif // NWK_MANAGER
  165. ZDNwkMgr_MgmtNwkUpdateNotifyAddr.addrMode = Addr16Bit;
  166. ZDNwkMgr_MgmtNwkUpdateNotifyAddr.addr.shortAddr = INVALID_NODE_ADDR;
  167. }
  168. /*********************************************************************
  169. * @fn ZDNwkMgr_event_loop
  170. *
  171. * @brief Main event loop for the Network Manager task. This function
  172. * is called to process all events for the task. Events
  173. * include timers, messages and any other user defined events.
  174. *
  175. * @param task_id - The OSAL assigned task ID.
  176. * @param events - events to process. This is a bit map and can
  177. * contain more than one event.
  178. *
  179. * @return none
  180. */
  181. UINT16 ZDNwkMgr_event_loop( byte task_id, UINT16 events )
  182. {
  183. osal_event_hdr_t *msgPtr;
  184. (void)task_id; // Intentionally unreferenced parameter
  185. if ( events & SYS_EVENT_MSG )
  186. {
  187. msgPtr = (osal_event_hdr_t *)osal_msg_receive( ZDNwkMgr_TaskID );
  188. while ( msgPtr )
  189. {
  190. switch ( msgPtr->event )
  191. {
  192. case ZDO_CB_MSG:
  193. // ZDO sends the message that we registered for
  194. ZDNwkMgr_ProcessMsgCBs( (zdoIncomingMsg_t *)msgPtr );
  195. break;
  196. case NM_CHANNEL_INTERFERE:
  197. // NWK layer sends the message when it detectes Channel Interference
  198. ZDNwkMgr_ProcessChannelInterference( (ZDNwkMgr_ChanInterference_t *)msgPtr );
  199. break;
  200. case NM_ED_SCAN_CONFIRM:
  201. // NWK layer sends the message when it receives an ED scan confirmation
  202. ZDNwkMgr_ProcessEDScanConfirm( (ZDNwkMgr_EDScanConfirm_t *)msgPtr );
  203. break;
  204. #if defined ( NWK_MANAGER )
  205. case ZDO_NETWORK_REPORT:
  206. // NWK layer sends this message when it receives a Network Report message
  207. ZDNwkMgr_ProcessNetworkReport( (ZDNwkMgr_NetworkReport_t *)msgPtr );
  208. break;
  209. case ZDO_NETWORK_UPDATE:
  210. // NKW layer sends this message when it receives a Network Update message
  211. ZDNwkMgr_ProcessNetworkUpdate( (ZDNwkMgr_NetworkUpdate_t *)msgPtr );
  212. break;
  213. #endif // NWK_MANAGER
  214. default:
  215. break;
  216. }
  217. // Release the memory
  218. osal_msg_deallocate( (uint8 *)msgPtr );
  219. // Next
  220. msgPtr = (osal_event_hdr_t *)osal_msg_receive( ZDNwkMgr_TaskID );
  221. }
  222. // Return unprocessed events
  223. return (events ^ SYS_EVENT_MSG);
  224. }
  225. if ( events & ZDNWKMGR_CHANNEL_CHANGE_EVT )
  226. {
  227. // Switch channel
  228. _NIB.nwkLogicalChannel = ZDNwkMgr_NewChannel;
  229. ZMacSetReq( ZMacChannel, &ZDNwkMgr_NewChannel );
  230. // Our Channel has been changed -- notify to save info into NV
  231. ZDApp_NwkStateUpdateCB();
  232. // Reset the total transmit count and the transmit failure counters
  233. _NIB.nwkTotalTransmissions = 0;
  234. nwkTransmissionFailures( TRUE );
  235. return ( events ^ ZDNWKMGR_CHANNEL_CHANGE_EVT );
  236. }
  237. if ( events & ZDNWKMGR_UPDATE_NOTIFY_EVT )
  238. {
  239. // Update the Update Notify timer
  240. if ( ZDNwkMgr_UpdateNotifyTimer > 0 )
  241. {
  242. ZDNwkMgr_UpdateNotifyTimer--;
  243. osal_start_timerEx( ZDNwkMgr_TaskID, ZDNWKMGR_UPDATE_NOTIFY_EVT, ONE_MINUTE );
  244. }
  245. else
  246. {
  247. ZDNwkMgr_NumUpdateNotifySent = 0;
  248. }
  249. return ( events ^ ZDNWKMGR_UPDATE_NOTIFY_EVT );
  250. }
  251. #if defined ( NWK_MANAGER )
  252. if ( events & ZDNWKMGR_UPDATE_REQUEST_EVT )
  253. {
  254. // Update the Update Request timer
  255. if ( ZDNwkMgr_UpdateRequestTimer > 0 )
  256. {
  257. ZDNwkMgr_UpdateRequestTimer--;
  258. osal_start_timerEx( ZDNwkMgr_TaskID, ZDNWKMGR_UPDATE_REQUEST_EVT, ONE_MINUTE );
  259. }
  260. return ( events ^ ZDNWKMGR_UPDATE_REQUEST_EVT );
  261. }
  262. #endif // NWK_MANAGER
  263. if ( events & ZDNWKMGR_SCAN_REQUEST_EVT )
  264. {
  265. if ( ZDNwkMgr_MgmtNwkUpdateReq.scanCount > 0 )
  266. {
  267. if ( NLME_EDScanRequest( ZDNwkMgr_MgmtNwkUpdateReq.channelMask,
  268. ZDNwkMgr_MgmtNwkUpdateReq.scanDuration ) == ZSuccess )
  269. {
  270. ZDNwkMgr_MgmtNwkUpdateReq.scanCount--;
  271. }
  272. }
  273. return ( events ^ ZDNWKMGR_SCAN_REQUEST_EVT );
  274. }
  275. // Discard or make more handlers
  276. return 0;
  277. }
  278. /*********************************************************************
  279. * @fn ZDNwkMgr_ProcessMsgCBs
  280. *
  281. * @brief Process the incoming messages.
  282. *
  283. * @param msgPtr - message to process
  284. *
  285. * @return TRUE if message to be freed. FALSE otherwise.
  286. */
  287. static void ZDNwkMgr_ProcessMsgCBs( zdoIncomingMsg_t *inMsg )
  288. {
  289. switch ( inMsg->clusterID )
  290. {
  291. case Mgmt_NWK_Update_req:
  292. ZDNwkMgr_ProcessMgmtNwkUpdateReq( inMsg );
  293. break;
  294. #if defined ( NWK_MANAGER )
  295. case Mgmt_NWK_Update_notify:
  296. ZDNwkMgr_ProcessMgmtNwkUpdateNotify( inMsg );
  297. break;
  298. #endif // NWK_MANAGER
  299. case Server_Discovery_rsp:
  300. ZDNwkMgr_ProcessServerDiscRsp( inMsg );
  301. break;
  302. default:
  303. // Unknown message
  304. break;
  305. }
  306. }
  307. /*********************************************************************
  308. * Frequency Agility Routines
  309. */
  310. #if defined ( NWK_MANAGER )
  311. /*********************************************************************
  312. * @fn ZDNwkMgr_ProcessMgmtNwkUpdateNotify
  313. *
  314. * @brief This function processes the incoming Management
  315. * Network Update notify.
  316. *
  317. * @param pUpdateNotify - notify message
  318. *
  319. * @return TRUE if message to be freed. FALSE otherwise.
  320. */
  321. static void ZDNwkMgr_ProcessMgmtNwkUpdateNotify( zdoIncomingMsg_t *inMsg )
  322. {
  323. if ( zgNwkMgrMode == ZDNWKMGR_ENABLE )
  324. {
  325. ZDO_MgmtNwkUpdateNotify_t *pNotify = ZDO_ParseMgmtNwkUpdateNotify( inMsg );
  326. if ( pNotify )
  327. {
  328. ZDNwkMgr_CheckForChannelChange( pNotify );
  329. osal_mem_free( pNotify );
  330. }
  331. }
  332. }
  333. /*********************************************************************
  334. * @fn ZDNwkMgr_CheckForChannelChange
  335. *
  336. * @brief This function processes the incoming Management Network
  337. * Update notify and starts an Update Request if a channel
  338. * change is needed.
  339. *
  340. * @param pUpdateNotify - notify message
  341. *
  342. * @return none
  343. */
  344. static void ZDNwkMgr_CheckForChannelChange( ZDO_MgmtNwkUpdateNotify_t *pNotify )
  345. {
  346. uint8 i;
  347. uint16 failureRate;
  348. uint8 lowestEnergyIndex;
  349. uint8 lowestEnergyValue = 0xFF;
  350. // If any device has more than 50% transmission failures, a channel
  351. // change should be considered
  352. failureRate = ( pNotify->transmissionFailures * 100 ) / pNotify->totalTransmissions;
  353. if ( failureRate < ZDNWKMGR_CC_TX_FAILURE )
  354. {
  355. #if defined ( LCD_SUPPORTED )
  356. HalLcdWriteString( (char*)NwkMgrStr_1, HAL_LCD_LINE_1 );
  357. HalLcdWriteStringValueValue( ": ", failureRate, 10, ZDNWKMGR_CC_TX_FAILURE, 10, HAL_LCD_LINE_2 );
  358. #endif
  359. return;
  360. }
  361. // If the current failure rate is higher than the last failure rate,
  362. // a channel change should be considered
  363. if ( failureRate < ZDNwkMgr_LastChannelFailureRate )
  364. {
  365. #if defined ( LCD_SUPPORTED )
  366. HalLcdWriteString( (char*)NwkMgrStr_2, HAL_LCD_LINE_1 );
  367. HalLcdWriteStringValueValue( ": ", failureRate, 10,
  368. ZDNwkMgr_LastChannelFailureRate, 10, HAL_LCD_LINE_2 );
  369. #endif
  370. return;
  371. }
  372. // Select a single channel based on the Mgmt_NWK_Update_notify based on
  373. // the lowest energy. This is the proposed new channel.
  374. for ( i = 0; i < pNotify->listCount; i++ )
  375. {
  376. if ( pNotify->energyValues[i] < lowestEnergyValue )
  377. {
  378. lowestEnergyIndex = i;
  379. lowestEnergyValue = pNotify->energyValues[i];
  380. }
  381. }
  382. // If this new channel does not have an energy level below an acceptable
  383. // threshold, a channel change should not be done.
  384. if ( lowestEnergyValue > ZDNWKMGR_ACCEPTABLE_ENERGY_LEVEL )
  385. {
  386. #if defined ( LCD_SUPPORTED )
  387. HalLcdWriteString( (char*)NwkMgrStr_3, HAL_LCD_LINE_1 );
  388. HalLcdWriteStringValueValue( ": ", lowestEnergyValue, 10,
  389. ZDNWKMGR_ACCEPTABLE_ENERGY_LEVEL, 10, HAL_LCD_LINE_2 );
  390. #endif
  391. return;
  392. }
  393. // Channel change should be done -- find out the new active channel
  394. for ( i = 0; i < ED_SCAN_MAXCHANNELS; i++ )
  395. {
  396. if ( ( (uint32)1 << i ) & pNotify->scannedChannels )
  397. {
  398. if ( lowestEnergyIndex == 0 )
  399. break;
  400. lowestEnergyIndex--;
  401. }
  402. }
  403. if ( ( _NIB.nwkLogicalChannel != i ) && ( ZDNwkMgr_UpdateRequestTimer == 0 ) )
  404. {
  405. uint32 channelMask;
  406. zAddrType_t dstAddr;
  407. // The new channel
  408. ZDNwkMgr_NewChannel = i;
  409. // Prior to changing channels, the network manager should store the
  410. // energy scan value as the last energy scan value and the failure
  411. // rate from the existing channel as the last failure rate. These
  412. // values are useful to allow comparison of the failure rate and energy
  413. // level on the previous channel to evaluate if the network is causing
  414. // its own interference.
  415. ZDNwkMgr_LastChannelEnergy = lowestEnergyValue;
  416. ZDNwkMgr_LastChannelFailureRate = failureRate;
  417. // The network manager should broadcast a Mgmt_NWK_Update_req notifying
  418. // devices of the new channel. The broadcast shall be to all routers
  419. // and coordinator.
  420. dstAddr.addrMode = AddrBroadcast;
  421. dstAddr.addr.shortAddr = NWK_BROADCAST_SHORTADDR_DEVRXON;
  422. channelMask = (uint32)1 << i;
  423. // Increment the nwkUpdateId parameter and set the updateID in the beacon
  424. NLME_SetUpdateID(_NIB.nwkUpdateId + 1);
  425. ZDP_MgmtNwkUpdateReq( &dstAddr, channelMask, 0xfe, 0, _NIB.nwkUpdateId, 0 );
  426. // The network manager shall set a timer based on the value of
  427. // apsChannelTimer upon issue of a Mgmt_NWK_Update_req that changes
  428. // channels and shall not issue another such command until this
  429. // timer expires.
  430. ZDNwkMgr_UpdateRequestTimer = ZDNWKMGR_UPDATE_REQUEST_TIMER;
  431. osal_start_timerEx( ZDNwkMgr_TaskID, ZDNWKMGR_UPDATE_REQUEST_EVT, ONE_MINUTE );
  432. // Upon receipt of a Mgmt_NWK_Update_req with a change of channels,
  433. // the local network manager shall set a timer equal to the
  434. // nwkNetworkBroadcastDeliveryTime and shall switch channels upon
  435. // expiration of this timer. NOTE: since we won't recevied our own
  436. // broadcasted Update Request, we start the channel change timer here.
  437. osal_start_timerEx( ZDNwkMgr_TaskID, ZDNWKMGR_CHANNEL_CHANGE_EVT,
  438. ZDNWKMGR_BCAST_DELIVERY_TIME );
  439. }
  440. }
  441. #endif // NWK_MANAGER
  442. /*********************************************************************
  443. * @fn ZDNwkMgr_ProcessMgmtNwkUpdateReq
  444. *
  445. * @brief This function processes the incoming Management
  446. * Network Update request and starts the request (if needed).
  447. *
  448. * @param Request message
  449. *
  450. * @return none
  451. */
  452. static void ZDNwkMgr_ProcessMgmtNwkUpdateReq( zdoIncomingMsg_t *inMsg )
  453. {
  454. ZDO_MgmtNwkUpdateReq_t Req;
  455. ZDO_ParseMgmtNwkUpdateReq( inMsg, &Req );
  456. if ( Req.scanDuration <= 0x05 )
  457. {
  458. // Request is to scan over channelMask. The result will be reported by Confirm
  459. if ( ( !inMsg->wasBroadcast ) &&
  460. ( Req.scanCount > ZDNWKMGR_MIN_SCAN_COUNT ) &&
  461. ( Req.scanCount <= ZDNWKMGR_MAX_SCAN_COUNT ) )
  462. {
  463. if ( NLME_EDScanRequest( Req.channelMask, Req.scanDuration ) == ZSuccess )
  464. {
  465. // Save off the information to be used for the notify
  466. ZDNwkMgr_MgmtNwkUpdateNotifyTransSeq = inMsg->TransSeq;
  467. ZDNwkMgr_MgmtNwkUpdateNotifyAddr.addr.shortAddr = inMsg->srcAddr.addr.shortAddr;
  468. Req.scanCount--;
  469. // Save off scan info for the subsequent scans
  470. ZDNwkMgr_MgmtNwkUpdateReq = Req;
  471. }
  472. }
  473. }
  474. else if ( Req.scanDuration == 0xFE )
  475. {
  476. // Request is to change Channel. The command provide a new active
  477. // channel as a single channel in the channelMask.
  478. if ( Req.nwkUpdateId > _NIB.nwkUpdateId )
  479. {
  480. uint8 i;
  481. // Set update ID in the Beacon
  482. NLME_SetUpdateID(Req.nwkUpdateId);
  483. // Find out the new active channel
  484. for ( i = 0; i < ED_SCAN_MAXCHANNELS; i++ )
  485. {
  486. if ( ( (uint32)1 << i ) & Req.channelMask )
  487. {
  488. break;
  489. }
  490. }
  491. if ( _NIB.nwkLogicalChannel != i )
  492. {
  493. ZDNwkMgr_NewChannel = i;
  494. // Upon receipt of a Mgmt_NWK_Update_req with a change of channels,
  495. // the local network manager shall set a timer equal to the
  496. // nwkNetworkBroadcastDeliveryTime and shall switch channels upon
  497. // expiration of this timer. Each node shall also increment the
  498. // nwkUpdateId parameter and also reset the total transmit count
  499. // and the transmit failure counters.
  500. osal_start_timerEx( ZDNwkMgr_TaskID, ZDNWKMGR_CHANNEL_CHANGE_EVT,
  501. ZDNWKMGR_BCAST_DELIVERY_TIME );
  502. }
  503. }
  504. }
  505. else if ( Req.scanDuration == 0xFF )
  506. {
  507. // Request is to change apsChannelMask and nwkManagerAddr
  508. if ( Req.nwkUpdateId > _NIB.nwkUpdateId )
  509. {
  510. NLME_SetUpdateID(Req.nwkUpdateId); // Set the updateID in the beacon
  511. if ( ( Req.channelMask != 0 ) && ( _NIB.channelList != Req.channelMask ) )
  512. {
  513. _NIB.channelList = Req.channelMask;
  514. // Our Channel List has been changed -- notify to save info into NV
  515. ZDApp_NwkStateUpdateCB();
  516. }
  517. ZDNwkMgr_SetNwkManagerAddr( Req.nwkManagerAddr );
  518. }
  519. }
  520. else // 0x06-0xFD
  521. {
  522. // Request is invalid
  523. if ( !inMsg->wasBroadcast )
  524. {
  525. ZDNwkMgr_MgmtNwkUpdateNotifyAddr.addr.shortAddr = inMsg->srcAddr.addr.shortAddr;
  526. ZDP_MgmtNwkUpdateNotify( inMsg->TransSeq, &ZDNwkMgr_MgmtNwkUpdateNotifyAddr,
  527. ZDP_INVALID_REQTYPE, 0, 0, 0, 0, NULL, AF_TX_OPTIONS_NONE, false );
  528. }
  529. }
  530. }
  531. /*********************************************************************
  532. * @fn ZDNwkMgr_ProcessServerDiscRsp
  533. *
  534. * @brief Process the incoming System Server Discovery Response
  535. *
  536. * @param pRsp - Structure containing Server Discovery response
  537. *
  538. * @return none
  539. */
  540. void ZDNwkMgr_ProcessServerDiscRsp( zdoIncomingMsg_t *inMsg )
  541. {
  542. ZDO_ServerDiscRsp_t Rsp;
  543. ZDO_ParseServerDiscRsp( inMsg, &Rsp );
  544. if ( Rsp.status == ZSuccess )
  545. {
  546. // Is the Network Manager bit set in the response?
  547. if ( Rsp.serverMask & NETWORK_MANAGER )
  548. {
  549. // Set the Remote Device's NWK Address as the Network Manager Address
  550. ZDNwkMgr_SetNwkManagerAddr( inMsg->srcAddr.addr.shortAddr );
  551. }
  552. }
  553. }
  554. /*********************************************************************
  555. * @fn ZDNwkMgr_ProcessChannelInterference
  556. *
  557. * @brief This function processes the incoming Channel Interference
  558. * detection message and sends out a notify (if needed).
  559. *
  560. * @param pChannelInterference - interference message
  561. *
  562. * @return none
  563. */
  564. static void ZDNwkMgr_ProcessChannelInterference( ZDNwkMgr_ChanInterference_t *pChanInterference )
  565. {
  566. // To avoid a device with communication problems from constantly
  567. // sending reports to the network manager, the device should not
  568. // send a Mgmt_NWK_Update_notify more than 4 times per hour.
  569. if ( ZDNwkMgr_NumUpdateNotifySent < 4 )
  570. {
  571. // Conduct an energy scan on all channels.
  572. if ( NLME_EDScanRequest( MAX_CHANNELS_24GHZ, _NIB.scanDuration ) == ZSuccess )
  573. {
  574. // Save the counters for the Update Notify message to be sent
  575. ZDNwkMgr_TotalTransmissions = pChanInterference->totalTransmissions;
  576. ZDNwkMgr_TxFailures = pChanInterference->txFailures;
  577. // Mark scan as channel inetrference check
  578. ZDNwkMgr_MgmtNwkUpdateReq.scanCount = 0xFF;
  579. }
  580. }
  581. }
  582. /*********************************************************************
  583. * @fn ZDNwkMgr_ProcessEDScanConfirm
  584. *
  585. * @brief This function processes the incoming ED Scan Confirm
  586. * message and sends out a notify (if needed).
  587. *
  588. * @param pEDScanConfirm - SD Scan Confirmation message
  589. *
  590. * @return none
  591. */
  592. static void ZDNwkMgr_ProcessEDScanConfirm( ZDNwkMgr_EDScanConfirm_t *pEDScanConfirm )
  593. {
  594. if ( ZDNwkMgr_MgmtNwkUpdateReq.scanCount == 0xFF )
  595. {
  596. // Confirm to scan all channels for channel interference check
  597. ZDNwkMgr_CheckForChannelInterference( pEDScanConfirm );
  598. ZDNwkMgr_MgmtNwkUpdateReq.scanCount = 0;
  599. }
  600. else
  601. {
  602. // Confirm to the requested scan
  603. uint16 txFailures = nwkTransmissionFailures( FALSE );
  604. ZDNwkMgr_BuildAndSendUpdateNotify( ZDNwkMgr_MgmtNwkUpdateNotifyTransSeq,
  605. &ZDNwkMgr_MgmtNwkUpdateNotifyAddr,
  606. _NIB.nwkTotalTransmissions, txFailures,
  607. pEDScanConfirm, AF_TX_OPTIONS_NONE );
  608. // More scans needed?
  609. if ( ZDNwkMgr_MgmtNwkUpdateReq.scanCount > 0 )
  610. {
  611. osal_start_timerEx( ZDNwkMgr_TaskID, ZDNWKMGR_SCAN_REQUEST_EVT, 50 );
  612. }
  613. }
  614. }
  615. /*********************************************************************
  616. * @fn ZDNwkMgr_CheckForChannelInterference
  617. *
  618. * @brief This function processes the incoming ED Scan Confirm
  619. * message and sends out an Update Notify (if needed).
  620. *
  621. * @param pEDScanConfirm - SD Scan Confirmation message
  622. *
  623. * @return none
  624. */
  625. static void ZDNwkMgr_CheckForChannelInterference( ZDNwkMgr_EDScanConfirm_t *pEDScanConfirm )
  626. {
  627. uint8 i;
  628. uint8 channelEnergy = 0;
  629. uint8 energyIncreased = FALSE;
  630. // Get the current channel energy
  631. if ( ( (uint32)1 << _NIB.nwkLogicalChannel ) & pEDScanConfirm->scannedChannels )
  632. {
  633. channelEnergy = pEDScanConfirm->energyDetectList[_NIB.nwkLogicalChannel];
  634. }
  635. // If this energy scan does not indicate higher energy on the current
  636. // channel then other channels, no action is taken. The device should
  637. // continue to operate as normal and the message counters are not reset.
  638. for ( i = 0; i < ED_SCAN_MAXCHANNELS; i++ )
  639. {
  640. if ( ( ( (uint32)1 << i ) & pEDScanConfirm->scannedChannels ) &&
  641. ( channelEnergy > pEDScanConfirm->energyDetectList[i] ) )
  642. {
  643. energyIncreased = TRUE;
  644. break;
  645. }
  646. }
  647. // If the energy scan does indicate increased energy on the channel
  648. // in use, a Mgmt_NWK_Update_notify should be sent to the Network
  649. // Manager to indicate interference is present.
  650. if ( energyIncreased )
  651. {
  652. // Send a Management Network Update notify to the Network Manager
  653. ZDNwkMgr_MgmtNwkUpdateNotifyAddr.addr.shortAddr = _NIB.nwkManagerAddr;
  654. ZDNwkMgr_BuildAndSendUpdateNotify( 0, &ZDNwkMgr_MgmtNwkUpdateNotifyAddr,
  655. ZDNwkMgr_TotalTransmissions, ZDNwkMgr_TxFailures,
  656. pEDScanConfirm, AF_MSG_ACK_REQUEST );
  657. ZDNwkMgr_WaitingForNotifyConfirm = TRUE; // Confirm will clear the counters
  658. if ( ZDNwkMgr_NumUpdateNotifySent == 0 )
  659. {
  660. // First notify message sent within this hour. Start the Update Notify timer.
  661. ZDNwkMgr_UpdateNotifyTimer = ZDNWKMGR_UPDATE_NOTIFY_TIMER;
  662. osal_start_timerEx( ZDNwkMgr_TaskID, ZDNWKMGR_UPDATE_NOTIFY_EVT, ONE_MINUTE );
  663. }
  664. ZDNwkMgr_NumUpdateNotifySent++;
  665. }
  666. #if defined ( LCD_SUPPORTED )
  667. else
  668. {
  669. // HalLcdWriteString( (char*)NwkMgrStr_4, HAL_LCD_LINE_1 );
  670. //HalLcdWriteStringValueValue( ": ", _NIB.nwkLogicalChannel, 10, channelEnergy, 10, HAL_LCD_LINE_2 );
  671. }
  672. #endif
  673. }
  674. /*********************************************************************
  675. * @fn ZDNwkMgr_BuildAndSendUpdateNotify
  676. *
  677. * @brief This builds and send a Mgmt_NWK_Update_notify message. This
  678. * function sends a unicast message.
  679. *
  680. * @param TransSeq - transaction sequence number
  681. * @param dstAddr - destination address of the message
  682. * @param pEDScanConfirm - update notify info
  683. *
  684. * @return afStatus_t
  685. */
  686. static void ZDNwkMgr_BuildAndSendUpdateNotify( uint8 TransSeq, zAddrType_t *dstAddr,
  687. uint16 totalTransmissions, uint16 txFailures,
  688. ZDNwkMgr_EDScanConfirm_t *pEDScanConfirm,
  689. uint8 txOptions )
  690. {
  691. uint8 i;
  692. uint8 listCount = 0;
  693. uint8 *energyValues = NULL;
  694. // Count number of energy detects
  695. for ( i = 0; i < ED_SCAN_MAXCHANNELS; i++ )
  696. {
  697. if ( ( (uint32)1 << i ) & pEDScanConfirm->scannedChannels )
  698. listCount++;
  699. }
  700. if ( listCount > 0 )
  701. {
  702. energyValues = (uint8 *)osal_mem_alloc( listCount );
  703. if ( energyValues )
  704. {
  705. uint8 j = 0;
  706. for ( i = 0; i < ED_SCAN_MAXCHANNELS; i++ )
  707. {
  708. if ( ( (uint32)1 << i ) & pEDScanConfirm->scannedChannels )
  709. energyValues[j++] = pEDScanConfirm->energyDetectList[i];
  710. }
  711. }
  712. }
  713. // Send a Management Network Update notify back
  714. ZDP_MgmtNwkUpdateNotify( TransSeq, dstAddr, pEDScanConfirm->status,
  715. pEDScanConfirm->scannedChannels,
  716. totalTransmissions, txFailures,
  717. listCount, energyValues, txOptions, false );
  718. if ( energyValues )
  719. osal_mem_free( energyValues );
  720. }
  721. #if defined ( NWK_MANAGER )
  722. /*********************************************************************
  723. * @fn NwkMgr_SetNwkManager
  724. *
  725. * @brief Set the local device as the Network Manager
  726. *
  727. * @param none
  728. *
  729. * @return none
  730. */
  731. void NwkMgr_SetNwkManager( void )
  732. {
  733. if ( zgNwkMgrMode == ZDNWKMGR_ENABLE )
  734. {
  735. // We're the Network Manager. Set our address as the Network Manager Address
  736. ZDNwkMgr_SetNwkManagerAddr( _NIB.nwkDevAddress );
  737. // Set the Network Manager bit of the Server Mask
  738. ZDO_Config_Node_Descriptor.ServerMask |= NETWORK_MANAGER;
  739. }
  740. }
  741. #endif // NWK_MANAGER
  742. /*********************************************************************
  743. * @fn ZDApp_SetNwkManagerAddr()
  744. *
  745. * @brief Sets the nwkManagerAddr in NIB.
  746. *
  747. * @param nwkManagerAddr
  748. *
  749. * @return none
  750. */
  751. void ZDNwkMgr_SetNwkManagerAddr( uint16 nwkManagerAddr )
  752. {
  753. if ( _NIB.nwkManagerAddr != nwkManagerAddr )
  754. {
  755. // Update the Network Manager Address
  756. _NIB.nwkManagerAddr = nwkManagerAddr;
  757. // Our Network Manger Address has been changed -- notify to save info into NV
  758. ZDApp_NwkStateUpdateCB();
  759. }
  760. }
  761. /*********************************************************************
  762. * @fn ZDNwkMgr_ReportChannelInterference
  763. *
  764. * @brief This function builds a Channel Interference detection
  765. * message and then forwards it to the Network Manager.
  766. *
  767. * @param chanInterference
  768. *
  769. * @return none
  770. */
  771. void ZDNwkMgr_ReportChannelInterference( NLME_ChanInterference_t *chanInterference )
  772. {
  773. ZDNwkMgr_ChanInterference_t *pChanInterference;
  774. // Send Channel Interference message to the Network Manager task
  775. pChanInterference = (ZDNwkMgr_ChanInterference_t *)osal_msg_allocate( sizeof( ZDNwkMgr_ChanInterference_t ) );
  776. if ( pChanInterference )
  777. {
  778. pChanInterference->hdr.event = NM_CHANNEL_INTERFERE;
  779. // Build the structure
  780. pChanInterference->totalTransmissions = chanInterference->totalTransmissions;
  781. pChanInterference->txFailures = chanInterference->txFailures;
  782. osal_msg_send( ZDNwkMgr_TaskID, (uint8 *)pChanInterference );
  783. }
  784. }
  785. /*********************************************************************
  786. * @fn ZDNwkMgr_EDScanConfirmCB
  787. *
  788. * @brief Handle Energy Scan confirm callback
  789. *
  790. * @param scannedChannels - scanned channels
  791. * @param energyDetectList - measured energy for channels
  792. *
  793. * @return none
  794. */
  795. void ZDNwkMgr_EDScanConfirmCB( NLME_EDScanConfirm_t *EDScanConfirm )
  796. {
  797. ZDNwkMgr_EDScanConfirm_t *pEDScanConfirm;
  798. // Send ED Confirm to the Network Manager task
  799. pEDScanConfirm = (ZDNwkMgr_EDScanConfirm_t *)osal_msg_allocate( sizeof( ZDNwkMgr_EDScanConfirm_t ) );
  800. if ( pEDScanConfirm )
  801. {
  802. pEDScanConfirm->hdr.event = NM_ED_SCAN_CONFIRM;
  803. // Build the structure
  804. pEDScanConfirm->status = EDScanConfirm->status;
  805. pEDScanConfirm->scannedChannels = EDScanConfirm->scannedChannels;
  806. osal_memcpy( pEDScanConfirm->energyDetectList, EDScanConfirm->energyDetectList, ED_SCAN_MAXCHANNELS );
  807. osal_msg_send( ZDNwkMgr_TaskID, (uint8 *)pEDScanConfirm );
  808. }
  809. }
  810. /*********************************************************************
  811. * @fn ZDNwkMgr_ProcessDataConfirm
  812. *
  813. * @brief Process received Confirmation for Mgmt NWK Update Notify message
  814. *
  815. * @param none
  816. *
  817. * @return none
  818. */
  819. void ZDNwkMgr_ProcessDataConfirm( afDataConfirm_t *afDataConfirm )
  820. {
  821. if ( ZDNwkMgr_WaitingForNotifyConfirm &&
  822. ( afDataConfirm->transID == 0 ) &&
  823. ( afDataConfirm->hdr.status == ZSuccess ) )
  824. {
  825. // The Mgmt NWK Update Notify was sent as an APS Unicast with
  826. // acknowledgement and once the acknowledgment is received the
  827. // total transmit and transmit failure counters are reset to zero.
  828. _NIB.nwkTotalTransmissions = 0;
  829. nwkTransmissionFailures( TRUE );
  830. ZDNwkMgr_WaitingForNotifyConfirm = FALSE;
  831. }
  832. }
  833. /*********************************************************************
  834. * PAN ID Conflict Routines
  835. */
  836. #if defined ( NWK_MANAGER )
  837. /*********************************************************************
  838. * @fn ZDNwkMgr_NetworkReportCB
  839. *
  840. * @brief Handle the Network Report Command
  841. *
  842. * @param srcAddr - Source Address of the message.
  843. * @param status - ZSuccess.
  844. * @param serverMask - Bit mask of services matching the req serverMask.
  845. * @param securityUse -
  846. *
  847. * @return none
  848. */
  849. void ZDNwkMgr_NetworkReportCB( ZDNwkMgr_NetworkReport_t *pReport )
  850. {
  851. // Send Network Report message to the Network Manager task
  852. osal_msg_send( ZDNwkMgr_TaskID, (uint8 *)pReport );
  853. }
  854. /*********************************************************************
  855. * @fn ZDNwkMgr_NetworkUpdateCB
  856. *
  857. * @brief Handle the Network Update Command
  858. *
  859. * @param srcAddr - Source Address of the message.
  860. * @param status - ZSuccess.
  861. * @param serverMask - Bit mask of services matching the req serverMask.
  862. * @param securityUse -
  863. *
  864. * @return none
  865. */
  866. void ZDNwkMgr_NetworkUpdateCB( ZDNwkMgr_NetworkUpdate_t *pUpdate )
  867. {
  868. // Send Network Update message to the Network Manager task
  869. osal_msg_send( ZDNwkMgr_TaskID, (uint8 *)pUpdate );
  870. }
  871. /*********************************************************************
  872. * @fn ZDNwkMgr_ProcessNetworkReport
  873. *
  874. * @brief Process the incoming Network Report message
  875. *
  876. * @param pNetworkReport - Structure containing Network Report message
  877. *
  878. * @return none
  879. */
  880. void ZDNwkMgr_ProcessNetworkReport( ZDNwkMgr_NetworkReport_t *pNetworkReport )
  881. {
  882. uint8 i;
  883. uint16 newPID;
  884. uint8 unique = TRUE;
  885. if ( pNetworkReport->reportType == NWKREPORT_PANID_CONFLICT )
  886. {
  887. if ( ZDNwkMgr_PanIdUpdateInProgress == FALSE )
  888. {
  889. do
  890. {
  891. // select a new PAN ID
  892. newPID = (uint16)osal_rand();
  893. // Make sure that the chosen PAN ID is not already in use in the
  894. // local neighborhood and also not contained within the Report
  895. // Information field of the Network Report Command frame
  896. for ( i = 0; i < pNetworkReport->reportInfoCnt; i++ )
  897. {
  898. if ( pNetworkReport->panIDs[i] == newPID )
  899. {
  900. unique = FALSE;
  901. break;
  902. }
  903. }
  904. } while ( !unique );
  905. // Send out a Network Update command.
  906. NLME_SendNetworkUpdate( NWK_BROADCAST_SHORTADDR, NWKUPDATE_PANID_UPDATE,
  907. _NIB.extendedPANID, _NIB.nwkUpdateId+1, newPID );
  908. ZDNwkMgr_PanIdUpdateInProgress = TRUE;
  909. }
  910. }
  911. }
  912. /*********************************************************************
  913. * @fn ZDNwkMgr_ProcessNetworkUpdate
  914. *
  915. * @brief Process the incoming Network Update message
  916. *
  917. * @param pNetworkReport - Structure containing Network Update message
  918. *
  919. * @return none
  920. */
  921. void ZDNwkMgr_ProcessNetworkUpdate( ZDNwkMgr_NetworkUpdate_t *pNetworkUpdate )
  922. {
  923. if ( pNetworkUpdate->updateType == NWKUPDATE_PANID_UPDATE )
  924. {
  925. // Our PAN ID has been changed -- notify to save info into NV
  926. ZDApp_NwkStateUpdateCB();
  927. ZDNwkMgr_PanIdUpdateInProgress = FALSE;
  928. }
  929. }
  930. #endif // NWK_MANAGER
  931. /*********************************************************************
  932. *********************************************************************/