ZDApp.c 81 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040
  1. /**************************************************************************************************
  2. Filename: ZDApp.c
  3. Revised: $Date: 2012-02-16 16:04:32 -0800 (Thu, 16 Feb 2012) $
  4. Revision: $Revision: 29348 $
  5. Description: This file contains the interface to the Zigbee Device Application. This is the
  6. Application part that the user can change. This also contains the Task functions.
  7. Copyright 2004-2012 Texas Instruments Incorporated. All rights reserved.
  8. IMPORTANT: Your use of this Software is limited to those specific rights
  9. granted under the terms of a software license agreement between the user
  10. who downloaded the software, his/her employer (which must be your employer)
  11. and Texas Instruments Incorporated (the "License"). You may not use this
  12. Software unless you agree to abide by the terms of the License. The License
  13. limits your use, and you acknowledge, that the Software may not be modified,
  14. copied or distributed unless embedded on a Texas Instruments microcontroller
  15. or used solely and exclusively in conjunction with a Texas Instruments radio
  16. frequency transceiver, which is integrated into your product. Other than for
  17. the foregoing purpose, you may not use, reproduce, copy, prepare derivative
  18. works of, modify, distribute, perform, display or sell this Software and/or
  19. its documentation for any purpose.
  20. YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
  21. PROVIDED 揂S IS?WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
  22. INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
  23. NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
  24. TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
  25. NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
  26. LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
  27. INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
  28. OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
  29. OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
  30. (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
  31. Should you have any questions regarding your right to use this Software,
  32. contact Texas Instruments Incorporated at www.TI.com.
  33. **************************************************************************************************/
  34. /*********************************************************************
  35. * INCLUDES
  36. */
  37. #include "ZComDef.h"
  38. #include "ZMac.h"
  39. #include "OSAL.h"
  40. #include "OSAL_Tasks.h"
  41. #include "OSAL_PwrMgr.h"
  42. #include "OSAL_Nv.h"
  43. #include "AF.h"
  44. #include "APSMEDE.h"
  45. #include "NLMEDE.h"
  46. #include "AddrMgr.h"
  47. #include "ZDProfile.h"
  48. #include "ZDObject.h"
  49. #include "ZDConfig.h"
  50. #include "ZDSecMgr.h"
  51. #include "ZDApp.h"
  52. #include "DebugTrace.h"
  53. #include "nwk_util.h"
  54. #include "OnBoard.h"
  55. #include "ZGlobals.h"
  56. #include "ZDNwkMgr.h"
  57. #include "rtg.h"
  58. #include "ssp.h"
  59. /* HAL */
  60. #include "hal_led.h"
  61. #include "hal_lcd.h"
  62. #include "hal_key.h"
  63. #if defined( MT_MAC_FUNC ) || defined( MT_MAC_CB_FUNC )
  64. #error "ERROR! MT_MAC functionalities should be disabled on ZDO devices"
  65. #endif
  66. /*********************************************************************
  67. * CONSTANTS
  68. */
  69. #if !defined( NWK_START_DELAY )
  70. #define NWK_START_DELAY 100 // in milliseconds
  71. #endif
  72. #if !defined( LEAVE_RESET_DELAY )
  73. #define LEAVE_RESET_DELAY 5000 // in milliseconds
  74. #endif
  75. // Init ZDO, but hold and wait for application to start the joining or
  76. // forming network
  77. #define ZDO_INIT_HOLD_NWK_START 0xFFFF
  78. #if !defined( EXTENDED_JOINING_RANDOM_MASK )
  79. #define EXTENDED_JOINING_RANDOM_MASK 0x007F
  80. #endif
  81. #if !defined( BEACON_REQUEST_DELAY )
  82. #define BEACON_REQUEST_DELAY 100 // in milliseconds
  83. #endif
  84. #if !defined( BEACON_REQ_DELAY_MASK )
  85. #define BEACON_REQ_DELAY_MASK 0x007F
  86. #endif
  87. #define MAX_RESUME_RETRY 3
  88. #define MAX_DEVICE_UNAUTH_TIMEOUT 5000 // 5 seconds
  89. // Beacon Order Settings (see NLMEDE.h)
  90. #define DEFAULT_BEACON_ORDER BEACON_ORDER_NO_BEACONS
  91. #define DEFAULT_SUPERFRAME_ORDER DEFAULT_BEACON_ORDER
  92. #if !defined( MAX_NWK_FRAMECOUNTER_CHANGES )
  93. // The number of times the frame counter can change before
  94. // saving to NV
  95. #define MAX_NWK_FRAMECOUNTER_CHANGES 1000
  96. #endif
  97. // Leave control bits
  98. #define ZDAPP_LEAVE_CTRL_INIT 0
  99. #define ZDAPP_LEAVE_CTRL_SET 1
  100. #define ZDAPP_LEAVE_CTRL_RA 2
  101. // Address Manager Stub Implementation
  102. #define ZDApp_NwkWriteNVRequest AddrMgrWriteNVRequest
  103. #if !defined ZDO_NV_SAVE_RFDs
  104. #define ZDO_NV_SAVE_RFDs TRUE
  105. #endif
  106. // Delay time before updating NWK NV data to force fewer writes during high activity.
  107. #if ZDO_NV_SAVE_RFDs
  108. #define ZDAPP_UPDATE_NWK_NV_TIME 700
  109. #else
  110. #define ZDAPP_UPDATE_NWK_NV_TIME 65000
  111. #endif
  112. /*********************************************************************
  113. * GLOBAL VARIABLES
  114. */
  115. #if defined( LCD_SUPPORTED )
  116. uint8 MatchRsps = 0;
  117. #endif
  118. uint8 zdoDiscCounter = 1;
  119. zAddrType_t ZDAppNwkAddr;
  120. uint8 zdappMgmtNwkDiscRspTransSeq;
  121. uint8 zdappMgmtNwkDiscReqInProgress = FALSE;
  122. zAddrType_t zdappMgmtNwkDiscRspAddr;
  123. uint8 zdappMgmtNwkDiscStartIndex;
  124. uint8 zdappMgmtSavedNwkState;
  125. uint16 nwkFrameCounterChanges = 0;
  126. uint8 continueJoining = TRUE;
  127. uint8 _tmpRejoinState;
  128. // The extended PanID used in ZDO layer for rejoin.
  129. uint8 ZDO_UseExtendedPANID[Z_EXTADDR_LEN];
  130. pfnZdoCb zdoCBFunc[MAX_ZDO_CB_FUNC];
  131. /*********************************************************************
  132. * EXTERNAL VARIABLES
  133. */
  134. /*********************************************************************
  135. * EXTERNAL FUNCTIONS
  136. */
  137. /*********************************************************************
  138. * LOCAL FUNCTIONS
  139. */
  140. void ZDApp_NetworkStartEvt( void );
  141. void ZDApp_DeviceAuthEvt( void );
  142. void ZDApp_SaveNetworkStateEvt( void );
  143. uint8 ZDApp_ReadNetworkRestoreState( void );
  144. uint8 ZDApp_RestoreNetworkState( void );
  145. void ZDAppDetermineDeviceType( void );
  146. void ZDApp_InitUserDesc( void );
  147. void ZDAppCheckForHoldKey( void );
  148. void ZDApp_ProcessOSALMsg( osal_event_hdr_t *msgPtr );
  149. void ZDApp_ProcessNetworkJoin( void );
  150. void ZDApp_SetCoordAddress( uint8 endPoint, uint8 dstEP );
  151. uint8 ZDApp_RestoreNwkKey( void );
  152. networkDesc_t* ZDApp_NwkDescListProcessing(void);
  153. void ZDApp_SecInit( uint8 state );
  154. UINT16 ZDApp_ProcessSecEvent( uint8 task_id, UINT16 events );
  155. void ZDApp_ProcessSecMsg( osal_event_hdr_t *msgPtr );
  156. void ZDApp_SendMsg( uint8 taskID, uint8 cmd, uint8 len, uint8 *buf );
  157. void ZDApp_ResetTimerStart( uint16 delay );
  158. void ZDApp_ResetTimerCancel( void );
  159. void ZDApp_LeaveCtrlInit( void );
  160. void ZDApp_LeaveCtrlSet( uint8 ra );
  161. uint8 ZDApp_LeaveCtrlBypass( void );
  162. void ZDApp_LeaveCtrlStartup( devStates_t* state, uint16* startDelay );
  163. void ZDApp_LeaveUpdate( uint16 nwkAddr, uint8* extAddr,
  164. uint8 removeChildren );
  165. void ZDApp_NodeProfileSync( uint8 stackProfile );
  166. void ZDApp_ProcessMsgCBs( zdoIncomingMsg_t *inMsg );
  167. void ZDApp_RegisterCBs( void );
  168. void ZDApp_InitZdoCBFunc(void);
  169. /*********************************************************************
  170. * LOCAL VARIABLES
  171. */
  172. uint8 ZDAppTaskID;
  173. uint8 nwkStatus;
  174. endPointDesc_t *ZDApp_AutoFindMode_epDesc = (endPointDesc_t *)NULL;
  175. uint8 ZDApp_LeaveCtrl;
  176. #if defined( HOLD_AUTO_START )
  177. devStates_t devState = DEV_HOLD;
  178. #else
  179. devStates_t devState = DEV_INIT;
  180. #endif
  181. #if ( ZG_BUILD_RTRONLY_TYPE ) || ( ZG_BUILD_ENDDEVICE_TYPE )
  182. devStartModes_t devStartMode = MODE_JOIN; // Assume joining
  183. //devStartModes_t devStartMode = MODE_RESUME; // if already "directly joined"
  184. // to parent. Set to make the device do an Orphan scan.
  185. #else
  186. // Set the default to coodinator
  187. devStartModes_t devStartMode = MODE_HARD;
  188. #endif
  189. uint8 retryCnt;
  190. endPointDesc_t ZDApp_epDesc =
  191. {
  192. ZDO_EP,
  193. &ZDAppTaskID,
  194. (SimpleDescriptionFormat_t *)NULL, // No Simple description for ZDO
  195. (afNetworkLatencyReq_t)0 // No Network Latency req
  196. };
  197. uint16 ZDApp_SavedPollRate = POLL_RATE;
  198. /*********************************************************************
  199. * @fn ZDApp_Init
  200. *
  201. * @brief ZDApp Initialization function.
  202. *
  203. * @param task_id - ZDApp Task ID
  204. *
  205. * @return None
  206. */
  207. void ZDApp_Init( uint8 task_id )
  208. {
  209. // Save the task ID
  210. ZDAppTaskID = task_id;
  211. // Initialize the ZDO global device short address storage
  212. ZDAppNwkAddr.addrMode = Addr16Bit;
  213. ZDAppNwkAddr.addr.shortAddr = INVALID_NODE_ADDR;
  214. (void)NLME_GetExtAddr(); // Load the saveExtAddr pointer.
  215. // Check for manual "Hold Auto Start"
  216. ZDAppCheckForHoldKey();
  217. // Initialize ZDO items and setup the device - type of device to create.
  218. ZDO_Init();
  219. // Register the endpoint description with the AF
  220. // This task doesn't have a Simple description, but we still need
  221. // to register the endpoint.
  222. afRegister( (endPointDesc_t *)&ZDApp_epDesc );
  223. #if defined( ZDO_USERDESC_RESPONSE )
  224. ZDApp_InitUserDesc();
  225. #endif // ZDO_USERDESC_RESPONSE
  226. // Start the device?
  227. if ( devState != DEV_HOLD )
  228. {
  229. ZDOInitDevice( 0 );
  230. }
  231. else
  232. {
  233. ZDOInitDevice( ZDO_INIT_HOLD_NWK_START );
  234. // Blink LED to indicate HOLD_START
  235. //HalLedBlink ( HAL_LED_4, 0, 50, 500 );
  236. }
  237. // Initialize the ZDO callback function pointers zdoCBFunc[]
  238. ZDApp_InitZdoCBFunc();
  239. ZDApp_RegisterCBs();
  240. } /* ZDApp_Init() */
  241. /*********************************************************************
  242. * @fn ZDApp_SecInit
  243. *
  244. * @brief ZDApp initialize security.
  245. *
  246. * @param state - device initialization state
  247. *
  248. * @return none
  249. */
  250. void ZDApp_SecInit( uint8 state )
  251. {
  252. uint8 zgPreConfigKey[SEC_KEY_LEN];
  253. if ( ZG_SECURE_ENABLED && ZG_BUILD_COORDINATOR_TYPE && ZG_DEVICE_COORDINATOR_TYPE )
  254. {
  255. // Set the Trust Center bit
  256. ZDO_Config_Node_Descriptor.ServerMask |= PRIM_TRUST_CENTER;
  257. }
  258. if ( ZG_CHECK_SECURITY_MODE == ZG_SECURITY_PRO_HIGH )
  259. {
  260. ZDO_Config_Node_Descriptor.CapabilityFlags |= CAPINFO_SECURITY_CAPABLE;
  261. }
  262. // Initialize ZigBee Device Security Manager
  263. ZDSecMgrInit(state);
  264. if ( ZG_SECURE_ENABLED )
  265. {
  266. if ( state != ZDO_INITDEV_RESTORED_NETWORK_STATE )
  267. {
  268. nwkFrameCounter = 0;
  269. if( _NIB.nwkKeyLoaded == FALSE )
  270. {
  271. if ( ( ZG_BUILD_COORDINATOR_TYPE && ZG_DEVICE_COORDINATOR_TYPE ) ||
  272. ( ( zgSecurityMode == ZG_SECURITY_RESIDENTIAL ) && zgPreConfigKeys ) )
  273. {
  274. ZDSecMgrReadKeyFromNv(ZCD_NV_PRECFGKEY, zgPreConfigKey);
  275. SSP_UpdateNwkKey( zgPreConfigKey, 0);
  276. SSP_SwitchNwkKey( 0 );
  277. // clear local copy of key
  278. osal_memset(zgPreConfigKey, 0x00, SEC_KEY_LEN);
  279. }
  280. }
  281. }
  282. }
  283. }
  284. /*********************************************************************
  285. * @fn ZDApp_event_loop()
  286. *
  287. * @brief Main event loop for Zigbee device objects task. This function
  288. * should be called at periodic intervals.
  289. *
  290. * @param task_id - Task ID
  291. * @param events - Bitmap of events
  292. *
  293. * @return none
  294. */
  295. UINT16 ZDApp_event_loop( uint8 task_id, UINT16 events )
  296. {
  297. uint8 *msg_ptr;
  298. if ( events & SYS_EVENT_MSG )//系统消息事件
  299. {
  300. while ( (msg_ptr = osal_msg_receive( ZDAppTaskID )) )
  301. {
  302. ZDApp_ProcessOSALMsg( (osal_event_hdr_t *)msg_ptr );
  303. // Release the memory
  304. osal_msg_deallocate( msg_ptr );
  305. }
  306. // Return unprocessed events
  307. return (events ^ SYS_EVENT_MSG);
  308. }
  309. if ( events & ZDO_NETWORK_INIT )//网络事件处理
  310. {
  311. // Initialize apps and start the network
  312. devState = DEV_INIT;
  313. osal_set_event( ZDAppTaskID, ZDO_STATE_CHANGE_EVT );
  314. ZDO_StartDevice( (uint8)ZDO_Config_Node_Descriptor.LogicalType, devStartMode,
  315. DEFAULT_BEACON_ORDER, DEFAULT_SUPERFRAME_ORDER );
  316. // Return unprocessed events
  317. return (events ^ ZDO_NETWORK_INIT);
  318. }
  319. if ( ZSTACK_ROUTER_BUILD )
  320. {
  321. if ( events & ZDO_NETWORK_START )
  322. {
  323. ZDApp_NetworkStartEvt();
  324. // Return unprocessed events
  325. return (events ^ ZDO_NETWORK_START);
  326. }
  327. if ( events & ZDO_ROUTER_START )
  328. {
  329. if ( nwkStatus == ZSuccess )
  330. {
  331. if ( devState == DEV_END_DEVICE )
  332. devState = DEV_ROUTER;
  333. osal_pwrmgr_device( PWRMGR_ALWAYS_ON );
  334. }
  335. else
  336. {
  337. // remain as end device!!
  338. }
  339. osal_set_event( ZDAppTaskID, ZDO_STATE_CHANGE_EVT );
  340. // Return unprocessed events
  341. return (events ^ ZDO_ROUTER_START);
  342. }
  343. }
  344. if ( events & ZDO_STATE_CHANGE_EVT )//ZDO状态改变事件
  345. {
  346. ZDO_UpdateNwkStatus( devState );
  347. // At start up, do one MTO route discovery if the device is a concentrator
  348. if ( zgConcentratorEnable == TRUE )
  349. {
  350. // Start next event
  351. osal_start_timerEx( NWK_TaskID, NWK_MTO_RTG_REQ_EVT, 100 );
  352. }
  353. // Return unprocessed events
  354. return (events ^ ZDO_STATE_CHANGE_EVT);
  355. }
  356. if ( events & ZDO_COMMAND_CNF )
  357. {
  358. // User defined logic
  359. // Return unprocessed events
  360. return (events ^ ZDO_COMMAND_CNF);
  361. }
  362. if ( events & ZDO_NWK_UPDATE_NV )
  363. {
  364. ZDApp_SaveNetworkStateEvt();
  365. // Return unprocessed events
  366. return (events ^ ZDO_NWK_UPDATE_NV);
  367. }
  368. if ( events & ZDO_DEVICE_RESET )//设备重启事件
  369. {
  370. #ifdef ZBA_FALLBACK_NWKKEY
  371. if ( devState == DEV_END_DEVICE_UNAUTH )
  372. {
  373. ZDSecMgrFallbackNwkKey();
  374. }
  375. else
  376. #endif
  377. {
  378. // Set the NV startup option to force a "new" join.
  379. zgWriteStartupOptions( ZG_STARTUP_SET, ZCD_STARTOPT_DEFAULT_NETWORK_STATE );
  380. // The device has been in the UNAUTH state, so reset
  381. // Note: there will be no return from this call
  382. SystemResetSoft();
  383. }
  384. }
  385. if ( ZG_SECURE_ENABLED )
  386. {
  387. return ( ZDApp_ProcessSecEvent( task_id, events ) );
  388. }
  389. else
  390. {
  391. // Discard or make more handlers
  392. return 0;
  393. }
  394. }
  395. /*********************************************************************
  396. * @fn ZDApp_ProcessSecEvent()
  397. *
  398. * @brief Process incoming security events.
  399. *
  400. * @param task_id - Task ID
  401. * @param events - Bitmap of events
  402. *
  403. * @return none
  404. */
  405. UINT16 ZDApp_ProcessSecEvent( uint8 task_id, UINT16 events )
  406. {
  407. (void)task_id; // Intentionally unreferenced parameter
  408. if ( ZSTACK_ROUTER_BUILD )
  409. {
  410. if ( events & ZDO_NEW_DEVICE )
  411. {
  412. // process the new device event
  413. if ( ZDSecMgrNewDeviceEvent() == TRUE )
  414. {
  415. osal_start_timerEx( ZDAppTaskID, ZDO_NEW_DEVICE, 1000 );
  416. }
  417. // Return unprocessed events
  418. return (events ^ ZDO_NEW_DEVICE);
  419. }
  420. }
  421. if ( (ZG_CHECK_SECURITY_MODE == ZG_SECURITY_PRO_HIGH)
  422. || (ZG_CHECK_SECURITY_MODE == ZG_SECURITY_SE_STANDARD) )
  423. {
  424. if ( ZG_BUILD_COORDINATOR_TYPE && ZG_DEVICE_COORDINATOR_TYPE )
  425. {
  426. if ( events & ZDO_SECMGR_EVENT )
  427. {
  428. ZDSecMgrEvent();
  429. // Return unprocessed events
  430. return (events ^ ZDO_SECMGR_EVENT);
  431. }
  432. }
  433. }
  434. if ( events & ZDO_DEVICE_AUTH )
  435. {
  436. ZDApp_DeviceAuthEvt();
  437. // Return unprocessed events
  438. return (events ^ ZDO_DEVICE_AUTH);
  439. }
  440. if ( events & ZDO_FRAMECOUNTER_CHANGE )
  441. {
  442. if ( nwkFrameCounterChanges++ > MAX_NWK_FRAMECOUNTER_CHANGES )
  443. {
  444. ZDApp_SaveNwkKey();
  445. }
  446. // Return unprocessed events
  447. return (events ^ ZDO_FRAMECOUNTER_CHANGE);
  448. }
  449. if ( events & ZDO_APS_FRAMECOUNTER_CHANGE )
  450. {
  451. #if defined (NV_RESTORE)
  452. ZDSecMgrSaveApsLinkKey();
  453. #endif // (NV_RESTORE)
  454. // Return unprocessed events
  455. return (events ^ ZDO_APS_FRAMECOUNTER_CHANGE);
  456. }
  457. if ( events & ZDO_TCLK_FRAMECOUNTER_CHANGE )
  458. {
  459. ZDSecMgrSaveTCLinkKey();
  460. // Return unprocessed events
  461. return (events ^ ZDO_TCLK_FRAMECOUNTER_CHANGE);
  462. }
  463. // Discard or make more handlers
  464. return 0;
  465. }
  466. /*********************************************************************
  467. * Application Functions
  468. */
  469. /*********************************************************************
  470. * @fn ZDOInitDevice
  471. *
  472. * @brief Start the device in the network. This function will read
  473. * ZCD_NV_STARTUP_OPTION (NV item) to determine whether or not to
  474. * restore the network state of the device.
  475. *
  476. * @param startDelay - timeDelay to start device (in milliseconds).
  477. * There is a jitter added to this delay:
  478. * ((NWK_START_DELAY + startDelay)
  479. * + (osal_rand() & EXTENDED_JOINING_RANDOM_MASK))
  480. * When startDelay is set to ZDO_INIT_HOLD_NWK_START
  481. * this function will hold the network init. Application
  482. * can start the device.
  483. *
  484. * NOTE: If the application would like to force a "new" join, the
  485. * application should set the ZCD_STARTOPT_DEFAULT_NETWORK_STATE
  486. * bit in the ZCD_NV_STARTUP_OPTION NV item before calling
  487. * this function. "new" join means to not restore the network
  488. * state of the device. Use zgWriteStartupOptions() to set these
  489. * options.
  490. *
  491. * @return
  492. * ZDO_INITDEV_RESTORED_NETWORK_STATE - The device's network state was
  493. * restored.
  494. * ZDO_INITDEV_NEW_NETWORK_STATE - The network state was initialized.
  495. * This could mean that ZCD_NV_STARTUP_OPTION said to not restore, or
  496. * it could mean that there was no network state to restore.
  497. * ZDO_INITDEV_LEAVE_NOT_STARTED - Before the reset, a network leave was issued
  498. * with the rejoin option set to TRUE. So, the device was not
  499. * started in the network (one time only). The next time this
  500. * function is called it will start.
  501. */
  502. uint8 ZDOInitDevice( uint16 startDelay )
  503. {
  504. uint8 networkStateNV = ZDO_INITDEV_NEW_NETWORK_STATE;
  505. uint16 extendedDelay = 0;
  506. if ( devState == DEV_HOLD )
  507. {
  508. // Initialize the RAM items table, in case an NV item has been updated.
  509. zgInitItems( FALSE );
  510. }
  511. ZDConfig_InitDescriptors();
  512. //devtag.071807.todo - fix this temporary solution
  513. _NIB.CapabilityFlags = ZDO_Config_Node_Descriptor.CapabilityFlags;
  514. #if defined ( NV_RESTORE )
  515. // Get Keypad directly to see if a reset nv is needed.
  516. // Hold down the SW_BYPASS_NV key (defined in OnBoard.h)
  517. // while booting to skip past NV Restore.
  518. if ( HalKeyRead() == SW_BYPASS_NV )
  519. networkStateNV = ZDO_INITDEV_NEW_NETWORK_STATE;
  520. else
  521. {
  522. // Determine if NV should be restored
  523. networkStateNV = ZDApp_ReadNetworkRestoreState();
  524. }
  525. if ( networkStateNV == ZDO_INITDEV_RESTORED_NETWORK_STATE )
  526. {
  527. networkStateNV = ZDApp_RestoreNetworkState();
  528. }
  529. else
  530. {
  531. // Wipe out the network state in NV
  532. NLME_InitNV();
  533. NLME_SetDefaultNV();
  534. // clear NWK key values
  535. ZDSecMgrClearNVKeyValues();
  536. }
  537. #endif
  538. if ( networkStateNV == ZDO_INITDEV_NEW_NETWORK_STATE )
  539. {
  540. ZDAppDetermineDeviceType();
  541. // Only delay if joining network - not restoring network state
  542. extendedDelay = (uint16)((NWK_START_DELAY + startDelay)
  543. + (osal_rand() & EXTENDED_JOINING_RANDOM_MASK));
  544. }
  545. // Initialize the security for type of device
  546. ZDApp_SecInit( networkStateNV );
  547. if( ZDO_INIT_HOLD_NWK_START != startDelay )
  548. {
  549. devState = DEV_INIT; // Remove the Hold state
  550. // Initialize leave control logic
  551. ZDApp_LeaveCtrlInit();
  552. // Check leave control reset settings
  553. ZDApp_LeaveCtrlStartup( &devState, &startDelay );
  554. // Leave may make the hold state come back
  555. if ( devState == DEV_HOLD )
  556. {
  557. // Set the NV startup option to force a "new" join.
  558. zgWriteStartupOptions( ZG_STARTUP_SET, ZCD_STARTOPT_DEFAULT_NETWORK_STATE );
  559. // Notify the applications
  560. osal_set_event( ZDAppTaskID, ZDO_STATE_CHANGE_EVT );
  561. return ( ZDO_INITDEV_LEAVE_NOT_STARTED ); // Don't join - (one time).
  562. }
  563. // Trigger the network start
  564. ZDApp_NetworkInit( extendedDelay );
  565. }
  566. // set broadcast address mask to support broadcast filtering
  567. NLME_SetBroadcastFilter( ZDO_Config_Node_Descriptor.CapabilityFlags );
  568. return ( networkStateNV );
  569. }
  570. /*********************************************************************
  571. * @fn ZDApp_ReadNetworkRestoreState
  572. *
  573. * @brief Read the ZCD_NV_STARTUP_OPTION NV Item to state whether
  574. * or not to restore the network state.
  575. * If the read value has the ZCD_STARTOPT_DEFAULT_NETWORK_STATE
  576. * bit set return the ZDO_INITDEV_NEW_NETWORK_STATE.
  577. *
  578. * @param none
  579. *
  580. * @return ZDO_INITDEV_NEW_NETWORK_STATE
  581. * or ZDO_INITDEV_RESTORED_NETWORK_STATE based on whether or
  582. * not ZCD_STARTOPT_DEFAULT_NETWORK_STATE bit is set in
  583. * ZCD_NV_STARTUP_OPTION
  584. */
  585. uint8 ZDApp_ReadNetworkRestoreState( void )
  586. {
  587. uint8 networkStateNV = ZDO_INITDEV_RESTORED_NETWORK_STATE;
  588. // Look for the New Network State option.
  589. if ( zgReadStartupOptions() & ZCD_STARTOPT_DEFAULT_NETWORK_STATE )
  590. {
  591. networkStateNV = ZDO_INITDEV_NEW_NETWORK_STATE;
  592. }
  593. return ( networkStateNV );
  594. }
  595. /*********************************************************************
  596. * @fn ZDAppDetermineDeviceType()
  597. *
  598. * @brief Determines the type of device to start.
  599. *
  600. * Looks at zgDeviceLogicalType and determines what type of
  601. * device to start. The types are:
  602. * ZG_DEVICETYPE_COORDINATOR
  603. * ZG_DEVICETYPE_ROUTER
  604. * ZG_DEVICETYPE_ENDDEVICE
  605. *
  606. * @param none
  607. *
  608. * @return none
  609. */
  610. void ZDAppDetermineDeviceType( void )
  611. {
  612. if ( zgDeviceLogicalType == ZG_DEVICETYPE_COORDINATOR )
  613. {
  614. devStartMode = MODE_HARD; // Start as a coordinator
  615. ZDO_Config_Node_Descriptor.LogicalType = NODETYPE_COORDINATOR;
  616. }
  617. else
  618. {
  619. if ( zgDeviceLogicalType == ZG_DEVICETYPE_ROUTER )
  620. ZDO_Config_Node_Descriptor.LogicalType = NODETYPE_ROUTER;
  621. else if ( zgDeviceLogicalType == ZG_DEVICETYPE_ENDDEVICE )
  622. ZDO_Config_Node_Descriptor.LogicalType = NODETYPE_DEVICE;
  623. // If AIB_apsUseExtendedPANID is set to a non-zero value by commissioning
  624. // The device shall do rejoin the network. Otherwise, do normal join
  625. if ( nwk_ExtPANIDValid( AIB_apsUseExtendedPANID ) == false )
  626. {
  627. devStartMode = MODE_JOIN; // Assume joining
  628. }
  629. else
  630. {
  631. devStartMode = MODE_REJOIN;
  632. }
  633. }
  634. }
  635. /*********************************************************************
  636. * @fn ZDApp_NetworkStartEvt()
  637. *
  638. * @brief Process the Network Start Event
  639. *
  640. * @param none
  641. *
  642. * @return none
  643. */
  644. void ZDApp_NetworkStartEvt( void )
  645. {
  646. if ( nwkStatus == ZSuccess )
  647. {
  648. // Successfully started a ZigBee network
  649. if ( devState == DEV_COORD_STARTING )
  650. {
  651. devState = DEV_ZB_COORD;
  652. }
  653. osal_pwrmgr_device( PWRMGR_ALWAYS_ON );
  654. osal_set_event( ZDAppTaskID, ZDO_STATE_CHANGE_EVT );
  655. }
  656. else
  657. {
  658. // Try again with a higher energy threshold !!
  659. if ( ( NLME_GetEnergyThreshold() + ENERGY_SCAN_INCREMENT ) < 0xff )
  660. {
  661. NLME_SetEnergyThreshold( (uint8)(NLME_GetEnergyThreshold() + ENERGY_SCAN_INCREMENT) );
  662. osal_set_event( ZDAppTaskID, ZDO_NETWORK_INIT );
  663. }
  664. else
  665. {
  666. // Failed to start network. Enter a dormant state (until user intervenes)
  667. devState = DEV_INIT;
  668. osal_set_event( ZDAppTaskID, ZDO_STATE_CHANGE_EVT );
  669. }
  670. }
  671. }
  672. /*********************************************************************
  673. * @fn ZDApp_DeviceAuthEvt()
  674. *
  675. * @brief Process the Device Authentic Event
  676. *
  677. * @param none
  678. *
  679. * @return none
  680. */
  681. void ZDApp_DeviceAuthEvt( void )
  682. {
  683. // received authentication from trust center
  684. if ( devState == DEV_END_DEVICE_UNAUTH )
  685. {
  686. // Stop the reset timer so it doesn't reset
  687. ZDApp_ResetTimerCancel();
  688. devState = DEV_END_DEVICE;
  689. osal_set_event( ZDAppTaskID, ZDO_STATE_CHANGE_EVT );
  690. // Set the Power Manager Device
  691. #if defined ( POWER_SAVING )
  692. osal_pwrmgr_device( PWRMGR_BATTERY );
  693. #endif
  694. if ( ZSTACK_ROUTER_BUILD )
  695. {
  696. if ( ZDO_Config_Node_Descriptor.LogicalType != NODETYPE_DEVICE )
  697. {
  698. // NOTE: first two parameters are not used, see NLMEDE.h for details
  699. NLME_StartRouterRequest( 0, 0, false );
  700. }
  701. }
  702. // Notify to save info into NV
  703. ZDApp_NVUpdate();
  704. // Save off the security
  705. ZDApp_SaveNwkKey();
  706. ZDApp_AnnounceNewAddress();
  707. if ( (ZDO_Config_Node_Descriptor.CapabilityFlags & CAPINFO_RCVR_ON_IDLE) == 0 )
  708. {
  709. NLME_SetPollRate( ZDApp_SavedPollRate );
  710. }
  711. }
  712. else
  713. {
  714. ZDApp_NVUpdate();
  715. }
  716. }
  717. /*********************************************************************
  718. * @fn ZDApp_SaveNetworkStateEvt()
  719. *
  720. * @brief Process the Save the Network State Event
  721. *
  722. * @param none
  723. *
  724. * @return none
  725. */
  726. void ZDApp_SaveNetworkStateEvt( void )
  727. {
  728. #if defined ( NV_RESTORE )
  729. #if defined ( NV_TURN_OFF_RADIO )
  730. // Turn off the radio's receiver during an NV update
  731. uint8 RxOnIdle;
  732. uint8 x = false;
  733. ZMacGetReq( ZMacRxOnIdle, &RxOnIdle );
  734. ZMacSetReq( ZMacRxOnIdle, &x );
  735. #endif
  736. // Update the Network State in NV
  737. NLME_UpdateNV( NWK_NV_NIB_ENABLE |
  738. NWK_NV_DEVICELIST_ENABLE |
  739. NWK_NV_BINDING_ENABLE |
  740. NWK_NV_ADDRMGR_ENABLE );
  741. // Reset the NV startup option to resume from NV by
  742. // clearing the "New" join option.
  743. zgWriteStartupOptions( FALSE, ZCD_STARTOPT_DEFAULT_NETWORK_STATE );
  744. #if defined ( NV_TURN_OFF_RADIO )
  745. ZMacSetReq( ZMacRxOnIdle, &RxOnIdle );
  746. #endif
  747. #endif // NV_RESTORE
  748. }
  749. /*********************************************************************
  750. * @fn ZDApp_RestoreNetworkState()
  751. *
  752. * @brief This function will restore the network state of the
  753. * device if the network state is stored in NV.
  754. *
  755. * @param none
  756. *
  757. * @return
  758. * ZDO_INITDEV_RESTORED_NETWORK_STATE - The device's network state was
  759. * restored.
  760. * ZDO_INITDEV_NEW_NETWORK_STATE - The network state was not used.
  761. * This could mean that zgStartupOption said to not restore, or
  762. * it could mean that there was no network state to restore.
  763. *
  764. */
  765. uint8 ZDApp_RestoreNetworkState( void )
  766. {
  767. uint8 nvStat;
  768. // Initialize NWK NV items
  769. nvStat = NLME_InitNV();
  770. if ( nvStat != NV_OPER_FAILED )
  771. {
  772. if ( NLME_RestoreFromNV() )
  773. {
  774. // Are we a coordinator
  775. ZDAppNwkAddr.addr.shortAddr = NLME_GetShortAddr();
  776. if ( ZDAppNwkAddr.addr.shortAddr == 0 )
  777. ZDO_Config_Node_Descriptor.LogicalType = NODETYPE_COORDINATOR;
  778. devStartMode = MODE_RESUME;
  779. osal_cpyExtAddr( ZDO_UseExtendedPANID, _NIB.extendedPANID );
  780. }
  781. else
  782. nvStat = NV_ITEM_UNINIT;
  783. if ( ZG_SECURE_ENABLED )
  784. {
  785. nwkFrameCounterChanges = 0;
  786. if ( ZG_BUILD_COORDINATOR_TYPE && ZG_DEVICE_COORDINATOR_TYPE )
  787. {
  788. ZDApp_RestoreNwkKey();
  789. }
  790. }
  791. // The default for RxOnWhenIdle is true for Routers and false for end devices
  792. // [setup in the NLME_RestoreFromNV()]. Change it here if you want something
  793. // other than default.
  794. }
  795. if ( nvStat == ZSUCCESS )
  796. return ( ZDO_INITDEV_RESTORED_NETWORK_STATE );
  797. else
  798. return ( ZDO_INITDEV_NEW_NETWORK_STATE );
  799. }
  800. /*********************************************************************
  801. * @fn ZDApp_InitUserDesc()
  802. *
  803. * @brief Initialize the User Descriptor, the descriptor is read from NV
  804. * when needed. If you want to initialize the User descriptor to
  805. * something other than all zero, do it here.
  806. *
  807. * @param none
  808. *
  809. * @return none
  810. */
  811. void ZDApp_InitUserDesc( void )
  812. {
  813. UserDescriptorFormat_t ZDO_DefaultUserDescriptor;
  814. // Initialize the User Descriptor, the descriptor is read from NV
  815. // when needed. If you want to initialize the User descriptor to something
  816. // other than all zero, do it here.
  817. osal_memset( &ZDO_DefaultUserDescriptor, 0, sizeof( UserDescriptorFormat_t ) );
  818. if ( ZSUCCESS == osal_nv_item_init( ZCD_NV_USERDESC,
  819. sizeof(UserDescriptorFormat_t), (void*)&ZDO_DefaultUserDescriptor ) )
  820. {
  821. if ( ZSUCCESS == osal_nv_read( ZCD_NV_USERDESC, 0,
  822. sizeof(UserDescriptorFormat_t), (void*)&ZDO_DefaultUserDescriptor ) )
  823. {
  824. if ( ZDO_DefaultUserDescriptor.len != 0 )
  825. {
  826. ZDO_Config_Node_Descriptor.UserDescAvail = TRUE;
  827. }
  828. }
  829. }
  830. }
  831. /*********************************************************************
  832. * @fn ZDAppCheckForHoldKey()
  833. *
  834. * @brief Check for key to set the device into Hold Auto Start
  835. *
  836. * @param none
  837. *
  838. * @return none
  839. */
  840. void ZDAppCheckForHoldKey( void )
  841. {
  842. #if (defined HAL_KEY) && (HAL_KEY == TRUE)
  843. // Get Keypad directly to see if a HOLD_START is needed.
  844. // Hold down the SW_BYPASS_START key (see OnBoard.h)
  845. // while booting to avoid starting up the device.
  846. // if ( HalKeyRead () == SW_BYPASS_START)
  847. // {
  848. // // Change the device state to HOLD on start up
  849. // devState = DEV_HOLD;
  850. // }
  851. #endif // HAL_KEY
  852. }
  853. /*********************************************************************
  854. * @fn ZDApp_ProcessOSALMsg()
  855. *
  856. * @brief Process the incoming task message.
  857. *
  858. * @param msgPtr - message to process
  859. *
  860. * @return none
  861. */
  862. void ZDApp_ProcessOSALMsg( osal_event_hdr_t *msgPtr )
  863. {
  864. // Data Confirmation message fields
  865. uint8 sentEP; // This should always be 0
  866. uint8 sentStatus;
  867. afDataConfirm_t *afDataConfirm;
  868. uint8 tmp;
  869. switch ( msgPtr->event )
  870. {
  871. // Incoming ZDO Message
  872. case AF_INCOMING_MSG_CMD:
  873. ZDP_IncomingData( (afIncomingMSGPacket_t *)msgPtr );
  874. break;
  875. case ZDO_CB_MSG:
  876. ZDApp_ProcessMsgCBs( (zdoIncomingMsg_t *)msgPtr );
  877. break;
  878. case AF_DATA_CONFIRM_CMD:
  879. // This message is received as a confirmation of a data packet sent.
  880. // The status is of ZStatus_t type [defined in NLMEDE.h]
  881. // The message fields are defined in AF.h
  882. afDataConfirm = (afDataConfirm_t *)msgPtr;
  883. sentEP = afDataConfirm->endpoint;
  884. sentStatus = afDataConfirm->hdr.status;
  885. // Action taken when confirmation is received.
  886. #if defined ( ZIGBEE_FREQ_AGILITY )
  887. if ( pZDNwkMgr_ProcessDataConfirm )
  888. pZDNwkMgr_ProcessDataConfirm( afDataConfirm );
  889. #endif
  890. (void)sentEP;
  891. (void)sentStatus;
  892. break;
  893. case ZDO_NWK_DISC_CNF:
  894. if (devState != DEV_NWK_DISC)
  895. break;
  896. if ( ZG_BUILD_JOINING_TYPE && ZG_DEVICE_JOINING_TYPE )
  897. {
  898. // Process the network discovery scan results and choose a parent
  899. // device to join/rejoin itself
  900. networkDesc_t *pChosenNwk;
  901. if ( ( (pChosenNwk = ZDApp_NwkDescListProcessing()) != NULL ) && (zdoDiscCounter > NUM_DISC_ATTEMPTS) )
  902. {
  903. if ( devStartMode == MODE_JOIN )
  904. {
  905. devState = DEV_NWK_JOINING;
  906. ZDApp_NodeProfileSync( pChosenNwk->stackProfile);
  907. if ( NLME_JoinRequest( pChosenNwk->extendedPANID, pChosenNwk->panId,
  908. pChosenNwk->logicalChannel,
  909. ZDO_Config_Node_Descriptor.CapabilityFlags,
  910. pChosenNwk->chosenRouter, pChosenNwk->chosenRouterDepth ) != ZSuccess )
  911. {
  912. ZDApp_NetworkInit( (uint16)(NWK_START_DELAY
  913. + ((uint16)(osal_rand()& EXTENDED_JOINING_RANDOM_MASK))) );
  914. }
  915. } // if ( devStartMode == MODE_JOIN )
  916. else if ( devStartMode == MODE_REJOIN )
  917. {
  918. devState = DEV_NWK_REJOIN;
  919. // Before trying to do rejoin, check if the device has a valid short address
  920. // If not, generate a random short address for itself
  921. if ( _NIB.nwkDevAddress == INVALID_NODE_ADDR )
  922. {
  923. _NIB.nwkDevAddress = osal_rand();
  924. ZMacSetReq( ZMacShortAddress, (byte*)&_NIB.nwkDevAddress );
  925. }
  926. if ( ZG_SECURE_ENABLED )
  927. {
  928. ZDApp_RestoreNwkKey();
  929. }
  930. // Check if the device has a valid PanID, if not, set it to the discovered Pan
  931. if ( _NIB.nwkPanId == INVALID_PAN_ID )
  932. {
  933. _NIB.nwkPanId = pChosenNwk->panId;
  934. ZMacSetReq( ZMacPanId, (byte*)&(_NIB.nwkPanId) );
  935. }
  936. tmp = true;
  937. ZMacSetReq( ZMacRxOnIdle, &tmp ); // Set receiver always on during rejoin
  938. if ( NLME_ReJoinRequest( ZDO_UseExtendedPANID, pChosenNwk->logicalChannel) != ZSuccess )
  939. {
  940. ZDApp_NetworkInit( (uint16)(NWK_START_DELAY
  941. + ((uint16)(osal_rand()& EXTENDED_JOINING_RANDOM_MASK))) );
  942. }
  943. } // else if ( devStartMode == MODE_REJOIN )
  944. if ( ZDO_Config_Node_Descriptor.CapabilityFlags & CAPINFO_RCVR_ON_IDLE )
  945. {
  946. // The receiver is on, turn network layer polling off.
  947. NLME_SetPollRate( 0 );
  948. NLME_SetQueuedPollRate( 0 );
  949. NLME_SetResponseRate( 0 );
  950. }
  951. else
  952. {
  953. if ( (ZG_SECURE_ENABLED) && (devStartMode == MODE_JOIN) )
  954. {
  955. ZDApp_SavedPollRate = zgPollRate;
  956. NLME_SetPollRate( zgRejoinPollRate );
  957. }
  958. }
  959. }
  960. else
  961. {
  962. if ( continueJoining )
  963. {
  964. #if defined ( MANAGED_SCAN )
  965. ZDApp_NetworkInit( MANAGEDSCAN_DELAY_BETWEEN_SCANS );
  966. #else
  967. zdoDiscCounter++;
  968. ZDApp_NetworkInit( (uint16)(BEACON_REQUEST_DELAY
  969. + ((uint16)(osal_rand()& BEACON_REQ_DELAY_MASK))) );
  970. #endif
  971. }
  972. }
  973. }
  974. break;
  975. case ZDO_NWK_JOIN_IND:
  976. if ( ZG_BUILD_JOINING_TYPE && ZG_DEVICE_JOINING_TYPE )
  977. {
  978. ZDApp_ProcessNetworkJoin();
  979. }
  980. break;
  981. case ZDO_NWK_JOIN_REQ:
  982. if ( ZG_BUILD_JOINING_TYPE && ZG_DEVICE_JOINING_TYPE )
  983. {
  984. retryCnt = 0;
  985. devStartMode = MODE_RESUME;
  986. _tmpRejoinState = true;
  987. osal_cpyExtAddr( ZDO_UseExtendedPANID, _NIB.extendedPANID );
  988. zgDefaultStartingScanDuration = BEACON_ORDER_60_MSEC;
  989. ZDApp_NetworkInit( 0 );
  990. }
  991. break;
  992. default:
  993. if ( ZG_SECURE_ENABLED )
  994. ZDApp_ProcessSecMsg( msgPtr );
  995. break;
  996. }
  997. }
  998. /*********************************************************************
  999. * @fn ZDApp_ProcessMsgCBs()
  1000. *
  1001. * @brief Process response messages
  1002. *
  1003. * @param none
  1004. *
  1005. * @return none
  1006. */
  1007. void ZDApp_ProcessMsgCBs( zdoIncomingMsg_t *inMsg )
  1008. {
  1009. switch ( inMsg->clusterID )
  1010. {
  1011. #if defined ( ZDO_NWKADDR_REQUEST ) || defined ( ZDO_IEEEADDR_REQUEST ) || defined ( REFLECTOR )
  1012. case NWK_addr_rsp:
  1013. case IEEE_addr_rsp:
  1014. {
  1015. ZDO_NwkIEEEAddrResp_t *pAddrRsp;
  1016. pAddrRsp = ZDO_ParseAddrRsp( inMsg );
  1017. if ( pAddrRsp )
  1018. {
  1019. if ( pAddrRsp->status == ZSuccess )
  1020. {
  1021. ZDO_UpdateAddrManager( pAddrRsp->nwkAddr, pAddrRsp->extAddr );
  1022. }
  1023. osal_mem_free( pAddrRsp );
  1024. }
  1025. }
  1026. break;
  1027. #endif
  1028. #if defined ( REFLECTOR )
  1029. case Bind_req:
  1030. case Unbind_req:
  1031. {
  1032. ZDO_BindUnbindReq_t bindReq;
  1033. ZDO_ParseBindUnbindReq( inMsg, &bindReq );
  1034. ZDO_ProcessBindUnbindReq( inMsg, &bindReq );
  1035. }
  1036. break;
  1037. #endif
  1038. #if ( ZG_BUILD_COORDINATOR_TYPE )
  1039. case Bind_rsp:
  1040. case Unbind_rsp:
  1041. if (ZG_DEVICE_COORDINATOR_TYPE && matchED)
  1042. {
  1043. ZDMatchSendState(
  1044. (uint8)((inMsg->clusterID == Bind_rsp) ? ZDMATCH_REASON_BIND_RSP : ZDMATCH_REASON_UNBIND_RSP),
  1045. ZDO_ParseBindRsp(inMsg), inMsg->TransSeq );
  1046. }
  1047. break;
  1048. case End_Device_Bind_req:
  1049. if (ZG_DEVICE_COORDINATOR_TYPE)
  1050. {
  1051. ZDEndDeviceBind_t bindReq;
  1052. ZDO_ParseEndDeviceBindReq( inMsg, &bindReq );
  1053. ZDO_MatchEndDeviceBind( &bindReq );
  1054. // Freeing the cluster lists - if allocated.
  1055. if ( bindReq.numInClusters )
  1056. osal_mem_free( bindReq.inClusters );
  1057. if ( bindReq.numOutClusters )
  1058. osal_mem_free( bindReq.outClusters );
  1059. }
  1060. break;
  1061. #endif
  1062. }
  1063. }
  1064. /*********************************************************************
  1065. * @fn ZDApp_RegisterCBs()
  1066. *
  1067. * @brief Process response messages
  1068. *
  1069. * @param none
  1070. *
  1071. * @return none
  1072. */
  1073. void ZDApp_RegisterCBs( void )
  1074. {
  1075. #if defined ( ZDO_IEEEADDR_REQUEST ) || defined ( REFLECTOR )
  1076. ZDO_RegisterForZDOMsg( ZDAppTaskID, IEEE_addr_rsp );
  1077. #endif
  1078. #if defined ( ZDO_NWKADDR_REQUEST ) || defined ( REFLECTOR )
  1079. ZDO_RegisterForZDOMsg( ZDAppTaskID, NWK_addr_rsp );
  1080. #endif
  1081. #if ZG_BUILD_COORDINATOR_TYPE
  1082. ZDO_RegisterForZDOMsg( ZDAppTaskID, Bind_rsp );
  1083. ZDO_RegisterForZDOMsg( ZDAppTaskID, Unbind_rsp );
  1084. ZDO_RegisterForZDOMsg( ZDAppTaskID, End_Device_Bind_req );
  1085. #endif
  1086. #if defined ( REFLECTOR )
  1087. ZDO_RegisterForZDOMsg( ZDAppTaskID, Bind_req );
  1088. ZDO_RegisterForZDOMsg( ZDAppTaskID, Unbind_req );
  1089. #endif
  1090. }
  1091. /*********************************************************************
  1092. * @fn ZDApp_ProcessSecMsg()
  1093. *
  1094. * @brief Process the incoming security message.
  1095. *
  1096. * @param msgPtr - message to process
  1097. *
  1098. * @return none
  1099. */
  1100. void ZDApp_ProcessSecMsg( osal_event_hdr_t *msgPtr )
  1101. {
  1102. switch ( msgPtr->event )
  1103. {
  1104. case ZDO_ESTABLISH_KEY_CFM:
  1105. if ( ZG_CHECK_SECURITY_MODE == ZG_SECURITY_PRO_HIGH )
  1106. {
  1107. ZDSecMgrEstablishKeyCfm( (ZDO_EstablishKeyCfm_t*)msgPtr );
  1108. }
  1109. break;
  1110. case ZDO_ESTABLISH_KEY_IND:
  1111. if ( ZG_CHECK_SECURITY_MODE == ZG_SECURITY_PRO_HIGH )
  1112. {
  1113. if ( ZG_BUILD_JOINING_TYPE && ZG_DEVICE_JOINING_TYPE )
  1114. {
  1115. ZDSecMgrEstablishKeyInd( (ZDO_EstablishKeyInd_t*)msgPtr );
  1116. }
  1117. }
  1118. break;
  1119. case ZDO_TRANSPORT_KEY_IND:
  1120. if ( ZG_BUILD_JOINING_TYPE && ZG_DEVICE_JOINING_TYPE )
  1121. {
  1122. ZDSecMgrTransportKeyInd( (ZDO_TransportKeyInd_t*)msgPtr );
  1123. }
  1124. break;
  1125. case ZDO_UPDATE_DEVICE_IND:
  1126. if ( ZG_BUILD_COORDINATOR_TYPE && ZG_DEVICE_COORDINATOR_TYPE )
  1127. {
  1128. ZDSecMgrUpdateDeviceInd( (ZDO_UpdateDeviceInd_t*)msgPtr );
  1129. }
  1130. break;
  1131. case ZDO_REMOVE_DEVICE_IND:
  1132. if ( ZG_BUILD_RTRONLY_TYPE && ( zgDeviceLogicalType == ZG_DEVICETYPE_ROUTER ) )
  1133. {
  1134. ZDSecMgrRemoveDeviceInd( (ZDO_RemoveDeviceInd_t*)msgPtr );
  1135. }
  1136. break;
  1137. case ZDO_REQUEST_KEY_IND:
  1138. if (( ZG_CHECK_SECURITY_MODE == ZG_SECURITY_PRO_HIGH ) ||
  1139. ( ZG_CHECK_SECURITY_MODE == ZG_SECURITY_SE_STANDARD ))
  1140. {
  1141. if ( ZG_BUILD_COORDINATOR_TYPE && ZG_DEVICE_COORDINATOR_TYPE )
  1142. {
  1143. ZDSecMgrRequestKeyInd( (ZDO_RequestKeyInd_t*)msgPtr );
  1144. }
  1145. }
  1146. break;
  1147. case ZDO_SWITCH_KEY_IND:
  1148. if ( ZG_BUILD_JOINING_TYPE && ZG_DEVICE_JOINING_TYPE )
  1149. {
  1150. ZDSecMgrSwitchKeyInd( (ZDO_SwitchKeyInd_t*)msgPtr );
  1151. }
  1152. break;
  1153. case ZDO_AUTHENTICATE_IND:
  1154. if ( ZG_CHECK_SECURITY_MODE == ZG_SECURITY_PRO_HIGH )
  1155. {
  1156. ZDSecMgrAuthenticateInd( (ZDO_AuthenticateInd_t*)msgPtr );
  1157. }
  1158. break;
  1159. case ZDO_AUTHENTICATE_CFM:
  1160. if ( ZG_CHECK_SECURITY_MODE == ZG_SECURITY_PRO_HIGH )
  1161. {
  1162. ZDSecMgrAuthenticateCfm( (ZDO_AuthenticateCfm_t*)msgPtr );
  1163. }
  1164. break;
  1165. default:
  1166. // Unsupported messages
  1167. break;
  1168. }
  1169. }
  1170. /*********************************************************************
  1171. * @fn ZDApp_ProcessNetworkJoin()
  1172. *
  1173. * @brief
  1174. *
  1175. * Save off the Network key information.
  1176. *
  1177. * @param none
  1178. *
  1179. * @return none
  1180. */
  1181. void ZDApp_ProcessNetworkJoin( void )
  1182. {
  1183. if ( (devState == DEV_NWK_JOINING) ||
  1184. ((devState == DEV_NWK_ORPHAN) &&
  1185. (ZDO_Config_Node_Descriptor.LogicalType == NODETYPE_ROUTER)) )
  1186. {
  1187. // Result of a Join attempt by this device.
  1188. if ( nwkStatus == ZSuccess )
  1189. {
  1190. osal_set_event( ZDAppTaskID, ZDO_STATE_CHANGE_EVT );
  1191. #if defined ( POWER_SAVING )
  1192. osal_pwrmgr_device( PWRMGR_BATTERY );
  1193. #endif
  1194. if ( ZG_SECURE_ENABLED && ( ZDApp_RestoreNwkKey() == false ) )
  1195. {
  1196. // wait for auth from trust center!!
  1197. devState = DEV_END_DEVICE_UNAUTH;
  1198. // Start the reset timer for MAX UNAUTH time
  1199. ZDApp_ResetTimerStart( 10000 );//MAX_DEVICE_UNAUTH_TIMEOUT );
  1200. }
  1201. else
  1202. {
  1203. if ( ZSTACK_ROUTER_BUILD )
  1204. {
  1205. if ( devState == DEV_NWK_ORPHAN
  1206. && ZDO_Config_Node_Descriptor.LogicalType != NODETYPE_DEVICE )
  1207. {
  1208. // Change NIB state to router for restore
  1209. _NIB.nwkState = NWK_ROUTER;
  1210. }
  1211. }
  1212. if ( devState == DEV_NWK_JOINING )
  1213. {
  1214. ZDApp_AnnounceNewAddress();
  1215. }
  1216. devState = DEV_END_DEVICE;
  1217. if ( ZSTACK_ROUTER_BUILD )
  1218. {
  1219. // NOTE: first two parameters are not used, see NLMEDE.h for details
  1220. if ( ZDO_Config_Node_Descriptor.LogicalType != NODETYPE_DEVICE )
  1221. {
  1222. NLME_StartRouterRequest( 0, 0, false );
  1223. }
  1224. }
  1225. }
  1226. }
  1227. else
  1228. {
  1229. if ( (devStartMode == MODE_RESUME) && (++retryCnt >= MAX_RESUME_RETRY) )
  1230. {
  1231. if ( _NIB.nwkPanId == 0xFFFF || _NIB.nwkPanId == INVALID_PAN_ID )
  1232. devStartMode = MODE_JOIN;
  1233. else
  1234. {
  1235. devStartMode = MODE_REJOIN;
  1236. _tmpRejoinState = true;
  1237. }
  1238. }
  1239. if ( (NLME_GetShortAddr() != INVALID_NODE_ADDR) ||
  1240. (_NIB.nwkDevAddress != INVALID_NODE_ADDR) )
  1241. {
  1242. uint16 addr = INVALID_NODE_ADDR;
  1243. // Invalidate nwk addr so end device does not use in its data reqs.
  1244. _NIB.nwkDevAddress = INVALID_NODE_ADDR;
  1245. ZMacSetReq( ZMacShortAddress, (uint8 *)&addr );
  1246. }
  1247. // Clear the neighbor Table and network discovery tables.
  1248. nwkNeighborInitTable();
  1249. NLME_NwkDiscTerm();
  1250. zdoDiscCounter = 1;
  1251. // ZDApp_NetworkInit( (uint16)
  1252. // ((NWK_START_DELAY * (osal_rand() & 0x0F)) +
  1253. // (NWK_START_DELAY * 5)) );
  1254. ZDApp_NetworkInit( (uint16)(NWK_START_DELAY
  1255. + ((uint16)(osal_rand()& EXTENDED_JOINING_RANDOM_MASK))) );
  1256. }
  1257. }
  1258. else if ( devState == DEV_NWK_ORPHAN || devState == DEV_NWK_REJOIN )
  1259. {
  1260. // results of an orphaning attempt by this device
  1261. if (nwkStatus == ZSuccess)
  1262. {
  1263. if ( ZG_SECURE_ENABLED )
  1264. {
  1265. ZDApp_RestoreNwkKey();
  1266. }
  1267. devState = DEV_END_DEVICE;
  1268. osal_set_event( ZDAppTaskID, ZDO_STATE_CHANGE_EVT );
  1269. // setup Power Manager Device
  1270. #if defined ( POWER_SAVING )
  1271. osal_pwrmgr_device( PWRMGR_BATTERY );
  1272. #endif
  1273. if ( ZDO_Config_Node_Descriptor.CapabilityFlags & CAPINFO_RCVR_ON_IDLE )
  1274. {
  1275. // The receiver is on, turn network layer polling off.
  1276. NLME_SetPollRate( 0 );
  1277. NLME_SetQueuedPollRate( 0 );
  1278. NLME_SetResponseRate( 0 );
  1279. }
  1280. if ( ZSTACK_ROUTER_BUILD )
  1281. {
  1282. // NOTE: first two parameters are not used, see NLMEDE.h for details
  1283. if ( ZDO_Config_Node_Descriptor.LogicalType != NODETYPE_DEVICE )
  1284. {
  1285. NLME_StartRouterRequest( 0, 0, false );
  1286. }
  1287. }
  1288. ZDApp_AnnounceNewAddress();
  1289. }
  1290. else
  1291. {
  1292. if ( devStartMode == MODE_RESUME )
  1293. {
  1294. if ( ++retryCnt <= MAX_RESUME_RETRY )
  1295. {
  1296. if ( _NIB.nwkPanId == 0xFFFF || _NIB.nwkPanId == INVALID_PAN_ID )
  1297. devStartMode = MODE_JOIN;
  1298. else
  1299. {
  1300. devStartMode = MODE_REJOIN;
  1301. _tmpRejoinState = true;
  1302. }
  1303. }
  1304. // Do a normal join to the network after certain times of rejoin retries
  1305. else if( AIB_apsUseInsecureJoin == true )
  1306. {
  1307. devStartMode = MODE_JOIN;
  1308. }
  1309. }
  1310. // Clear the neighbor Table and network discovery tables.
  1311. nwkNeighborInitTable();
  1312. NLME_NwkDiscTerm();
  1313. // setup a retry for later...
  1314. ZDApp_NetworkInit( (uint16)(NWK_START_DELAY
  1315. + (osal_rand()& EXTENDED_JOINING_RANDOM_MASK)) );
  1316. }
  1317. }
  1318. #if defined ( ZIGBEE_STOCHASTIC_ADDRESSING )
  1319. else
  1320. {
  1321. // Assume from address conflict
  1322. if ( _NIB.nwkAddrAlloc == NWK_ADDRESSING_STOCHASTIC )
  1323. {
  1324. // Notify the network
  1325. ZDApp_AnnounceNewAddress();
  1326. // Notify apps
  1327. osal_set_event( ZDAppTaskID, ZDO_STATE_CHANGE_EVT );
  1328. }
  1329. }
  1330. #endif
  1331. }
  1332. /*********************************************************************
  1333. * @fn ZDApp_SaveNwkKey()
  1334. *
  1335. * @brief Save off the Network key information.
  1336. *
  1337. * @param none
  1338. *
  1339. * @return none
  1340. */
  1341. void ZDApp_SaveNwkKey( void )
  1342. {
  1343. nwkActiveKeyItems keyItems;
  1344. SSP_ReadNwkActiveKey( &keyItems );
  1345. keyItems.frameCounter++;
  1346. osal_nv_write( ZCD_NV_NWKKEY, 0, sizeof( nwkActiveKeyItems ),
  1347. (void *)&keyItems );
  1348. nwkFrameCounterChanges = 0;
  1349. // Clear copy in RAM before return.
  1350. osal_memset( &keyItems, 0x00, sizeof(keyItems) );
  1351. }
  1352. /*********************************************************************
  1353. * @fn ZDApp_ResetNwkKey()
  1354. *
  1355. * @brief Reset the Network key information in NV.
  1356. *
  1357. * @param none
  1358. *
  1359. * @return none
  1360. */
  1361. void ZDApp_ResetNwkKey( void )
  1362. {
  1363. nwkActiveKeyItems keyItems;
  1364. osal_memset( &keyItems, 0, sizeof( nwkActiveKeyItems ) );
  1365. osal_nv_write( ZCD_NV_NWKKEY, 0, sizeof( nwkActiveKeyItems ),
  1366. (void *)&keyItems );
  1367. }
  1368. /*********************************************************************
  1369. * @fn ZDApp_RestoreNwkKey()
  1370. *
  1371. * @brief
  1372. *
  1373. * Save off the Network key information.
  1374. *
  1375. * @param none
  1376. *
  1377. * @return true if restored from NV, false if not
  1378. */
  1379. uint8 ZDApp_RestoreNwkKey( void )
  1380. {
  1381. nwkActiveKeyItems keyItems;
  1382. uint8 ret = false;
  1383. if ( osal_nv_read( ZCD_NV_NWKKEY, 0, sizeof(nwkActiveKeyItems), (void*)&keyItems )
  1384. == ZSUCCESS )
  1385. {
  1386. if ( keyItems.frameCounter > 0 )
  1387. {
  1388. // Restore the key information
  1389. keyItems.frameCounter += MAX_NWK_FRAMECOUNTER_CHANGES;
  1390. nwkFrameCounter = keyItems.frameCounter;
  1391. ret = true;
  1392. }
  1393. // Force a save for the first frame counter increment
  1394. nwkFrameCounterChanges = MAX_NWK_FRAMECOUNTER_CHANGES + 1;
  1395. }
  1396. // Clear copy in RAM before return.
  1397. osal_memset( &keyItems, 0x00, sizeof(keyItems) );
  1398. return ( ret );
  1399. }
  1400. /*********************************************************************
  1401. * @fn ZDApp_ResetTimerStart
  1402. *
  1403. * @brief Start the reset timer.
  1404. *
  1405. * @param delay - delay time(ms) before reset
  1406. *
  1407. * @return none
  1408. */
  1409. void ZDApp_ResetTimerStart( uint16 delay )
  1410. {
  1411. // Start the rest timer
  1412. osal_start_timerEx( ZDAppTaskID, ZDO_DEVICE_RESET, delay );
  1413. }
  1414. /*********************************************************************
  1415. * @fn ZDApp_ResetTimerCancel
  1416. *
  1417. * @brief Cancel the reset timer.
  1418. *
  1419. * @param none
  1420. *
  1421. * @return none
  1422. */
  1423. void ZDApp_ResetTimerCancel( void )
  1424. {
  1425. // Cancel the reset timer
  1426. osal_stop_timerEx( ZDAppTaskID, ZDO_DEVICE_RESET );
  1427. }
  1428. /*********************************************************************
  1429. * @fn ZDApp_LeaveCtrlInit
  1430. *
  1431. * @brief Initialize the leave control logic.
  1432. *
  1433. * @param none
  1434. *
  1435. * @return none
  1436. */
  1437. void ZDApp_LeaveCtrlInit( void )
  1438. {
  1439. uint8 status;
  1440. // Initialize control state
  1441. ZDApp_LeaveCtrl = ZDAPP_LEAVE_CTRL_INIT;
  1442. status = osal_nv_item_init( ZCD_NV_LEAVE_CTRL,
  1443. sizeof(ZDApp_LeaveCtrl),
  1444. &ZDApp_LeaveCtrl );
  1445. if ( status == ZSUCCESS )
  1446. {
  1447. // Read saved control
  1448. osal_nv_read( ZCD_NV_LEAVE_CTRL,
  1449. 0,
  1450. sizeof( uint8 ),
  1451. &ZDApp_LeaveCtrl);
  1452. }
  1453. }
  1454. /*********************************************************************
  1455. * @fn ZDApp_LeaveCtrlSet
  1456. *
  1457. * @brief Set the leave control logic.
  1458. *
  1459. * @param ra - reassociate flag
  1460. *
  1461. * @return none
  1462. */
  1463. void ZDApp_LeaveCtrlSet( uint8 ra )
  1464. {
  1465. ZDApp_LeaveCtrl = ZDAPP_LEAVE_CTRL_SET;
  1466. if ( ra == TRUE )
  1467. {
  1468. ZDApp_LeaveCtrl |= ZDAPP_LEAVE_CTRL_RA;
  1469. }
  1470. // Write the leave control
  1471. osal_nv_write( ZCD_NV_LEAVE_CTRL,
  1472. 0,
  1473. sizeof( uint8 ),
  1474. &ZDApp_LeaveCtrl);
  1475. }
  1476. /*********************************************************************
  1477. * @fn ZDApp_LeaveCtrlReset
  1478. *
  1479. * @brief Re-initialize the leave control logic.
  1480. *
  1481. * @param none
  1482. *
  1483. * @return none
  1484. */
  1485. void ZDApp_LeaveCtrlReset( void )
  1486. {
  1487. // Set leave control to initialized state
  1488. ZDApp_LeaveCtrl = ZDAPP_LEAVE_CTRL_INIT;
  1489. // Write initialized control
  1490. osal_nv_write( ZCD_NV_LEAVE_CTRL,
  1491. 0,
  1492. sizeof( uint8 ),
  1493. &ZDApp_LeaveCtrl);
  1494. }
  1495. /*********************************************************************
  1496. * @fn ZDApp_LeaveCtrlBypass
  1497. *
  1498. * @brief Check if NV restore should be skipped during a leave reset.
  1499. *
  1500. * @param none
  1501. *
  1502. * @return uint8 - (TRUE bypass:FALSE do not bypass)
  1503. */
  1504. uint8 ZDApp_LeaveCtrlBypass( void )
  1505. {
  1506. uint8 bypass;
  1507. if ( ZDApp_LeaveCtrl & ZDAPP_LEAVE_CTRL_SET )
  1508. {
  1509. bypass = TRUE;
  1510. }
  1511. else
  1512. {
  1513. bypass = FALSE;
  1514. }
  1515. return bypass;
  1516. }
  1517. /*********************************************************************
  1518. * @fn ZDApp_LeaveCtrlStartup
  1519. *
  1520. * @brief Check for startup conditions during a leave reset.
  1521. *
  1522. * @param state - devState_t determined by leave control logic
  1523. * @param startDelay - startup delay
  1524. *
  1525. * @return none
  1526. */
  1527. void ZDApp_LeaveCtrlStartup( devStates_t* state, uint16* startDelay )
  1528. {
  1529. *startDelay = 0;
  1530. if ( ZDApp_LeaveCtrl & ZDAPP_LEAVE_CTRL_SET )
  1531. {
  1532. if ( ZDApp_LeaveCtrl & ZDAPP_LEAVE_CTRL_RA )
  1533. {
  1534. *startDelay = LEAVE_RESET_DELAY;
  1535. }
  1536. else
  1537. {
  1538. *state = DEV_HOLD;
  1539. }
  1540. // Reset leave control logic
  1541. ZDApp_LeaveCtrlReset();
  1542. }
  1543. }
  1544. /*********************************************************************
  1545. * @fn ZDApp_LeaveReset
  1546. *
  1547. * @brief Setup a device reset due to a leave indication/confirm.
  1548. *
  1549. * @param ra - reassociate flag
  1550. *
  1551. * @return none
  1552. */
  1553. void ZDApp_LeaveReset( uint8 ra )
  1554. {
  1555. ZDApp_LeaveCtrlSet( ra );
  1556. ZDApp_ResetTimerStart( LEAVE_RESET_DELAY );
  1557. }
  1558. /*********************************************************************
  1559. * @fn ZDApp_LeaveUpdate
  1560. *
  1561. * @brief Update local device data related to leaving device.
  1562. *
  1563. * @param nwkAddr - NWK address of leaving device
  1564. * @param extAddr - EXT address of leaving device
  1565. * @param removeChildren - remove children of leaving device
  1566. *
  1567. * @return none
  1568. */
  1569. void ZDApp_LeaveUpdate( uint16 nwkAddr, uint8* extAddr,
  1570. uint8 removeChildren )
  1571. {
  1572. // Remove Apps Key for leaving device
  1573. ZDSecMgrDeviceRemoveByExtAddr(extAddr);
  1574. // Clear SECURITY bit from Address Manager
  1575. ZDSecMgrAddrClear( extAddr );
  1576. if ( pbindRemoveDev )
  1577. {
  1578. zAddrType_t devAddr;
  1579. // Remove bind entry and all related data
  1580. devAddr.addrMode = Addr64Bit;
  1581. osal_memcpy(devAddr.addr.extAddr, extAddr, Z_EXTADDR_LEN);
  1582. pbindRemoveDev(&devAddr);
  1583. }
  1584. // Remove if child
  1585. if ( ZSTACK_ROUTER_BUILD )
  1586. {
  1587. NLME_RemoveChild( extAddr, removeChildren );
  1588. }
  1589. // Remove Routing table related entry
  1590. RTG_RemoveRtgEntry( nwkAddr, 0 );
  1591. // Remove entry from neighborTable
  1592. nwkNeighborRemove( nwkAddr, _NIB.nwkPanId );
  1593. // Schedule to save data to NV
  1594. ZDApp_NwkWriteNVRequest();
  1595. }
  1596. /*********************************************************************
  1597. * @fn ZDApp_NetworkDiscoveryReq
  1598. *
  1599. * @brief Request a network discovery.
  1600. *
  1601. * @param scanChannels -
  1602. * @param scanDuration -
  1603. *
  1604. * @return ZStatus_t
  1605. */
  1606. ZStatus_t ZDApp_NetworkDiscoveryReq( uint32 scanChannels, uint8 scanDuration)
  1607. {
  1608. // Setup optional filters - tbd
  1609. // Request NLME network discovery
  1610. return NLME_NetworkDiscoveryRequest(scanChannels, scanDuration);
  1611. }
  1612. /*********************************************************************
  1613. * @fn ZDApp_JoinReq
  1614. *
  1615. * @brief Request the device to join a parent in a network.
  1616. *
  1617. * @param channel -
  1618. * @param panID -
  1619. *
  1620. * @return ZStatus_t
  1621. */
  1622. ZStatus_t ZDApp_JoinReq( uint8 channel, uint16 panID, uint8 *extendedPanID,
  1623. uint16 chosenParent, uint8 parentDepth, uint8 stackProfile )
  1624. {
  1625. // Sync up the node with the stack profile (In the case where a pro device
  1626. // joins a non-pro network, or verse versa)
  1627. ZDApp_NodeProfileSync( stackProfile);
  1628. // Request NLME Join Request
  1629. return NLME_JoinRequest(extendedPanID, panID,channel,
  1630. ZDO_Config_Node_Descriptor.CapabilityFlags,
  1631. chosenParent, parentDepth);
  1632. }
  1633. /*********************************************************************
  1634. * @fn ZDApp_DeviceConfigured
  1635. *
  1636. * @brief Check to see if the local device is configured (i.e., part
  1637. * of a network).
  1638. *
  1639. * @param none
  1640. *
  1641. * @return TRUE if configured. FALSE, otherwise.
  1642. */
  1643. uint8 ZDApp_DeviceConfigured( void )
  1644. {
  1645. uint16 nwkAddr = INVALID_NODE_ADDR;
  1646. osal_nv_read( ZCD_NV_NIB, osal_offsetof( nwkIB_t, nwkDevAddress ),
  1647. sizeof( uint16), &nwkAddr );
  1648. // Does the NIB have anything more than default?
  1649. return ( nwkAddr == INVALID_NODE_ADDR ? FALSE : TRUE );
  1650. }
  1651. /*********************************************************************
  1652. * CALLBACK FUNCTIONS
  1653. */
  1654. /*********************************************************************
  1655. * @fn ZDApp_SendEventMsg()
  1656. *
  1657. * @brief
  1658. *
  1659. * Sends a Network Join message
  1660. *
  1661. * @param cmd - command ID
  1662. * @param len - length (in bytes) of the buf field
  1663. * @param buf - buffer for the rest of the message.
  1664. *
  1665. * @return none
  1666. */
  1667. void ZDApp_SendEventMsg( uint8 cmd, uint8 len, uint8 *buf )
  1668. {
  1669. ZDApp_SendMsg( ZDAppTaskID, cmd, len, buf );
  1670. }
  1671. /*********************************************************************
  1672. * @fn ZDApp_SendMsg()
  1673. *
  1674. * @brief Sends a OSAL message
  1675. *
  1676. * @param taskID - Where to send the message
  1677. * @param cmd - command ID
  1678. * @param len - length (in bytes) of the buf field
  1679. * @param buf - buffer for the rest of the message.
  1680. *
  1681. * @return none
  1682. */
  1683. void ZDApp_SendMsg( uint8 taskID, uint8 cmd, uint8 len, uint8 *buf )
  1684. {
  1685. osal_event_hdr_t *msgPtr;
  1686. // Send the address to the task
  1687. msgPtr = (osal_event_hdr_t *)osal_msg_allocate( len );
  1688. if ( msgPtr )
  1689. {
  1690. if ( (len > 0) && (buf != NULL) )
  1691. osal_memcpy( msgPtr, buf, len );
  1692. msgPtr->event = cmd;
  1693. osal_msg_send( taskID, (uint8 *)msgPtr );
  1694. }
  1695. }
  1696. /*********************************************************************
  1697. * Call Back Functions from NWK - API
  1698. */
  1699. /*********************************************************************
  1700. * @fn ZDO_NetworkDiscoveryConfirmCB
  1701. *
  1702. * @brief This function returns a choice of PAN to join.
  1703. *
  1704. * @param status - return status of the nwk discovery confirm
  1705. *
  1706. * @return ZStatus_t
  1707. */
  1708. ZStatus_t ZDO_NetworkDiscoveryConfirmCB(uint8 status)
  1709. {
  1710. osal_event_hdr_t msg;
  1711. // If Scan is initiated by ZDO_MGMT_NWK_DISC_REQ
  1712. // Send ZDO_MGMT_NWK_DISC_RSP back
  1713. #if defined ( ZDO_MGMT_NWKDISC_RESPONSE )
  1714. if ( zdappMgmtNwkDiscReqInProgress )
  1715. {
  1716. zdappMgmtNwkDiscReqInProgress = false;
  1717. ZDO_FinishProcessingMgmtNwkDiscReq();
  1718. }
  1719. else
  1720. #endif
  1721. {
  1722. // Pass the confirm to another task if it registers the callback
  1723. // Otherwise, pass the confirm to ZDApp.
  1724. if (zdoCBFunc[ZDO_NWK_DISCOVERY_CNF_CBID] != NULL )
  1725. {
  1726. zdoCBFunc[ZDO_NWK_DISCOVERY_CNF_CBID]( (void*)&status );
  1727. }
  1728. else
  1729. {
  1730. // Otherwise, send scan confirm to ZDApp task to proceed
  1731. msg.status = ZDO_SUCCESS;
  1732. ZDApp_SendMsg( ZDAppTaskID, ZDO_NWK_DISC_CNF, sizeof(osal_event_hdr_t), (uint8 *)&msg );
  1733. }
  1734. }
  1735. return (ZSuccess);
  1736. } // ZDO_NetworkDiscoveryConfirmCB
  1737. /*********************************************************************
  1738. * @fn ZDApp_NwkDescListProcessing
  1739. *
  1740. * @brief This function process the network discovery result and select
  1741. * a parent device to join itself.
  1742. *
  1743. * @param none
  1744. *
  1745. * @return ZStatus_t
  1746. */
  1747. #define STACK_PROFILE_MAX 2
  1748. networkDesc_t* ZDApp_NwkDescListProcessing(void)
  1749. {
  1750. networkDesc_t *pNwkDesc;
  1751. uint8 i, ResultCount = 0;
  1752. uint8 stackProfile;
  1753. uint8 stackProfilePro;
  1754. uint8 selected;
  1755. // Count the number of nwk descriptors in the list
  1756. pNwkDesc = nwk_getNwkDescList();
  1757. while (pNwkDesc)
  1758. {
  1759. ResultCount++;
  1760. pNwkDesc = pNwkDesc->nextDesc;
  1761. }
  1762. // process discovery results
  1763. stackProfilePro = FALSE;
  1764. selected = FALSE;
  1765. for ( stackProfile = 0; stackProfile < STACK_PROFILE_MAX; stackProfile++ )
  1766. {
  1767. pNwkDesc = nwk_getNwkDescList();
  1768. for ( i = 0; i < ResultCount; i++, pNwkDesc = pNwkDesc->nextDesc )
  1769. {
  1770. if ( zgConfigPANID != 0xFFFF )
  1771. {
  1772. // PAN Id is preconfigured. check if it matches
  1773. if ( pNwkDesc->panId != zgConfigPANID )
  1774. continue;
  1775. }
  1776. if ( nwk_ExtPANIDValid( ZDO_UseExtendedPANID) == true )
  1777. {
  1778. // If the extended Pan ID is commissioned to a non zero value
  1779. // Only join the Pan that has match EPID
  1780. if ( osal_ExtAddrEqual( ZDO_UseExtendedPANID, pNwkDesc->extendedPANID) == false )
  1781. continue;
  1782. }
  1783. // check that network is allowing joining
  1784. if ( ZSTACK_ROUTER_BUILD )
  1785. {
  1786. if ( stackProfilePro == FALSE )
  1787. {
  1788. if ( !pNwkDesc->routerCapacity )
  1789. {
  1790. continue;
  1791. }
  1792. }
  1793. else
  1794. {
  1795. if ( !pNwkDesc->deviceCapacity )
  1796. {
  1797. continue;
  1798. }
  1799. }
  1800. }
  1801. else if ( ZSTACK_END_DEVICE_BUILD )
  1802. {
  1803. if ( !pNwkDesc->deviceCapacity )
  1804. {
  1805. continue;
  1806. }
  1807. }
  1808. // check version of zigbee protocol
  1809. if ( pNwkDesc->version != _NIB.nwkProtocolVersion )
  1810. continue;
  1811. // check version of stack profile
  1812. if ( pNwkDesc->stackProfile != zgStackProfile )
  1813. {
  1814. if ( ((zgStackProfile == HOME_CONTROLS) && (pNwkDesc->stackProfile == ZIGBEEPRO_PROFILE))
  1815. || ((zgStackProfile == ZIGBEEPRO_PROFILE) && (pNwkDesc->stackProfile == HOME_CONTROLS)) )
  1816. {
  1817. stackProfilePro = TRUE;
  1818. }
  1819. if ( stackProfile == 0 )
  1820. {
  1821. continue;
  1822. }
  1823. }
  1824. break;
  1825. }
  1826. if (i < ResultCount)
  1827. {
  1828. selected = TRUE;
  1829. break;
  1830. }
  1831. // break if selected or stack profile pro wasn't found
  1832. if ( (selected == TRUE) || (stackProfilePro == FALSE) )
  1833. {
  1834. break;
  1835. }
  1836. }
  1837. if ( i == ResultCount )
  1838. {
  1839. return (NULL); // couldn't find appropriate PAN to join !
  1840. }
  1841. else
  1842. {
  1843. return (pNwkDesc);
  1844. }
  1845. }// ZDApp_NwkDescListProcessing()
  1846. /*********************************************************************
  1847. * @fn ZDO_NetworkFormationConfirmCB
  1848. *
  1849. * @brief This function reports the results of the request to
  1850. * initialize a coordinator in a network.
  1851. *
  1852. * @param Status - Result of NLME_NetworkFormationRequest()
  1853. *
  1854. * @return none
  1855. */
  1856. void ZDO_NetworkFormationConfirmCB( ZStatus_t Status )
  1857. {
  1858. nwkStatus = (byte)Status;
  1859. if ( Status == ZSUCCESS )
  1860. {
  1861. // LED on shows Coordinator started
  1862. //HalLedSet ( HAL_LED_3, HAL_LED_MODE_ON );
  1863. // LED off forgets HOLD_AUTO_START
  1864. //HalLedSet (HAL_LED_4, HAL_LED_MODE_OFF);
  1865. #if defined ( ZBIT )
  1866. SIM_SetColor(0xd0ffd0);
  1867. #endif
  1868. if ( devState == DEV_HOLD )
  1869. {
  1870. // Began with HOLD_AUTO_START
  1871. devState = DEV_COORD_STARTING;
  1872. }
  1873. }
  1874. #if defined(BLINK_LEDS)
  1875. else
  1876. {
  1877. //HalLedSet ( HAL_LED_3, HAL_LED_MODE_FLASH ); // Flash LED to show failure
  1878. }
  1879. #endif
  1880. osal_set_event( ZDAppTaskID, ZDO_NETWORK_START );
  1881. }
  1882. /****************************************************************************
  1883. * @fn ZDApp_beaconIndProcessing
  1884. *
  1885. * @brief This function processes the incoming beacon indication.
  1886. *
  1887. * When another task (MT or App) is registered to process
  1888. * beacon indication themselves, this function will parse the
  1889. * beacon payload and pass the beacon descriptor to that task
  1890. * If no other tasks registered, this function will process
  1891. * the beacon payload and generate the network descriptor link
  1892. * list.
  1893. *
  1894. * @param
  1895. *
  1896. * @return none
  1897. *
  1898. */
  1899. void ZDO_beaconNotifyIndCB( NLME_beaconInd_t *pBeacon )
  1900. {
  1901. // Pass the beacon Indication to another task if it registers the callback
  1902. // Otherwise, process the beacon notification here.
  1903. if (zdoCBFunc[ZDO_BEACON_NOTIFY_IND_CBID] != NULL )
  1904. {
  1905. zdoCBFunc[ZDO_BEACON_NOTIFY_IND_CBID]( (void*)pBeacon );
  1906. }
  1907. else
  1908. {
  1909. networkDesc_t *pNwkDesc;
  1910. networkDesc_t *pLastNwkDesc;
  1911. uint8 found = false;
  1912. // Add the network to the Network Descriptor List
  1913. pNwkDesc = NwkDescList;
  1914. pLastNwkDesc = NwkDescList;
  1915. while (pNwkDesc)
  1916. {
  1917. if ((pNwkDesc->panId == pBeacon->panID) &&
  1918. (pNwkDesc->logicalChannel == pBeacon->logicalChannel))
  1919. {
  1920. found = true;
  1921. break;
  1922. }
  1923. pLastNwkDesc = pNwkDesc;
  1924. pNwkDesc = pNwkDesc->nextDesc;
  1925. }
  1926. // If no existing descriptor found, make a new one and add to the list
  1927. if (found == false)
  1928. {
  1929. pNwkDesc = osal_mem_alloc( sizeof(networkDesc_t) );
  1930. if ( !pNwkDesc )
  1931. {
  1932. // Memory alloc failed, discard this beacon
  1933. return;
  1934. }
  1935. // Clear the network descriptor
  1936. osal_memset( pNwkDesc, 0, sizeof(networkDesc_t) );
  1937. // Initialize the descriptor
  1938. pNwkDesc->chosenRouter = INVALID_NODE_ADDR;
  1939. pNwkDesc->chosenRouterDepth = 0xFF;
  1940. // Save new entry into the descriptor list
  1941. if ( !NwkDescList )
  1942. {
  1943. NwkDescList = pNwkDesc;
  1944. }
  1945. else
  1946. {
  1947. pLastNwkDesc->nextDesc = pNwkDesc;
  1948. }
  1949. }
  1950. // Update the descriptor with the incoming beacon
  1951. pNwkDesc->stackProfile = pBeacon->stackProfile;
  1952. pNwkDesc->version = pBeacon->protocolVersion;
  1953. pNwkDesc->logicalChannel = pBeacon->logicalChannel;
  1954. pNwkDesc->panId = pBeacon->panID;
  1955. pNwkDesc->updateId = pBeacon->updateID;
  1956. // Save the extended PAN ID from the beacon payload only if 1.1 version network
  1957. if ( pBeacon->protocolVersion != ZB_PROT_V1_0 )
  1958. {
  1959. osal_cpyExtAddr( pNwkDesc->extendedPANID, pBeacon->extendedPanID );
  1960. }
  1961. else
  1962. {
  1963. osal_memset( pNwkDesc->extendedPANID, 0xFF, Z_EXTADDR_LEN );
  1964. }
  1965. // check if this device is a better choice to join...
  1966. // ...dont bother checking assocPermit flag is doing a rejoin
  1967. if ( ( pBeacon->LQI > gMIN_TREE_LINK_COST ) &&
  1968. ( ( pBeacon->permitJoining == TRUE ) || ( _tmpRejoinState ) ) )
  1969. {
  1970. uint8 selected = FALSE;
  1971. uint8 capacity = FALSE;
  1972. if ( _NIB.nwkAddrAlloc == NWK_ADDRESSING_STOCHASTIC )
  1973. {
  1974. if ( ((pBeacon->LQI > pNwkDesc->chosenRouterLinkQuality) &&
  1975. (pBeacon->depth < MAX_NODE_DEPTH)) ||
  1976. ((pBeacon->LQI == pNwkDesc->chosenRouterLinkQuality) &&
  1977. (pBeacon->depth < pNwkDesc->chosenRouterDepth)) )
  1978. {
  1979. selected = TRUE;
  1980. }
  1981. }
  1982. else
  1983. {
  1984. if ( pBeacon->depth < pNwkDesc->chosenRouterDepth )
  1985. {
  1986. selected = TRUE;
  1987. }
  1988. }
  1989. if ( ZSTACK_ROUTER_BUILD )
  1990. {
  1991. capacity = pBeacon->routerCapacity;
  1992. }
  1993. else if ( ZSTACK_END_DEVICE_BUILD )
  1994. {
  1995. capacity = pBeacon->deviceCapacity;
  1996. }
  1997. if ( (capacity) && (selected) )
  1998. {
  1999. // this is the new chosen router for joining...
  2000. pNwkDesc->chosenRouter = pBeacon->sourceAddr;
  2001. pNwkDesc->chosenRouterLinkQuality = pBeacon->LQI;
  2002. pNwkDesc->chosenRouterDepth = pBeacon->depth;
  2003. }
  2004. if ( pBeacon->deviceCapacity )
  2005. pNwkDesc->deviceCapacity = 1;
  2006. if ( pBeacon->routerCapacity )
  2007. pNwkDesc->routerCapacity = 1;
  2008. }
  2009. }
  2010. }
  2011. /*********************************************************************
  2012. * @fn ZDO_StartRouterConfirmCB
  2013. *
  2014. * @brief This function reports the results of the request to
  2015. * start functioning as a router in a network.
  2016. *
  2017. * @param Status - Result of NLME_StartRouterRequest()
  2018. *
  2019. * @return none
  2020. */
  2021. void ZDO_StartRouterConfirmCB( ZStatus_t Status )
  2022. {
  2023. nwkStatus = (byte)Status;
  2024. if ( Status == ZSUCCESS )
  2025. {
  2026. // LED on shows Router started
  2027. //HalLedSet ( HAL_LED_3, HAL_LED_MODE_ON );
  2028. // LED off forgets HOLD_AUTO_START
  2029. // HalLedSet ( HAL_LED_4, HAL_LED_MODE_OFF);
  2030. if ( devState == DEV_HOLD )
  2031. {
  2032. // Began with HOLD_AUTO_START
  2033. devState = DEV_END_DEVICE;
  2034. }
  2035. }
  2036. #if defined(BLINK_LEDS)
  2037. else
  2038. {
  2039. // HalLedSet( HAL_LED_3, HAL_LED_MODE_FLASH ); // Flash LED to show failure
  2040. }
  2041. #endif
  2042. osal_set_event( ZDAppTaskID, ZDO_ROUTER_START );
  2043. }
  2044. /*********************************************************************
  2045. * @fn ZDO_JoinConfirmCB
  2046. *
  2047. * @brief This function allows the next hight layer to be notified
  2048. * of the results of its request to join itself or another
  2049. * device to a network.
  2050. *
  2051. * @param Status - Result of NLME_JoinRequest()
  2052. *
  2053. * @return none
  2054. */
  2055. void ZDO_JoinConfirmCB( uint16 PanId, ZStatus_t Status )
  2056. {
  2057. (void)PanId; // remove if this parameter is used.
  2058. nwkStatus = (byte)Status;
  2059. if ( Status == ZSUCCESS )
  2060. {
  2061. // LED on shows device joined
  2062. ///HalLedSet ( HAL_LED_3, HAL_LED_MODE_ON );
  2063. // LED off forgets HOLD_AUTO_START
  2064. //HalLedSet ( HAL_LED_4, HAL_LED_MODE_OFF);
  2065. if ( (devState == DEV_HOLD) )
  2066. {
  2067. // Began with HOLD_AUTO_START
  2068. devState = DEV_NWK_JOINING;
  2069. }
  2070. if ( !ZG_SECURE_ENABLED )
  2071. {
  2072. // Notify to save info into NV
  2073. ZDApp_NVUpdate();
  2074. }
  2075. }
  2076. else
  2077. {
  2078. #if defined(BLINK_LEDS)
  2079. // HalLedSet ( HAL_LED_3, HAL_LED_MODE_FLASH ); // Flash LED to show failure
  2080. #endif
  2081. }
  2082. // Pass the join confirm to higher layer if callback registered
  2083. if (zdoCBFunc[ZDO_JOIN_CNF_CBID] != NULL )
  2084. {
  2085. zdoJoinCnf_t joinCnf;
  2086. joinCnf.status = Status;
  2087. joinCnf.deviceAddr = _NIB.nwkDevAddress;
  2088. joinCnf.parentAddr = _NIB.nwkCoordAddress;
  2089. zdoCBFunc[ZDO_JOIN_CNF_CBID]( (void*)&joinCnf );
  2090. }
  2091. // Notify ZDApp
  2092. ZDApp_SendMsg( ZDAppTaskID, ZDO_NWK_JOIN_IND, sizeof(osal_event_hdr_t), (byte*)NULL );
  2093. }
  2094. /*********************************************************************
  2095. * @fn ZDO_AddrChangeIndicationCB
  2096. *
  2097. * @brief This function notifies the application that this
  2098. * device's address has changed. Could happen in
  2099. * a network with stochastic addressing (PRO).
  2100. *
  2101. * @param newAddr - the new address
  2102. *
  2103. * @return none
  2104. */
  2105. void ZDO_AddrChangeIndicationCB( uint16 newAddr )
  2106. {
  2107. ZDO_AddrChangeInd_t *pZDOAddrChangeMsg;
  2108. epList_t *pItem = epList;
  2109. // Notify to save info into NV
  2110. ZDApp_NVUpdate();
  2111. // Notify the applications
  2112. osal_set_event( ZDAppTaskID, ZDO_STATE_CHANGE_EVT );
  2113. while (pItem != NULL)
  2114. {
  2115. if (pItem->epDesc->endPoint != ZDO_EP)
  2116. {
  2117. pZDOAddrChangeMsg = (ZDO_AddrChangeInd_t *)osal_msg_allocate( sizeof( ZDO_AddrChangeInd_t ) );
  2118. if (pZDOAddrChangeMsg != NULL)
  2119. {
  2120. pZDOAddrChangeMsg->hdr.event = ZDO_ADDR_CHANGE_IND;
  2121. pZDOAddrChangeMsg->shortAddr = newAddr;
  2122. osal_msg_send( *(pItem->epDesc->task_id), (uint8 *)pZDOAddrChangeMsg );
  2123. }
  2124. }
  2125. pItem = pItem->nextDesc;
  2126. }
  2127. // Send out a device announce
  2128. ZDApp_AnnounceNewAddress();
  2129. }
  2130. /*********************************************************************
  2131. * @fn ZDO_JoinIndicationCB
  2132. *
  2133. * @brief This function allows the next higher layer of a
  2134. * coordinator to be notified of a remote join request.
  2135. *
  2136. * @param ShortAddress - 16-bit address
  2137. * @param ExtendedAddress - IEEE (64-bit) address
  2138. * @param CapabilityFlags - Association Capability Flags
  2139. * @param type - of joining -
  2140. * NWK_ASSOC_JOIN
  2141. * NWK_ASSOC_REJOIN_UNSECURE
  2142. * NWK_ASSOC_REJOIN_SECURE
  2143. *
  2144. * @return ZStatus_t
  2145. */
  2146. ZStatus_t ZDO_JoinIndicationCB(uint16 ShortAddress, uint8 *ExtendedAddress,
  2147. uint8 CapabilityFlags, uint8 type)
  2148. {
  2149. (void)ShortAddress;
  2150. (void)ExtendedAddress;
  2151. #if ZDO_NV_SAVE_RFDs
  2152. (void)CapabilityFlags;
  2153. #else // if !ZDO_NV_SAVE_RFDs
  2154. if (CapabilityFlags & CAPINFO_DEVICETYPE_FFD)
  2155. #endif
  2156. {
  2157. ZDApp_NVUpdate(); // Notify to save info into NV.
  2158. }
  2159. if (ZG_SECURE_ENABLED) // Send notification to TC of new device.
  2160. {
  2161. if (type == NWK_ASSOC_JOIN || type == NWK_ASSOC_REJOIN_UNSECURE)
  2162. {
  2163. osal_start_timerEx( ZDAppTaskID, ZDO_NEW_DEVICE, 600 );
  2164. }
  2165. }
  2166. return ZSuccess;
  2167. }
  2168. /*********************************************************************
  2169. * @fn ZDO_ConcentratorIndicationCB
  2170. *
  2171. * @brief This function allows the next higher layer of a
  2172. * device to be notified of existence of the concentrator.
  2173. *
  2174. * @param nwkAddr - 16-bit NWK address of the concentrator
  2175. * @param extAddr - pointer to extended Address
  2176. * NULL if not available
  2177. * @param pktCost - PktCost from RREQ
  2178. *
  2179. * @return void
  2180. */
  2181. void ZDO_ConcentratorIndicationCB( uint16 nwkAddr, uint8 *extAddr, uint8 pktCost )
  2182. {
  2183. zdoConcentratorInd_t conInd;
  2184. conInd.nwkAddr = nwkAddr;
  2185. conInd.extAddr = extAddr;
  2186. conInd.pktCost = pktCost;
  2187. if( zdoCBFunc[ZDO_CONCENTRATOR_IND_CBID] != NULL )
  2188. {
  2189. zdoCBFunc[ZDO_CONCENTRATOR_IND_CBID]( (void*)&conInd );
  2190. }
  2191. }
  2192. /*********************************************************************
  2193. * @fn ZDO_LeaveCnf
  2194. *
  2195. * @brief This function allows the next higher layer to be
  2196. * notified of the results of its request for this or
  2197. * a child device to leave the network.
  2198. *
  2199. * @param cnf - NLME_LeaveCnf_t
  2200. *
  2201. * @return none
  2202. */
  2203. void ZDO_LeaveCnf( NLME_LeaveCnf_t* cnf )
  2204. {
  2205. // Check for this device
  2206. if ( osal_ExtAddrEqual( cnf->extAddr,
  2207. NLME_GetExtAddr() ) == TRUE )
  2208. {
  2209. // Pass the leave confirm to higher layer if callback registered
  2210. if ( ( zdoCBFunc[ZDO_LEAVE_CNF_CBID] == NULL ) ||
  2211. ( (*zdoCBFunc[ZDO_LEAVE_CNF_CBID])( cnf ) == NULL ) )
  2212. {
  2213. // Prepare to leave with reset
  2214. ZDApp_LeaveReset( cnf->rejoin );
  2215. }
  2216. }
  2217. else if ( ZSTACK_ROUTER_BUILD )
  2218. {
  2219. // Remove device address(optionally descendents) from data
  2220. ZDApp_LeaveUpdate( cnf->dstAddr,
  2221. cnf->extAddr,
  2222. cnf->removeChildren );
  2223. }
  2224. }
  2225. /*********************************************************************
  2226. * @fn ZDO_LeaveInd
  2227. *
  2228. * @brief This function allows the next higher layer of a
  2229. * device to be notified of a remote leave request or
  2230. * indication.
  2231. *
  2232. * @param ind - NLME_LeaveInd_t
  2233. *
  2234. * @return none
  2235. */
  2236. void ZDO_LeaveInd( NLME_LeaveInd_t* ind )
  2237. {
  2238. uint8 leave;
  2239. // Parent is requesting the leave - NWK layer filters out illegal
  2240. // requests
  2241. if ( ind->request == TRUE )
  2242. {
  2243. // Notify network of leave
  2244. if ( ZSTACK_ROUTER_BUILD )
  2245. {
  2246. NLME_LeaveRsp_t rsp;
  2247. rsp.rejoin = ind->rejoin;
  2248. rsp.removeChildren = ind->removeChildren;
  2249. NLME_LeaveRsp( &rsp );
  2250. }
  2251. // Prepare to leave with reset
  2252. ZDApp_LeaveReset( ind->rejoin );
  2253. }
  2254. else
  2255. {
  2256. leave = FALSE;
  2257. // Check if this device needs to leave as a child or descendent
  2258. if ( ind->srcAddr == NLME_GetCoordShortAddr() )
  2259. {
  2260. if ( ( ind->removeChildren == TRUE ) ||
  2261. ( ZDO_Config_Node_Descriptor.LogicalType ==
  2262. NODETYPE_DEVICE ) )
  2263. {
  2264. leave = TRUE;
  2265. }
  2266. }
  2267. else if ( ind->removeChildren == TRUE )
  2268. {
  2269. // Check NWK address allocation algorithm
  2270. //leave = RTG_ANCESTOR(nwkAddr,thisAddr);
  2271. }
  2272. if ( leave == TRUE )
  2273. {
  2274. // Prepare to leave with reset
  2275. ZDApp_LeaveReset( ind->rejoin );
  2276. }
  2277. else
  2278. {
  2279. // Remove device address(optionally descendents) from data
  2280. ZDApp_LeaveUpdate( ind->srcAddr,
  2281. ind->extAddr,
  2282. ind->removeChildren );
  2283. }
  2284. }
  2285. // Pass the leave indication to higher layer if callback registered.
  2286. if (zdoCBFunc[ZDO_LEAVE_IND_CBID] != NULL)
  2287. {
  2288. (void)zdoCBFunc[ZDO_LEAVE_IND_CBID](ind);
  2289. }
  2290. }
  2291. /*********************************************************************
  2292. * @fn ZDO_SyncIndicationCB
  2293. *
  2294. * @brief This function allows the next higher layer of a
  2295. * coordinator to be notified of a loss of synchronization
  2296. * with the parent/child device.
  2297. *
  2298. * @param type: 0 - child; 1 - parent
  2299. *
  2300. *
  2301. * @return none
  2302. */
  2303. void ZDO_SyncIndicationCB( uint8 type, uint16 shortAddr )
  2304. {
  2305. (void)shortAddr; // Remove this line if this parameter is used.
  2306. if ( ZSTACK_END_DEVICE_BUILD
  2307. || (ZSTACK_ROUTER_BUILD && ((_NIB.CapabilityFlags & ZMAC_ASSOC_CAPINFO_FFD_TYPE) == 0)))
  2308. {
  2309. if ( type == 1 )
  2310. {
  2311. // We lost contact with our parent. Clear the neighbor Table.
  2312. nwkNeighborInitTable();
  2313. // Start the rejoin process.
  2314. ZDApp_SendMsg( ZDAppTaskID, ZDO_NWK_JOIN_REQ, sizeof(osal_event_hdr_t), NULL );
  2315. }
  2316. }
  2317. }
  2318. /*********************************************************************
  2319. * @fn ZDO_ManytoOneFailureIndicationCB
  2320. *
  2321. * @brief This function allows the next higher layer of a
  2322. * concentrator to be notified of a many-to-one route
  2323. * failure.
  2324. *
  2325. * @param none
  2326. *
  2327. *
  2328. * @return none
  2329. */
  2330. void ZDO_ManytoOneFailureIndicationCB()
  2331. {
  2332. // By default, the concentrator automatically redo many-to-one route
  2333. // discovery to update all many-to-one routes in the network
  2334. // If you want anything processing other than the default,
  2335. // please replace the following code.
  2336. RTG_MTORouteReq();
  2337. }
  2338. /*********************************************************************
  2339. * @fn ZDO_PollConfirmCB
  2340. *
  2341. * @brief This function allows the next higher layer to be
  2342. * notified of a Poll Confirm.
  2343. *
  2344. * @param none
  2345. *
  2346. * @return none
  2347. */
  2348. void ZDO_PollConfirmCB( uint8 status )
  2349. {
  2350. (void)status; // Remove this line if this parameter is used.
  2351. return;
  2352. }
  2353. /******************************************************************************
  2354. * @fn ZDApp_NwkWriteNVRequest (stubs AddrMgrWriteNVRequest)
  2355. *
  2356. * @brief Stub routine implemented by NHLE. NHLE should call
  2357. * <AddrMgrWriteNV> when appropriate.
  2358. *
  2359. * @param none
  2360. *
  2361. * @return none
  2362. */
  2363. void ZDApp_NwkWriteNVRequest( void )
  2364. {
  2365. #if defined ( NV_RESTORE )
  2366. if ( !osal_get_timeoutEx( ZDAppTaskID, ZDO_NWK_UPDATE_NV ) )
  2367. {
  2368. // Trigger to save info into NV
  2369. ZDApp_NVUpdate();
  2370. }
  2371. #endif
  2372. }
  2373. /*********************************************************************
  2374. * Call Back Functions from Security - API
  2375. */
  2376. /*********************************************************************
  2377. * @fn ZDO_UpdateDeviceIndication
  2378. *
  2379. * @brief This function notifies the "Trust Center" of a
  2380. * network when a device joins or leaves the network.
  2381. *
  2382. * @param extAddr - pointer to 64 bit address of new device
  2383. * @param status - 0 if a new device joined securely
  2384. * - 1 if a new device joined un-securely
  2385. * - 2 if a device left the network
  2386. *
  2387. * @return true if newly joined device should be allowed to
  2388. * remain on network
  2389. */
  2390. ZStatus_t ZDO_UpdateDeviceIndication( uint8 *extAddr, uint8 status )
  2391. {
  2392. // can implement a network access policy based on the
  2393. // IEEE address of newly joining devices...
  2394. (void)extAddr;
  2395. (void)status;
  2396. return ZSuccess;
  2397. }
  2398. /*********************************************************************
  2399. * @fn ZDApp_InMsgCB
  2400. *
  2401. * @brief This function is called to pass up any message that is
  2402. * not yet supported. This allows for the developer to
  2403. * support features themselves..
  2404. *
  2405. * @return none
  2406. */
  2407. void ZDApp_InMsgCB( zdoIncomingMsg_t *inMsg )
  2408. {
  2409. if ( inMsg->clusterID & ZDO_RESPONSE_BIT )
  2410. {
  2411. // Handle the response message
  2412. }
  2413. else
  2414. {
  2415. // Handle the request message by sending a generic "not supported".
  2416. // Device Announce doesn't have a response.
  2417. if ( !(inMsg->wasBroadcast) && inMsg->clusterID != Device_annce )
  2418. {
  2419. ZDP_GenericRsp( inMsg->TransSeq, &(inMsg->srcAddr), ZDP_NOT_SUPPORTED, 0,
  2420. (uint16)(inMsg->clusterID | ZDO_RESPONSE_BIT), inMsg->SecurityUse );
  2421. }
  2422. }
  2423. }
  2424. /*********************************************************************
  2425. * @fn ZDApp_ChangeMatchDescRespPermission()
  2426. *
  2427. * @brief Changes the Match Descriptor Response permission.
  2428. *
  2429. * @param endpoint - endpoint to allow responses
  2430. * @param action - true to allow responses, false to not
  2431. *
  2432. * @return none
  2433. */
  2434. void ZDApp_ChangeMatchDescRespPermission( uint8 endpoint, uint8 action )
  2435. {
  2436. // Store the action
  2437. afSetMatch( endpoint, action );
  2438. }
  2439. /*********************************************************************
  2440. * @fn ZDApp_NetworkInit()
  2441. *
  2442. * @brief Used to start the network joining process
  2443. *
  2444. * @param delay - mSec delay to wait before starting
  2445. *
  2446. * @return none
  2447. */
  2448. void ZDApp_NetworkInit( uint16 delay )
  2449. {
  2450. if ( delay )
  2451. {
  2452. // Wait awhile before starting the device
  2453. osal_start_timerEx( ZDAppTaskID, ZDO_NETWORK_INIT, delay );
  2454. }
  2455. else
  2456. {
  2457. osal_set_event( ZDAppTaskID, ZDO_NETWORK_INIT );
  2458. }
  2459. }
  2460. /*********************************************************************
  2461. * @fn ZDApp_NwkStateUpdateCB()
  2462. *
  2463. * @brief This function notifies that this device's network
  2464. * state info has been changed.
  2465. *
  2466. * @param none
  2467. *
  2468. * @return none
  2469. */
  2470. void ZDApp_NwkStateUpdateCB( void )
  2471. {
  2472. // Notify to save info into NV
  2473. if ( !osal_get_timeoutEx( ZDAppTaskID, ZDO_NWK_UPDATE_NV ) )
  2474. {
  2475. // Trigger to save info into NV
  2476. ZDApp_NVUpdate();
  2477. }
  2478. }
  2479. /*********************************************************************
  2480. * @fn ZDApp_NodeProfileSync()
  2481. *
  2482. * @brief Sync node with stack profile.
  2483. *
  2484. * @param stackProfile - stack profile of the network to join
  2485. *
  2486. * @return none
  2487. */
  2488. void ZDApp_NodeProfileSync( uint8 stackProfile )
  2489. {
  2490. if ( ZDO_Config_Node_Descriptor.CapabilityFlags & CAPINFO_DEVICETYPE_FFD )
  2491. {
  2492. if ( stackProfile != zgStackProfile )
  2493. {
  2494. ZDO_Config_Node_Descriptor.LogicalType = NODETYPE_DEVICE;
  2495. ZDO_Config_Node_Descriptor.CapabilityFlags = CAPINFO_DEVICETYPE_RFD | CAPINFO_POWER_AC | CAPINFO_RCVR_ON_IDLE;
  2496. NLME_SetBroadcastFilter( ZDO_Config_Node_Descriptor.CapabilityFlags );
  2497. }
  2498. }
  2499. }
  2500. /*********************************************************************
  2501. * @fn ZDApp_StartJoiningCycle()
  2502. *
  2503. * @brief Starts the joining cycle of a device. This will only
  2504. * continue an already started (or stopped) joining cycle.
  2505. *
  2506. * @param none
  2507. *
  2508. * @return TRUE if joining stopped, FALSE if joining or rejoining
  2509. */
  2510. uint8 ZDApp_StartJoiningCycle( void )
  2511. {
  2512. if ( devState == DEV_INIT || devState == DEV_NWK_DISC )
  2513. {
  2514. continueJoining = TRUE;
  2515. ZDApp_NetworkInit( 0 );
  2516. return ( TRUE );
  2517. }
  2518. else
  2519. return ( FALSE );
  2520. }
  2521. /*********************************************************************
  2522. * @fn ZDApp_StopJoiningCycle()
  2523. *
  2524. * @brief Stops the joining or rejoining process of a device.
  2525. *
  2526. * @param none
  2527. *
  2528. * @return TRUE if joining stopped, FALSE if joining or rejoining
  2529. */
  2530. uint8 ZDApp_StopJoiningCycle( void )
  2531. {
  2532. if ( devState == DEV_INIT || devState == DEV_NWK_DISC )
  2533. {
  2534. continueJoining = FALSE;
  2535. return ( TRUE );
  2536. }
  2537. else
  2538. return ( FALSE );
  2539. }
  2540. /*********************************************************************
  2541. * @fn ZDApp_AnnounceNewAddress()
  2542. *
  2543. * @brief Send Device Announce and hold all transmissions for
  2544. * new address timeout.
  2545. *
  2546. * @param none
  2547. *
  2548. * @return none
  2549. */
  2550. void ZDApp_AnnounceNewAddress( void )
  2551. {
  2552. #if defined ( ZIGBEE_NWK_UNIQUE_ADDR_CHECK )
  2553. // Turn off data request hold
  2554. APSME_HoldDataRequests( 0 );
  2555. #endif
  2556. ZDP_DeviceAnnce( NLME_GetShortAddr(), NLME_GetExtAddr(),
  2557. ZDO_Config_Node_Descriptor.CapabilityFlags, 0 );
  2558. #if defined ( ZIGBEE_NWK_UNIQUE_ADDR_CHECK )
  2559. // Setup the timeout
  2560. APSME_HoldDataRequests( ZDAPP_HOLD_DATA_REQUESTS_TIMEOUT );
  2561. #endif
  2562. }
  2563. /*********************************************************************
  2564. * @fn ZDApp_NVUpdate
  2565. *
  2566. * @brief Set the NV Update Timer.
  2567. *
  2568. * @param none
  2569. *
  2570. * @return none
  2571. */
  2572. void ZDApp_NVUpdate( void )
  2573. {
  2574. #if defined ( NV_RESTORE )
  2575. osal_start_timerEx( ZDAppTaskID, ZDO_NWK_UPDATE_NV, ZDAPP_UPDATE_NWK_NV_TIME );
  2576. #endif
  2577. }
  2578. /*********************************************************************
  2579. * @fn ZDApp_CoordStartPANIDConflictCB()
  2580. *
  2581. * @brief Returns a PAN ID for the network layer to use during
  2582. * a coordinator start and there is another network with
  2583. * the intended PANID.
  2584. *
  2585. * @param panid - the intended PAN ID
  2586. *
  2587. * @return PANID to try
  2588. */
  2589. uint16 ZDApp_CoordStartPANIDConflictCB( uint16 panid )
  2590. {
  2591. return ( panid + 1 );
  2592. }
  2593. /*********************************************************************
  2594. * @fn ZDO_SrcRtgIndCB
  2595. *
  2596. * @brief This function notifies the ZDO available src route record received.
  2597. *
  2598. * @param srcAddr - source address of the source route
  2599. * @param relayCnt - number of devices in the relay list
  2600. * @param relayList - relay list of the source route
  2601. *
  2602. * @return none
  2603. */
  2604. void ZDO_SrcRtgIndCB (uint16 srcAddr, uint8 relayCnt, uint16* pRelayList )
  2605. {
  2606. zdoSrcRtg_t srcRtg;
  2607. srcRtg.srcAddr = srcAddr;
  2608. srcRtg.relayCnt = relayCnt;
  2609. srcRtg.pRelayList = pRelayList;
  2610. if( zdoCBFunc[ZDO_SRC_RTG_IND_CBID] != NULL )
  2611. {
  2612. zdoCBFunc[ZDO_SRC_RTG_IND_CBID]( (void*)&srcRtg );
  2613. }
  2614. }
  2615. /*********************************************************************
  2616. * @fn ZDApp_InitZdoCBFunc
  2617. *
  2618. * @brief Call this function to initialize zdoCBFunc[]
  2619. *
  2620. * @param none
  2621. *
  2622. * @return none
  2623. */
  2624. void ZDApp_InitZdoCBFunc( void )
  2625. {
  2626. uint8 i;
  2627. for ( i=0; i< MAX_ZDO_CB_FUNC; i++ )
  2628. {
  2629. zdoCBFunc[i] = NULL;
  2630. }
  2631. }
  2632. /*********************************************************************
  2633. * @fn ZDO_RegisterForZdoCB
  2634. *
  2635. * @brief Call this function to register the higher layer (for
  2636. * example, the Application layer or MT layer) with ZDO
  2637. * callbacks to get notified of some ZDO indication like
  2638. * existence of a concentrator or receipt of a source
  2639. * route record.
  2640. *
  2641. * @param indID - ZDO Indication ID
  2642. * @param pFn - Callback function pointer
  2643. *
  2644. * @return ZSuccess - successful, ZInvalidParameter if not
  2645. */
  2646. ZStatus_t ZDO_RegisterForZdoCB( uint8 indID, pfnZdoCb pFn )
  2647. {
  2648. // Check the range of the indication ID
  2649. if ( indID < MAX_ZDO_CB_FUNC )
  2650. {
  2651. zdoCBFunc[indID] = pFn;
  2652. return ZSuccess;
  2653. }
  2654. return ZInvalidParameter;
  2655. }
  2656. /*********************************************************************
  2657. * @fn ZDO_DeregisterForZdoCB
  2658. *
  2659. * @brief Call this function to de-register the higher layer (for
  2660. * example, the Application layer or MT layer) with ZDO
  2661. * callbacks to get notified of some ZDO indication like
  2662. * existence of a concentrator or receipt of a source
  2663. * route record.
  2664. *
  2665. * @param indID - ZDO Indication ID
  2666. *
  2667. * @return ZSuccess - successful, ZInvalidParameter if not
  2668. */
  2669. ZStatus_t ZDO_DeregisterForZdoCB( uint8 indID )
  2670. {
  2671. // Check the range of the indication ID
  2672. if ( indID < MAX_ZDO_CB_FUNC )
  2673. {
  2674. zdoCBFunc[indID] = NULL;
  2675. return ZSuccess;
  2676. }
  2677. return ZInvalidParameter;
  2678. }
  2679. /*********************************************************************
  2680. *********************************************************************/