ZDObject.c 87 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082
  1. /**************************************************************************************************
  2. Filename: ZDObject.c
  3. Revised: $Date: 2009-03-19 11:37:20 -0700 (Thu, 19 Mar 2009) $
  4. Revision: $Revision: 19466 $
  5. Description: This is the Zigbee Device Object.
  6. Copyright 2004-2009 Texas Instruments Incorporated. All rights reserved.
  7. IMPORTANT: Your use of this Software is limited to those specific rights
  8. granted under the terms of a software license agreement between the user
  9. who downloaded the software, his/her employer (which must be your employer)
  10. and Texas Instruments Incorporated (the "License"). You may not use this
  11. Software unless you agree to abide by the terms of the License. The License
  12. limits your use, and you acknowledge, that the Software may not be modified,
  13. copied or distributed unless embedded on a Texas Instruments microcontroller
  14. or used solely and exclusively in conjunction with a Texas Instruments radio
  15. frequency transceiver, which is integrated into your product. Other than for
  16. the foregoing purpose, you may not use, reproduce, copy, prepare derivative
  17. works of, modify, distribute, perform, display or sell this Software and/or
  18. its documentation for any purpose.
  19. YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
  20. PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
  21. INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
  22. NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
  23. TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
  24. NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
  25. LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
  26. INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
  27. OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
  28. OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
  29. (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
  30. Should you have any questions regarding your right to use this Software,
  31. contact Texas Instruments Incorporated at www.TI.com.
  32. **************************************************************************************************/
  33. /*********************************************************************
  34. * INCLUDES
  35. */
  36. #include "ZComdef.h"
  37. #include "OSAL.h"
  38. #include "OSAL_Nv.h"
  39. #include "rtg.h"
  40. #include "NLMEDE.h"
  41. #include "nwk_globals.h"
  42. #include "APS.h"
  43. #include "APSMEDE.h"
  44. #include "AssocList.h"
  45. #include "BindingTable.h"
  46. #include "AddrMgr.h"
  47. #include "AF.h"
  48. #include "ZDObject.h"
  49. #include "ZDProfile.h"
  50. #include "ZDConfig.h"
  51. #include "ZDSecMgr.h"
  52. #include "ZDApp.h"
  53. #include "nwk_util.h" // NLME_IsAddressBroadcast()
  54. #include "ZGlobals.h"
  55. #if defined( LCD_SUPPORTED )
  56. #include "OnBoard.h"
  57. #endif
  58. /* HAL */
  59. #include "hal_lcd.h"
  60. /*********************************************************************
  61. * MACROS
  62. */
  63. /*********************************************************************
  64. * CONSTANTS
  65. */
  66. // NLME Stub Implementations
  67. #define ZDO_ProcessMgmtPermitJoinTimeout NLME_PermitJoiningTimeout
  68. // Status fields used by ZDO_ProcessMgmtRtgReq
  69. #define ZDO_MGMT_RTG_ENTRY_ACTIVE 0x00
  70. #define ZDO_MGMT_RTG_ENTRY_DISCOVERY_UNDERWAY 0x01
  71. #define ZDO_MGMT_RTG_ENTRY_DISCOVERY_FAILED 0x02
  72. #define ZDO_MGMT_RTG_ENTRY_INACTIVE 0x03
  73. /*********************************************************************
  74. * TYPEDEFS
  75. */
  76. #if defined ( REFLECTOR )
  77. typedef struct
  78. {
  79. byte SrcTransSeq;
  80. zAddrType_t SrcAddr;
  81. uint16 LocalCoordinator;
  82. byte epIntf;
  83. uint16 ProfileID;
  84. byte numInClusters;
  85. uint16 *inClusters;
  86. byte numOutClusters;
  87. uint16 *outClusters;
  88. byte SecurityUse;
  89. byte status;
  90. } ZDO_EDBind_t;
  91. #endif // defined ( REFLECTOR )
  92. enum
  93. {
  94. ZDMATCH_INIT, // Initialized
  95. ZDMATCH_WAIT_REQ, // Received first request, waiting for second
  96. ZDMATCH_SENDING_BINDS // Received both requests, sending unbind/binds
  97. };
  98. enum
  99. {
  100. ZDMATCH_SENDING_NOT,
  101. ZDMATCH_SENDING_UNBIND,
  102. ZDMATCH_SENDING_BIND
  103. };
  104. /*********************************************************************
  105. * GLOBAL VARIABLES
  106. */
  107. /*********************************************************************
  108. * EXTERNAL VARIABLES
  109. */
  110. /*********************************************************************
  111. * EXTERNAL FUNCTIONS
  112. */
  113. /*********************************************************************
  114. * LOCAL VARIABLES
  115. */
  116. static uint16 ZDOBuildBuf[26]; // temp area to build data without allocation
  117. #if defined ( REFLECTOR )
  118. static ZDO_EDBind_t *ZDO_EDBind; // Null when not used
  119. #endif
  120. #if defined ( MANAGED_SCAN )
  121. uint32 managedScanNextChannel = 0;
  122. uint32 managedScanChannelMask = 0;
  123. uint8 managedScanTimesPerChannel = 0;
  124. #endif
  125. ZDMatchEndDeviceBind_t *matchED = (ZDMatchEndDeviceBind_t *)NULL;
  126. uint32 apsChannelMask = 0;
  127. /*********************************************************************
  128. * LOCAL FUNCTIONS
  129. */
  130. static void ZDODeviceSetup( void );
  131. #if defined ( MANAGED_SCAN )
  132. static void ZDOManagedScan_Next( void );
  133. #endif
  134. #if defined ( REFLECTOR )
  135. static void ZDO_RemoveEndDeviceBind( void );
  136. static void ZDO_SendEDBindRsp( byte TransSeq, zAddrType_t *dstAddr, byte Status, byte secUse );
  137. #endif
  138. static byte ZDO_CompareClusterLists( byte numList1, uint16 *list1,
  139. byte numList2, uint16 *list2, uint16 *pMatches );
  140. static void ZDO_RemoveMatchMemory( void );
  141. static uint8 ZDO_CopyMatchInfo( ZDEndDeviceBind_t *destReq, ZDEndDeviceBind_t *srcReq );
  142. static void ZDO_EndDeviceBindMatchTimeoutCB( void );
  143. uint8 *ZDO_ConvertOTAClusters( uint8 cnt, uint8 *inBuf, uint16 *outList );
  144. /*********************************************************************
  145. * @fn ZDO_Init
  146. *
  147. * @brief ZDObject and ZDProfile initialization.
  148. *
  149. * @param none
  150. *
  151. * @return none
  152. */
  153. void ZDO_Init( void )
  154. {
  155. // Initialize ZD items
  156. #if defined ( REFLECTOR )
  157. ZDO_EDBind = NULL;
  158. #endif
  159. // Initialize default ZDO_UseExtendedPANID to the APS one.
  160. osal_cpyExtAddr( ZDO_UseExtendedPANID, AIB_apsUseExtendedPANID );
  161. // Setup the device - type of device to create.
  162. ZDODeviceSetup();
  163. }
  164. #if defined ( MANAGED_SCAN )
  165. /*********************************************************************
  166. * @fn ZDOManagedScan_Next()
  167. *
  168. * @brief Setup a managed scan.
  169. *
  170. * @param none
  171. *
  172. * @return none
  173. */
  174. static void ZDOManagedScan_Next( void )
  175. {
  176. // Is it the first time
  177. if ( managedScanNextChannel == 0 && managedScanTimesPerChannel == 0 )
  178. {
  179. // Setup the defaults
  180. managedScanNextChannel = 1;
  181. while( managedScanNextChannel && (zgDefaultChannelList & managedScanNextChannel) == 0 )
  182. managedScanNextChannel <<= 1;
  183. managedScanChannelMask = managedScanNextChannel;
  184. managedScanTimesPerChannel = MANAGEDSCAN_TIMES_PRE_CHANNEL;
  185. }
  186. else
  187. {
  188. // Do we need to go to the next channel
  189. if ( managedScanTimesPerChannel == 0 )
  190. {
  191. // Find next active channel
  192. managedScanChannelMask = managedScanNextChannel;
  193. managedScanTimesPerChannel = MANAGEDSCAN_TIMES_PRE_CHANNEL;
  194. }
  195. else
  196. {
  197. managedScanTimesPerChannel--;
  198. if ( managedScanTimesPerChannel == 0 )
  199. {
  200. managedScanNextChannel <<= 1;
  201. while( managedScanNextChannel && (zgDefaultChannelList & managedScanNextChannel) == 0 )
  202. managedScanNextChannel <<= 1;
  203. if ( managedScanNextChannel == 0 )
  204. zdoDiscCounter = NUM_DISC_ATTEMPTS + 1; // Stop
  205. }
  206. }
  207. }
  208. }
  209. #endif // MANAGED_SCAN
  210. /*********************************************************************
  211. * @fn ZDODeviceSetup()
  212. *
  213. * @brief Call set functions depending on the type of device compiled.
  214. *
  215. * @param none
  216. *
  217. * @return none
  218. */
  219. static void ZDODeviceSetup( void )
  220. {
  221. if ( ZG_BUILD_COORDINATOR_TYPE )
  222. {
  223. NLME_CoordinatorInit();
  224. }
  225. #if defined ( REFLECTOR )
  226. APS_ReflectorInit( (ZG_DEVICE_COORDINATOR_TYPE) ? APS_REFLECTOR_PUBLIC : APS_REFLECTOR_PRIVATE );
  227. #endif
  228. if ( ZG_BUILD_JOINING_TYPE )
  229. {
  230. NLME_DeviceJoiningInit();
  231. }
  232. }
  233. /*********************************************************************
  234. * @fn ZDO_StartDevice
  235. *
  236. * @brief This function starts a device in a network.
  237. *
  238. * @param logicalType - Device type to start
  239. * startMode - indicates mode of device startup
  240. * beaconOrder - indicates time betwen beacons
  241. * superframeOrder - indicates length of active superframe
  242. *
  243. * @return none
  244. */
  245. void ZDO_StartDevice( byte logicalType, devStartModes_t startMode, byte beaconOrder, byte superframeOrder )
  246. {
  247. ZStatus_t ret;
  248. #if defined ( ZIGBEE_FREQ_AGILITY )
  249. static uint8 discRetries = 0;
  250. #endif
  251. #if defined ( ZIGBEE_COMMISSIONING )
  252. static uint8 scanCnt = 0;
  253. #endif
  254. ret = ZUnsupportedMode;
  255. if ( ZG_BUILD_COORDINATOR_TYPE && logicalType == NODETYPE_COORDINATOR )
  256. {
  257. if ( startMode == MODE_HARD )
  258. {
  259. devState = DEV_COORD_STARTING;
  260. ret = NLME_NetworkFormationRequest( zgConfigPANID, zgApsUseExtendedPANID, zgDefaultChannelList,
  261. zgDefaultStartingScanDuration, beaconOrder,
  262. superframeOrder, false );
  263. }
  264. else if ( startMode == MODE_RESUME )
  265. {
  266. // Just start the coordinator
  267. devState = DEV_COORD_STARTING;
  268. ret = NLME_StartRouterRequest( beaconOrder, beaconOrder, false );
  269. }
  270. else
  271. {
  272. #if defined( LCD_SUPPORTED )
  273. HalLcdWriteScreen( "StartDevice ERR", "MODE unknown" );
  274. #endif
  275. }
  276. }
  277. if ( ZG_BUILD_JOINING_TYPE && (logicalType == NODETYPE_ROUTER || logicalType == NODETYPE_DEVICE) )
  278. {
  279. if ( (startMode == MODE_JOIN) || (startMode == MODE_REJOIN) )
  280. {
  281. devState = DEV_NWK_DISC;
  282. #if defined( MANAGED_SCAN )
  283. ZDOManagedScan_Next();
  284. ret = NLME_NetworkDiscoveryRequest( managedScanChannelMask, BEACON_ORDER_15_MSEC );
  285. #else
  286. ret = NLME_NetworkDiscoveryRequest( zgDefaultChannelList, zgDefaultStartingScanDuration );
  287. #if defined ( ZIGBEE_FREQ_AGILITY )
  288. if ( !( ZDO_Config_Node_Descriptor.CapabilityFlags & CAPINFO_RCVR_ON_IDLE ) &&
  289. ( ret == ZSuccess ) && ( ++discRetries == 4 ) )
  290. {
  291. // For devices with RxOnWhenIdle equals to FALSE, any network channel
  292. // change will not be recieved. On these devices or routers that have
  293. // lost the network, an active scan shall be conducted on the Default
  294. // Channel list using the extended PANID to find the network. If the
  295. // extended PANID isn't found using the Default Channel list, an scan
  296. // should be completed using all channels.
  297. zgDefaultChannelList = MAX_CHANNELS_24GHZ;
  298. }
  299. #endif // ZIGBEE_FREQ_AGILITY
  300. #if defined ( ZIGBEE_COMMISSIONING )
  301. if (startMode == MODE_REJOIN && scanCnt++ >= 5 )
  302. {
  303. // When ApsUseExtendedPanID is commissioned to a non zero value via
  304. // application specific means, the device shall conduct an active scan
  305. // on the Default Channel list and join the PAN with the same
  306. // ExtendedPanID. If the PAN is not found, an scan should be completed
  307. // on all channels.
  308. // When devices rejoin the network and the PAN is not found from
  309. zgDefaultChannelList = MAX_CHANNELS_24GHZ;
  310. }
  311. #endif // ZIGBEE_COMMISSIONING
  312. #endif
  313. }
  314. else if ( startMode == MODE_RESUME )
  315. {
  316. if ( logicalType == NODETYPE_ROUTER )
  317. {
  318. ZMacScanCnf_t scanCnf;
  319. devState = DEV_NWK_ORPHAN;
  320. /* if router and nvram is available, fake successful orphan scan */
  321. scanCnf.hdr.Status = ZSUCCESS;
  322. scanCnf.ScanType = ZMAC_ORPHAN_SCAN;
  323. scanCnf.UnscannedChannels = 0;
  324. scanCnf.ResultListSize = 0;
  325. nwk_ScanJoiningOrphan(&scanCnf);
  326. ret = ZSuccess;
  327. }
  328. else
  329. {
  330. devState = DEV_NWK_ORPHAN;
  331. ret = NLME_OrphanJoinRequest( zgDefaultChannelList,
  332. zgDefaultStartingScanDuration );
  333. }
  334. }
  335. else
  336. {
  337. #if defined( LCD_SUPPORTED )
  338. HalLcdWriteScreen( "StartDevice ERR", "MODE unknown" );
  339. #endif
  340. }
  341. }
  342. if ( ret != ZSuccess )
  343. osal_start_timerEx(ZDAppTaskID, ZDO_NETWORK_INIT, NWK_RETRY_DELAY );
  344. }
  345. /*********************************************************************
  346. * @fn ZDO_UpdateNwkStatus()
  347. *
  348. * @brief
  349. *
  350. * This function will send an update message to each registered
  351. * application endpoint/interface about a network status change.
  352. *
  353. * @param none
  354. *
  355. * @return none
  356. */
  357. void ZDO_UpdateNwkStatus( devStates_t state )
  358. {
  359. // Endpoint/Interface descriptor list.
  360. epList_t *epDesc = epList;
  361. byte bufLen = sizeof(osal_event_hdr_t);
  362. osal_event_hdr_t *msgPtr;
  363. ZDAppNwkAddr.addr.shortAddr = NLME_GetShortAddr();
  364. (void)NLME_GetExtAddr(); // Load the saveExtAddr pointer.
  365. while ( epDesc )
  366. {
  367. if ( epDesc->epDesc->endPoint != ZDO_EP )
  368. {
  369. msgPtr = (osal_event_hdr_t *)osal_msg_allocate( bufLen );
  370. if ( msgPtr )
  371. {
  372. msgPtr->event = ZDO_STATE_CHANGE; // Command ID
  373. msgPtr->status = (byte)state;
  374. osal_msg_send( *(epDesc->epDesc->task_id), (uint8 *)msgPtr );
  375. }
  376. }
  377. epDesc = epDesc->nextDesc;
  378. }
  379. }
  380. #if defined ( REFLECTOR )
  381. /*********************************************************************
  382. * @fn ZDO_RemoveEndDeviceBind
  383. *
  384. * @brief Remove the end device bind
  385. *
  386. * @param none
  387. *
  388. * @return none
  389. */
  390. static void ZDO_RemoveEndDeviceBind( void )
  391. {
  392. if ( ZDO_EDBind != NULL )
  393. {
  394. // Free the RAM
  395. if ( ZDO_EDBind->inClusters != NULL )
  396. osal_mem_free( ZDO_EDBind->inClusters );
  397. if ( ZDO_EDBind->outClusters != NULL )
  398. osal_mem_free( ZDO_EDBind->outClusters );
  399. osal_mem_free( ZDO_EDBind );
  400. ZDO_EDBind = NULL;
  401. }
  402. }
  403. #endif // REFLECTOR
  404. #if defined ( REFLECTOR )
  405. /*********************************************************************
  406. * @fn ZDO_RemoveEndDeviceBind
  407. *
  408. * @brief Remove the end device bind
  409. *
  410. * @param none
  411. *
  412. * @return none
  413. */
  414. static void ZDO_SendEDBindRsp( byte TransSeq, zAddrType_t *dstAddr, byte Status, byte secUse )
  415. {
  416. ZDP_EndDeviceBindRsp( TransSeq, dstAddr, Status, secUse );
  417. #if defined( LCD_SUPPORTED )
  418. HalLcdWriteString( "End Device Bind", HAL_LCD_LINE_1 );
  419. if ( Status == ZDP_SUCCESS )
  420. HalLcdWriteString( "Success Sent", HAL_LCD_LINE_2 );
  421. else
  422. HalLcdWriteString( "Timeout", HAL_LCD_LINE_2 );
  423. #endif
  424. }
  425. #endif // REFLECTOR
  426. /*********************************************************************
  427. * @fn ZDO_CompareClusterLists
  428. *
  429. * @brief Compare one list to another list
  430. *
  431. * @param numList1 - number of items in list 1
  432. * @param list1 - first list of cluster IDs
  433. * @param numList2 - number of items in list 2
  434. * @param list2 - second list of cluster IDs
  435. * @param pMatches - buffer to put matches
  436. *
  437. * @return number of matches
  438. */
  439. static byte ZDO_CompareClusterLists( byte numList1, uint16 *list1,
  440. byte numList2, uint16 *list2, uint16 *pMatches )
  441. {
  442. byte x, y;
  443. uint16 z;
  444. byte numMatches = 0;
  445. // Check the first in against the seconds out
  446. for ( x = 0; x < numList1; x++ )
  447. {
  448. for ( y = 0; y < numList2; y++ )
  449. {
  450. z = list2[y];
  451. if ( list1[x] == z )
  452. pMatches[numMatches++] = z;
  453. }
  454. }
  455. return ( numMatches );
  456. }
  457. /*********************************************************************
  458. * Utility functions
  459. */
  460. /*********************************************************************
  461. * @fn ZDO_CompareByteLists
  462. *
  463. * @brief Compares two lists for matches.
  464. *
  465. * @param ACnt - number of entries in list A
  466. * @param AList - List A
  467. * @param BCnt - number of entries in list B
  468. * @param BList - List B
  469. *
  470. * @return true if a match is found
  471. */
  472. byte ZDO_AnyClusterMatches( byte ACnt, uint16 *AList, byte BCnt, uint16 *BList )
  473. {
  474. byte x, y;
  475. for ( x = 0; x < ACnt; x++ )
  476. {
  477. for ( y = 0; y < BCnt; y++ )
  478. {
  479. if ( AList[x] == BList[y] )
  480. {
  481. return true;
  482. }
  483. }
  484. }
  485. return false;
  486. }
  487. /*********************************************************************
  488. * Callback functions from ZDProfile
  489. */
  490. /*********************************************************************
  491. * @fn ZDO_ProcessNodeDescReq
  492. *
  493. * @brief This function processes and responds to the
  494. * Node_Desc_req message.
  495. *
  496. * @param inMsg - incoming message
  497. *
  498. * @return none
  499. */
  500. void ZDO_ProcessNodeDescReq( zdoIncomingMsg_t *inMsg )
  501. {
  502. uint16 aoi = BUILD_UINT16( inMsg->asdu[0], inMsg->asdu[1] );
  503. NodeDescriptorFormat_t *desc = NULL;
  504. if ( aoi == ZDAppNwkAddr.addr.shortAddr )
  505. {
  506. desc = &ZDO_Config_Node_Descriptor;
  507. }
  508. if ( desc != NULL )
  509. {
  510. ZDP_NodeDescMsg( inMsg, aoi, desc );
  511. }
  512. else
  513. {
  514. ZDP_GenericRsp( inMsg->TransSeq, &(inMsg->srcAddr),
  515. ZDP_INVALID_REQTYPE, aoi, Node_Desc_rsp, inMsg->SecurityUse );
  516. }
  517. }
  518. /*********************************************************************
  519. * @fn ZDO_ProcessPowerDescReq
  520. *
  521. * @brief This function processes and responds to the
  522. * Node_Power_req message.
  523. *
  524. * @param inMsg - incoming request
  525. *
  526. * @return none
  527. */
  528. void ZDO_ProcessPowerDescReq( zdoIncomingMsg_t *inMsg )
  529. {
  530. uint16 aoi = BUILD_UINT16( inMsg->asdu[0], inMsg->asdu[1] );
  531. NodePowerDescriptorFormat_t *desc = NULL;
  532. if ( aoi == ZDAppNwkAddr.addr.shortAddr )
  533. {
  534. desc = &ZDO_Config_Power_Descriptor;
  535. }
  536. if ( desc != NULL )
  537. {
  538. ZDP_PowerDescMsg( inMsg, aoi, desc );
  539. }
  540. else
  541. {
  542. ZDP_GenericRsp( inMsg->TransSeq, &(inMsg->srcAddr),
  543. ZDP_INVALID_REQTYPE, aoi, Power_Desc_rsp, inMsg->SecurityUse );
  544. }
  545. }
  546. /*********************************************************************
  547. * @fn ZDO_ProcessSimpleDescReq
  548. *
  549. * @brief This function processes and responds to the
  550. * Simple_Desc_req message.
  551. *
  552. * @param inMsg - incoming message (request)
  553. *
  554. * @return none
  555. */
  556. void ZDO_ProcessSimpleDescReq( zdoIncomingMsg_t *inMsg )
  557. {
  558. SimpleDescriptionFormat_t *sDesc = NULL;
  559. uint16 aoi = BUILD_UINT16( inMsg->asdu[0], inMsg->asdu[1] );
  560. byte endPoint = inMsg->asdu[2];
  561. byte free = false;
  562. byte stat = ZDP_SUCCESS;
  563. if ( (endPoint == ZDO_EP) || (endPoint > MAX_ENDPOINTS) )
  564. {
  565. stat = ZDP_INVALID_EP;
  566. }
  567. else if ( aoi == ZDAppNwkAddr.addr.shortAddr )
  568. {
  569. free = afFindSimpleDesc( &sDesc, endPoint );
  570. if ( sDesc == NULL )
  571. {
  572. stat = ZDP_NOT_ACTIVE;
  573. }
  574. }
  575. else
  576. {
  577. if ( ZSTACK_ROUTER_BUILD )
  578. {
  579. stat = ZDP_DEVICE_NOT_FOUND;
  580. }
  581. else if ( ZSTACK_END_DEVICE_BUILD )
  582. {
  583. stat = ZDP_INVALID_REQTYPE;
  584. }
  585. }
  586. ZDP_SimpleDescMsg( inMsg, stat, sDesc );
  587. if ( free && sDesc )
  588. {
  589. osal_mem_free( sDesc );
  590. }
  591. }
  592. /*********************************************************************
  593. * @fn ZDO_ProcessActiveEPReq
  594. *
  595. * @brief This function processes and responds to the
  596. * Active_EP_req message.
  597. *
  598. * @param inMsg - incoming message (request)
  599. *
  600. * @return none
  601. */
  602. void ZDO_ProcessActiveEPReq( zdoIncomingMsg_t *inMsg )
  603. {
  604. byte cnt = 0;
  605. uint16 aoi;
  606. byte stat = ZDP_SUCCESS;
  607. aoi = BUILD_UINT16( inMsg->asdu[0], inMsg->asdu[1] );
  608. if ( aoi == NLME_GetShortAddr() )
  609. {
  610. cnt = afNumEndPoints() - 1; // -1 for ZDO endpoint descriptor
  611. afEndPoints( (uint8 *)ZDOBuildBuf, true );
  612. }
  613. else
  614. {
  615. stat = ZDP_INVALID_REQTYPE;
  616. }
  617. ZDP_ActiveEPRsp( inMsg->TransSeq, &(inMsg->srcAddr), stat,
  618. aoi, cnt, (uint8 *)ZDOBuildBuf, inMsg->SecurityUse );
  619. }
  620. /*********************************************************************
  621. * @fn ZDO_ConvertOTAClusters
  622. *
  623. * @brief This function will convert the over-the-air cluster list
  624. * format to an internal format.
  625. *
  626. * @param inMsg - incoming message (request)
  627. *
  628. * @return pointer to incremented inBuf
  629. */
  630. uint8 *ZDO_ConvertOTAClusters( uint8 cnt, uint8 *inBuf, uint16 *outList )
  631. {
  632. uint8 x;
  633. for ( x = 0; x < cnt; x++ )
  634. {
  635. // convert ota format to internal
  636. outList[x] = BUILD_UINT16( inBuf[0], inBuf[1] );
  637. inBuf += sizeof( uint16 );
  638. }
  639. return ( inBuf );
  640. }
  641. /*********************************************************************
  642. * @fn ZDO_ProcessMatchDescReq
  643. *
  644. * @brief This function processes and responds to the
  645. * Match_Desc_req message.
  646. *
  647. * @param inMsg - incoming message (request)
  648. *
  649. * @return none
  650. */
  651. void ZDO_ProcessMatchDescReq( zdoIncomingMsg_t *inMsg )
  652. {
  653. uint8 epCnt = 0;
  654. uint8 numInClusters;
  655. uint16 *inClusters = NULL;
  656. uint8 numOutClusters;
  657. uint16 *outClusters = NULL;
  658. epList_t *epDesc;
  659. SimpleDescriptionFormat_t *sDesc = NULL;
  660. uint8 allocated;
  661. uint8 *msg;
  662. uint16 aoi;
  663. uint16 profileID;
  664. // Parse the incoming message
  665. msg = inMsg->asdu;
  666. aoi = BUILD_UINT16( msg[0], msg[1] );
  667. profileID = BUILD_UINT16( msg[2], msg[3] );
  668. msg += 4;
  669. if ( ADDR_BCAST_NOT_ME == NLME_IsAddressBroadcast(aoi) )
  670. {
  671. ZDP_MatchDescRsp( inMsg->TransSeq, &(inMsg->srcAddr), ZDP_INVALID_REQTYPE,
  672. ZDAppNwkAddr.addr.shortAddr, 0, NULL, inMsg->SecurityUse );
  673. return;
  674. }
  675. else if ( (ADDR_NOT_BCAST == NLME_IsAddressBroadcast(aoi)) && (aoi != ZDAppNwkAddr.addr.shortAddr) )
  676. {
  677. ZDP_MatchDescRsp( inMsg->TransSeq, &(inMsg->srcAddr), ZDP_INVALID_REQTYPE,
  678. ZDAppNwkAddr.addr.shortAddr, 0, NULL, inMsg->SecurityUse );
  679. return;
  680. }
  681. if ((numInClusters = *msg++) &&
  682. (inClusters = (uint16*)osal_mem_alloc( numInClusters * sizeof( uint16 ) )))
  683. {
  684. msg = ZDO_ConvertOTAClusters( numInClusters, msg, inClusters );
  685. }
  686. else
  687. {
  688. numInClusters = 0;
  689. }
  690. if ((numOutClusters = *msg++) &&
  691. (outClusters = (uint16 *)osal_mem_alloc( numOutClusters * sizeof( uint16 ) )))
  692. {
  693. msg = ZDO_ConvertOTAClusters( numOutClusters, msg, outClusters );
  694. }
  695. else
  696. {
  697. numOutClusters = 0;
  698. }
  699. // First count the number of endpoints that match.
  700. epDesc = epList;
  701. while ( epDesc )
  702. {
  703. // Don't search endpoint 0 and check if response is allowed
  704. if ( epDesc->epDesc->endPoint != ZDO_EP && (epDesc->flags&eEP_AllowMatch) )
  705. {
  706. if ( epDesc->pfnDescCB )
  707. {
  708. sDesc = (SimpleDescriptionFormat_t *)epDesc->pfnDescCB( AF_DESCRIPTOR_SIMPLE, epDesc->epDesc->endPoint );
  709. allocated = TRUE;
  710. }
  711. else
  712. {
  713. sDesc = epDesc->epDesc->simpleDesc;
  714. allocated = FALSE;
  715. }
  716. if ( sDesc && sDesc->AppProfId == profileID )
  717. {
  718. uint8 *uint8Buf = (uint8 *)ZDOBuildBuf;
  719. // If there are no search input/ouput clusters - respond
  720. if ( ((numInClusters == 0) && (numOutClusters == 0))
  721. // Are there matching input clusters?
  722. || (ZDO_AnyClusterMatches( numInClusters, inClusters,
  723. sDesc->AppNumInClusters, sDesc->pAppInClusterList ))
  724. // Are there matching output clusters?
  725. || (ZDO_AnyClusterMatches( numOutClusters, outClusters,
  726. sDesc->AppNumOutClusters, sDesc->pAppOutClusterList )) )
  727. {
  728. // Notify the endpoint of the match.
  729. uint8 bufLen = sizeof( ZDO_MatchDescRspSent_t ) + (numOutClusters + numInClusters) * sizeof(uint16);
  730. ZDO_MatchDescRspSent_t *pRspSent = (ZDO_MatchDescRspSent_t *) osal_msg_allocate( bufLen );
  731. if (pRspSent)
  732. {
  733. pRspSent->hdr.event = ZDO_MATCH_DESC_RSP_SENT;
  734. pRspSent->nwkAddr = inMsg->srcAddr.addr.shortAddr;
  735. pRspSent->numInClusters = numInClusters;
  736. pRspSent->numOutClusters = numOutClusters;
  737. if (numInClusters)
  738. {
  739. pRspSent->pInClusters = (uint16*) (pRspSent + 1);
  740. osal_memcpy(pRspSent->pInClusters, inClusters, numInClusters * sizeof(uint16));
  741. }
  742. else
  743. {
  744. pRspSent->pInClusters = NULL;
  745. }
  746. if (numOutClusters)
  747. {
  748. pRspSent->pOutClusters = (uint16*)(pRspSent + 1) + numInClusters;
  749. osal_memcpy(pRspSent->pOutClusters, outClusters, numOutClusters * sizeof(uint16));
  750. }
  751. else
  752. {
  753. pRspSent->pOutClusters = NULL;
  754. }
  755. osal_msg_send( *epDesc->epDesc->task_id, (uint8 *)pRspSent );
  756. }
  757. uint8Buf[epCnt++] = sDesc->EndPoint;
  758. }
  759. }
  760. if ( allocated )
  761. osal_mem_free( sDesc );
  762. }
  763. epDesc = epDesc->nextDesc;
  764. }
  765. // Send the message only if at least one match found.
  766. if ( epCnt )
  767. {
  768. if ( ZSuccess == ZDP_MatchDescRsp( inMsg->TransSeq, &(inMsg->srcAddr), ZDP_SUCCESS,
  769. ZDAppNwkAddr.addr.shortAddr, epCnt, (uint8 *)ZDOBuildBuf, inMsg->SecurityUse ) )
  770. {
  771. #if defined( LCD_SUPPORTED )
  772. HalLcdWriteScreen( "Match Desc Req", "Rsp Sent" );
  773. #endif
  774. }
  775. }
  776. else
  777. {
  778. #if defined( LCD_SUPPORTED )
  779. HalLcdWriteScreen( "Match Desc Req", "Non Matched" );
  780. #endif
  781. }
  782. if ( inClusters != NULL )
  783. osal_mem_free( inClusters );
  784. if ( outClusters != NULL )
  785. osal_mem_free( outClusters );
  786. }
  787. /*********************************************************************
  788. * @fn ZDO_ProcessBindUnbindReq()
  789. *
  790. * @brief Called to process a Bind or Unbind Request message.
  791. *
  792. * @param inMsg - incoming message (request)
  793. * @param pReq - place to put parsed information
  794. *
  795. * @return none
  796. */
  797. void ZDO_ProcessBindUnbindReq( zdoIncomingMsg_t *inMsg, ZDO_BindUnbindReq_t *pReq )
  798. {
  799. zAddrType_t SourceAddr; // Binding Source addres
  800. byte bindStat;
  801. SourceAddr.addrMode = Addr64Bit;
  802. osal_cpyExtAddr( SourceAddr.addr.extAddr, pReq->srcAddress );
  803. // If the local device is not the primary binding cache
  804. // check the src address of the bind request.
  805. // If it is not the local device's extended address
  806. // discard the request.
  807. if ( !osal_ExtAddrEqual( SourceAddr.addr.extAddr, NLME_GetExtAddr()) ||
  808. (pReq->dstAddress.addrMode != Addr64Bit &&
  809. pReq->dstAddress.addrMode != AddrGroup) )
  810. {
  811. bindStat = ZDP_NOT_SUPPORTED;
  812. }
  813. else
  814. {
  815. // Check source & destination endpoints
  816. if ( (pReq->srcEndpoint == 0 || pReq->srcEndpoint > MAX_ENDPOINTS)
  817. || (( pReq->dstAddress.addrMode == Addr64Bit ) &&
  818. (pReq->dstEndpoint == 0 || pReq->dstEndpoint > MAX_ENDPOINTS)) )
  819. {
  820. bindStat = ZDP_INVALID_EP;
  821. }
  822. else
  823. {
  824. if ( inMsg->clusterID == Bind_req )
  825. {
  826. // Assume the table is full
  827. bindStat = ZDP_TABLE_FULL;
  828. if ( bindNumOfEntries() < gNWK_MAX_BINDING_ENTRIES )
  829. {
  830. if ( APSME_BindRequest( pReq->srcEndpoint, pReq->clusterID,
  831. &(pReq->dstAddress), pReq->dstEndpoint ) == ZSuccess )
  832. {
  833. uint16 nwkAddr;
  834. // valid entry
  835. bindStat = ZDP_SUCCESS;
  836. // Notify to save info into NV
  837. ZDApp_NVUpdate();
  838. // Check for the destination address
  839. if ( pReq->dstAddress.addrMode == Addr64Bit )
  840. {
  841. if ( APSME_LookupNwkAddr( pReq->dstAddress.addr.extAddr, &nwkAddr ) == FALSE )
  842. {
  843. ZDP_NwkAddrReq( pReq->dstAddress.addr.extAddr, ZDP_ADDR_REQTYPE_SINGLE, 0, 0 );
  844. }
  845. }
  846. }
  847. }
  848. }
  849. else // Unbind_req
  850. {
  851. if ( APSME_UnBindRequest( pReq->srcEndpoint, pReq->clusterID,
  852. &(pReq->dstAddress), pReq->dstEndpoint ) == ZSuccess )
  853. {
  854. bindStat = ZDP_SUCCESS;
  855. // Notify to save info into NV
  856. ZDApp_NVUpdate();
  857. }
  858. else
  859. bindStat = ZDP_NO_ENTRY;
  860. }
  861. }
  862. }
  863. // Send back a response message
  864. ZDP_SendData( &(inMsg->TransSeq), &(inMsg->srcAddr),
  865. (inMsg->clusterID | ZDO_RESPONSE_BIT), 1, &bindStat,
  866. inMsg->SecurityUse );
  867. }
  868. /*********************************************************************
  869. * @fn ZDO_UpdateAddrManager
  870. *
  871. * @brief Update the Address Manager.
  872. *
  873. * @param nwkAddr - network address
  874. * @param extAddr - extended address
  875. *
  876. * @return none
  877. */
  878. void ZDO_UpdateAddrManager( uint16 nwkAddr, uint8 *extAddr )
  879. {
  880. AddrMgrEntry_t addrEntry;
  881. // Update the address manager
  882. addrEntry.user = ADDRMGR_USER_DEFAULT;
  883. addrEntry.nwkAddr = nwkAddr;
  884. AddrMgrExtAddrSet( addrEntry.extAddr, extAddr );
  885. AddrMgrEntryUpdate( &addrEntry );
  886. }
  887. /*********************************************************************
  888. * @fn ZDO_ProcessServerDiscReq
  889. *
  890. * @brief Process the Server_Discovery_req message.
  891. *
  892. * @param inMsg - incoming message (request)
  893. *
  894. * @return none
  895. */
  896. void ZDO_ProcessServerDiscReq( zdoIncomingMsg_t *inMsg )
  897. {
  898. uint16 serverMask = BUILD_UINT16( inMsg->asdu[0], inMsg->asdu[1] );
  899. uint16 matchMask = serverMask & ZDO_Config_Node_Descriptor.ServerMask;
  900. if ( matchMask )
  901. {
  902. ZDP_ServerDiscRsp( inMsg->TransSeq, &(inMsg->srcAddr), ZSUCCESS,
  903. ZDAppNwkAddr.addr.shortAddr, matchMask, inMsg->SecurityUse );
  904. }
  905. }
  906. /*********************************************************************
  907. * Call Back Functions from APS - API
  908. */
  909. /*********************************************************************
  910. * @fn ZDO_EndDeviceTimeoutCB
  911. *
  912. * @brief This function handles the binding timer for the End
  913. * Device Bind command.
  914. *
  915. * @param none
  916. *
  917. * @return none
  918. */
  919. void ZDO_EndDeviceTimeoutCB( void )
  920. {
  921. #if defined ( REFLECTOR )
  922. byte stat;
  923. if ( ZDO_EDBind )
  924. {
  925. stat = ZDO_EDBind->status;
  926. // Send the response message to the first sent
  927. ZDO_SendEDBindRsp( ZDO_EDBind->SrcTransSeq, &(ZDO_EDBind->SrcAddr),
  928. stat, ZDO_EDBind->SecurityUse );
  929. ZDO_RemoveEndDeviceBind();
  930. }
  931. #endif // REFLECTOR
  932. }
  933. /*********************************************************************
  934. * Optional Management Messages
  935. */
  936. /*********************************************************************
  937. * @fn ZDO_ProcessMgmtLqiReq
  938. *
  939. * @brief This function handles parsing the incoming Management
  940. * LQI request and generate the response.
  941. *
  942. * Note: This function will limit the number of items returned
  943. * to ZDO_MAX_LQI_ITEMS items.
  944. *
  945. * @param inMsg - incoming message (request)
  946. *
  947. * @return none
  948. */
  949. void ZDO_ProcessMgmtLqiReq( zdoIncomingMsg_t *inMsg )
  950. {
  951. byte x;
  952. byte index;
  953. byte numItems;
  954. byte maxItems;
  955. ZDP_MgmtLqiItem_t* table = NULL;
  956. ZDP_MgmtLqiItem_t* item;
  957. neighborEntry_t entry;
  958. byte aItems;
  959. associated_devices_t *aDevice;
  960. AddrMgrEntry_t nwkEntry;
  961. uint8 StartIndex = inMsg->asdu[0];
  962. // Get the number of neighbor items
  963. NLME_GetRequest( nwkNumNeighborTableEntries, 0, &maxItems );
  964. // Get the number of associated items
  965. aItems = (uint8)AssocCount( PARENT, CHILD_FFD_RX_IDLE );
  966. // Total number of items
  967. maxItems += aItems;
  968. // Start with the supplied index
  969. if ( maxItems > StartIndex )
  970. {
  971. numItems = maxItems - StartIndex;
  972. // limit the size of the list
  973. if ( numItems > ZDO_MAX_LQI_ITEMS )
  974. numItems = ZDO_MAX_LQI_ITEMS;
  975. // Allocate the memory to build the table
  976. table = (ZDP_MgmtLqiItem_t*)osal_mem_alloc( (short)
  977. ( numItems * sizeof( ZDP_MgmtLqiItem_t ) ) );
  978. if ( table != NULL )
  979. {
  980. x = 0;
  981. item = table;
  982. index = StartIndex;
  983. // Loop through associated items and build list
  984. for ( ; x < numItems; x++ )
  985. {
  986. if ( index < aItems )
  987. {
  988. // get next associated device
  989. aDevice = AssocFindDevice( index++ );
  990. // set basic fields
  991. item->panID = _NIB.nwkPanId;
  992. osal_cpyExtAddr( item->extPanID, _NIB.extendedPANID );
  993. item->nwkAddr = aDevice->shortAddr;
  994. item->permit = ZDP_MGMT_BOOL_UNKNOWN;
  995. item->depth = 0xFF;
  996. item->lqi = aDevice->linkInfo.rxLqi;
  997. // set extented address
  998. nwkEntry.user = ADDRMGR_USER_DEFAULT;
  999. nwkEntry.nwkAddr = aDevice->shortAddr;
  1000. if ( AddrMgrEntryLookupNwk( &nwkEntry ) == TRUE )
  1001. {
  1002. osal_cpyExtAddr( item->extAddr, nwkEntry.extAddr );
  1003. }
  1004. else
  1005. {
  1006. osal_memset( item->extAddr, 0xFF, Z_EXTADDR_LEN );
  1007. }
  1008. // use association info to set other fields
  1009. if ( aDevice->nodeRelation == PARENT )
  1010. {
  1011. if ( aDevice->shortAddr == 0 )
  1012. {
  1013. item->devType = ZDP_MGMT_DT_COORD;
  1014. item->depth = 0;
  1015. }
  1016. else
  1017. {
  1018. item->devType = ZDP_MGMT_DT_ROUTER;
  1019. item->depth = _NIB.nodeDepth - 1;
  1020. }
  1021. item->rxOnIdle = ZDP_MGMT_BOOL_UNKNOWN;
  1022. item->relation = ZDP_MGMT_REL_PARENT;
  1023. }
  1024. else
  1025. {
  1026. // If not parent, then it's a child
  1027. item->depth = _NIB.nodeDepth + 1;
  1028. if ( aDevice->nodeRelation < CHILD_FFD )
  1029. {
  1030. item->devType = ZDP_MGMT_DT_ENDDEV;
  1031. if ( aDevice->nodeRelation == CHILD_RFD )
  1032. {
  1033. item->rxOnIdle = FALSE;
  1034. }
  1035. else
  1036. {
  1037. item->rxOnIdle = TRUE;
  1038. }
  1039. }
  1040. else
  1041. {
  1042. item->devType = ZDP_MGMT_DT_ROUTER;
  1043. if ( aDevice->nodeRelation == CHILD_FFD )
  1044. {
  1045. item->rxOnIdle = FALSE;
  1046. }
  1047. else
  1048. {
  1049. item->rxOnIdle = TRUE;
  1050. }
  1051. }
  1052. item->relation = ZDP_MGMT_REL_CHILD;
  1053. }
  1054. item++;
  1055. }
  1056. else
  1057. {
  1058. if ( StartIndex <= aItems )
  1059. // Start with 1st neighbor
  1060. index = 0;
  1061. else
  1062. // Start with >1st neighbor
  1063. index = StartIndex - aItems;
  1064. break;
  1065. }
  1066. }
  1067. // Loop through neighbor items and finish list
  1068. for ( ; x < numItems; x++ )
  1069. {
  1070. // Add next neighbor table item
  1071. NLME_GetRequest( nwkNeighborTable, index++, &entry );
  1072. // set ZDP_MgmtLqiItem_t fields
  1073. item->panID = entry.panId;
  1074. osal_cpyExtAddr( item->extPanID, _NIB.extendedPANID );
  1075. osal_memset( item->extAddr, 0xFF, Z_EXTADDR_LEN );
  1076. item->nwkAddr = entry.neighborAddress;
  1077. item->rxOnIdle = ZDP_MGMT_BOOL_UNKNOWN;
  1078. item->relation = ZDP_MGMT_REL_UNKNOWN;
  1079. item->permit = ZDP_MGMT_BOOL_UNKNOWN;
  1080. item->depth = 0xFF;
  1081. item->lqi = entry.linkInfo.rxLqi;
  1082. if ( item->nwkAddr == 0 )
  1083. {
  1084. item->devType = ZDP_MGMT_DT_COORD;
  1085. }
  1086. else
  1087. {
  1088. item->devType = ZDP_MGMT_DT_ROUTER;
  1089. }
  1090. item++;
  1091. }
  1092. }
  1093. }
  1094. else
  1095. {
  1096. numItems = 0;
  1097. }
  1098. // Send response
  1099. ZDP_MgmtLqiRsp( inMsg->TransSeq, &(inMsg->srcAddr), ZSuccess, maxItems,
  1100. StartIndex, numItems, table, false );
  1101. if ( table )
  1102. {
  1103. osal_mem_free( table );
  1104. }
  1105. }
  1106. /*********************************************************************
  1107. * @fn ZDO_ProcessMgmtNwkDiscReq
  1108. *
  1109. * @brief This function handles parsing the incoming Management
  1110. * Network Discover request and starts the request.
  1111. *
  1112. * @param inMsg - incoming message (request)
  1113. *
  1114. * @return none
  1115. */
  1116. void ZDO_ProcessMgmtNwkDiscReq( zdoIncomingMsg_t *inMsg )
  1117. {
  1118. NLME_ScanFields_t scan;
  1119. uint8 index;
  1120. uint8 *msg;
  1121. msg = inMsg->asdu;
  1122. scan.channels = osal_build_uint32( msg, 4 );
  1123. msg += 4;
  1124. scan.duration = *msg++;
  1125. index = *msg;
  1126. scan.scanType = ZMAC_ACTIVE_SCAN;
  1127. scan.scanApp = NLME_DISC_SCAN;
  1128. // Save off the information to be used for the response
  1129. zdappMgmtNwkDiscReqInProgress = true;
  1130. zdappMgmtNwkDiscRspAddr.addrMode = Addr16Bit;
  1131. zdappMgmtNwkDiscRspAddr.addr.shortAddr = inMsg->srcAddr.addr.shortAddr;
  1132. zdappMgmtNwkDiscStartIndex = index;
  1133. zdappMgmtNwkDiscRspTransSeq = inMsg->TransSeq;
  1134. if ( NLME_NwkDiscReq2( &scan ) != ZSuccess )
  1135. {
  1136. NLME_NwkDiscTerm();
  1137. // zdappMgmtNwkDiscReqInProgress will be reset in the confirm callback
  1138. }
  1139. }
  1140. #if defined ( ZDO_MGMT_NWKDISC_RESPONSE )
  1141. /*********************************************************************
  1142. * @fn ZDO_FinishProcessingMgmtNwkDiscReq
  1143. *
  1144. * @brief This function finishes the processing of the Management
  1145. * Network Discover Request and generates the response.
  1146. *
  1147. * Note: This function will limit the number of items returned
  1148. * to ZDO_MAX_NWKDISC_ITEMS items.
  1149. *
  1150. * @param ResultCountSrcAddr - source of the request
  1151. * @param msg - pointer to incoming message
  1152. * @param SecurityUse -
  1153. *
  1154. * @return none
  1155. */
  1156. void ZDO_FinishProcessingMgmtNwkDiscReq( byte ResultCount,
  1157. networkDesc_t *NetworkList )
  1158. {
  1159. byte count, i;
  1160. networkDesc_t *newDesc = NULL, *pList = NetworkList;
  1161. if ( ZSTACK_ROUTER_BUILD )
  1162. {
  1163. // Look for my PanID.
  1164. while ( pList )
  1165. {
  1166. if ( pList->panId == _NIB.nwkPanId )
  1167. {
  1168. break;
  1169. }
  1170. if ( !pList->nextDesc )
  1171. {
  1172. break;
  1173. }
  1174. pList = pList->nextDesc;
  1175. }
  1176. // If my Pan not present (query to a star network ZC or an isolated ZR?),
  1177. // prepend it.
  1178. if ( !pList || (pList->panId != _NIB.nwkPanId) )
  1179. {
  1180. newDesc = (networkDesc_t *)osal_mem_alloc( sizeof( networkDesc_t ) );
  1181. if ( newDesc )
  1182. {
  1183. byte pJoin;
  1184. newDesc->panId = _NIB.nwkPanId;
  1185. newDesc->logicalChannel = _NIB.nwkLogicalChannel;
  1186. newDesc->beaconOrder = _NIB.beaconOrder;
  1187. newDesc->superFrameOrder = _NIB.superFrameOrder;
  1188. newDesc->version = NLME_GetProtocolVersion();
  1189. newDesc->stackProfile = zgStackProfile;
  1190. //Extended PanID
  1191. osal_cpyExtAddr( newDesc->extendedPANID, _NIB.extendedPANID);
  1192. ZMacGetReq( ZMacAssociationPermit, &pJoin );
  1193. newDesc->chosenRouter = ((pJoin) ? ZDAppNwkAddr.addr.shortAddr :
  1194. INVALID_NODE_ADDR);
  1195. newDesc->nextDesc = NetworkList;
  1196. NetworkList = newDesc;
  1197. ResultCount++;
  1198. }
  1199. }
  1200. }
  1201. // Calc the count and apply a max count.
  1202. if ( zdappMgmtNwkDiscStartIndex > ResultCount )
  1203. {
  1204. count = 0;
  1205. }
  1206. else
  1207. {
  1208. count = ResultCount - zdappMgmtNwkDiscStartIndex;
  1209. if ( count > ZDO_MAX_NWKDISC_ITEMS )
  1210. {
  1211. count = ZDO_MAX_NWKDISC_ITEMS;
  1212. }
  1213. // Move the list pointer up to the start index.
  1214. for ( i = 0; i < zdappMgmtNwkDiscStartIndex; i++ )
  1215. {
  1216. NetworkList = NetworkList->nextDesc;
  1217. }
  1218. }
  1219. ZDP_MgmtNwkDiscRsp( zdappMgmtNwkDiscRspTransSeq,
  1220. &zdappMgmtNwkDiscRspAddr, ZSuccess, ResultCount,
  1221. zdappMgmtNwkDiscStartIndex,
  1222. count,
  1223. NetworkList,
  1224. false );
  1225. if ( ZSTACK_ROUTER_BUILD )
  1226. {
  1227. if ( newDesc != NULL )
  1228. {
  1229. osal_mem_free( newDesc );
  1230. }
  1231. }
  1232. NLME_NwkDiscTerm();
  1233. }
  1234. #endif
  1235. /*********************************************************************
  1236. * @fn ZDO_ProcessMgmtRtgReq
  1237. *
  1238. * @brief This function finishes the processing of the Management
  1239. * Routing Request and generates the response.
  1240. *
  1241. * Note: This function will limit the number of items returned
  1242. * to ZDO_MAX_RTG_ITEMS items.
  1243. *
  1244. * @param inMsg - incoming message (request)
  1245. *
  1246. * @return none
  1247. */
  1248. void ZDO_ProcessMgmtRtgReq( zdoIncomingMsg_t *inMsg )
  1249. {
  1250. byte x;
  1251. byte maxNumItems;
  1252. byte numItems = 0;
  1253. uint8 *pBuf = NULL;
  1254. rtgItem_t *pList;
  1255. uint8 StartIndex = inMsg->asdu[0];
  1256. // Get the number of table items
  1257. NLME_GetRequest( nwkNumRoutingTableEntries, 0, &maxNumItems );
  1258. if ( maxNumItems > StartIndex )
  1259. {
  1260. numItems = maxNumItems - StartIndex; // Start at the passed in index
  1261. // limit the size of the list
  1262. if ( numItems > ZDO_MAX_RTG_ITEMS )
  1263. {
  1264. numItems = ZDO_MAX_RTG_ITEMS;
  1265. }
  1266. // Allocate the memory to build the table
  1267. pBuf = osal_mem_alloc( (short)(sizeof( rtgItem_t ) * numItems) );
  1268. if ( pBuf != NULL )
  1269. {
  1270. // Convert buffer to list
  1271. pList = (rtgItem_t *)pBuf;
  1272. // Loop through items and build list
  1273. for ( x = 0; x < numItems; x++ )
  1274. {
  1275. NLME_GetRequest( nwkRoutingTable, (uint16)(x + StartIndex), (void*)pList );
  1276. // Remap the status to the RoutingTableList Record Format defined in the ZigBee spec
  1277. switch( pList->status )
  1278. {
  1279. case RT_ACTIVE:
  1280. pList->status = ZDO_MGMT_RTG_ENTRY_ACTIVE;
  1281. break;
  1282. case RT_DISC:
  1283. pList->status = ZDO_MGMT_RTG_ENTRY_DISCOVERY_UNDERWAY;
  1284. break;
  1285. case RT_LINK_FAIL:
  1286. pList->status = ZDO_MGMT_RTG_ENTRY_DISCOVERY_FAILED;
  1287. case RT_INIT:
  1288. case RT_REPAIR:
  1289. default:
  1290. pList->status = ZDO_MGMT_RTG_ENTRY_INACTIVE;
  1291. break;
  1292. }
  1293. // Increment pointer to next record
  1294. pList++;
  1295. }
  1296. }
  1297. else
  1298. {
  1299. numItems = 0;
  1300. }
  1301. }
  1302. // Send response
  1303. ZDP_MgmtRtgRsp( inMsg->TransSeq, &(inMsg->srcAddr), ZSuccess, maxNumItems, StartIndex, numItems,
  1304. (rtgItem_t *)pBuf, false );
  1305. if ( pBuf )
  1306. {
  1307. osal_mem_free( pBuf );
  1308. }
  1309. }
  1310. /*********************************************************************
  1311. * @fn ZDO_ProcessMgmtBindReq
  1312. *
  1313. * @brief This function finishes the processing of the Management
  1314. * Bind Request and generates the response.
  1315. *
  1316. * Note: This function will limit the number of items returned
  1317. * to ZDO_MAX_BIND_ITEMS items.
  1318. *
  1319. * @param inMsg - incoming message (request)
  1320. *
  1321. * @return none
  1322. */
  1323. void ZDO_ProcessMgmtBindReq( zdoIncomingMsg_t *inMsg )
  1324. {
  1325. #if defined ( REFLECTOR )
  1326. byte x;
  1327. uint16 maxNumItems;
  1328. uint16 numItems;
  1329. uint8 *pBuf = NULL;
  1330. apsBindingItem_t *pList;
  1331. uint8 StartIndex = inMsg->asdu[0];
  1332. uint8 status;
  1333. // Get the number of table items
  1334. APSME_GetRequest( apsNumBindingTableEntries, 0, (byte*)(&maxNumItems) );
  1335. if ( maxNumItems > StartIndex )
  1336. {
  1337. numItems = maxNumItems - StartIndex; // Start at the passed in index
  1338. }
  1339. else
  1340. {
  1341. numItems = 0;
  1342. }
  1343. // limit the size of the list
  1344. if ( numItems > ZDO_MAX_BIND_ITEMS )
  1345. {
  1346. numItems = ZDO_MAX_BIND_ITEMS;
  1347. }
  1348. // Allocate the memory to build the table
  1349. if ( numItems && (pBuf = osal_mem_alloc( sizeof( apsBindingItem_t ) * numItems )) )
  1350. {
  1351. status = ZSuccess;
  1352. // Convert buffer to list
  1353. pList = (apsBindingItem_t *)pBuf;
  1354. // Loop through items and build list
  1355. for ( x = 0; x < numItems; x++ )
  1356. {
  1357. APSME_GetRequest( apsBindingTable, (x + StartIndex), (void*)pList );
  1358. pList++;
  1359. }
  1360. }
  1361. else
  1362. {
  1363. status = ZDP_NOT_PERMITTED;
  1364. numItems = 0;
  1365. }
  1366. // Send response
  1367. ZDP_MgmtBindRsp( inMsg->TransSeq, &(inMsg->srcAddr), status, (byte)maxNumItems, StartIndex,
  1368. (byte)numItems, (apsBindingItem_t *)pBuf, false );
  1369. if ( pBuf )
  1370. {
  1371. osal_mem_free( pBuf );
  1372. }
  1373. #else
  1374. (void)inMsg;
  1375. #endif
  1376. }
  1377. /*********************************************************************
  1378. * @fn ZDO_ProcessMgmtDirectJoinReq
  1379. *
  1380. * @brief This function finishes the processing of the Management
  1381. * Direct Join Request and generates the response.
  1382. *
  1383. * @param inMsg - incoming message (request)
  1384. *
  1385. * @return none
  1386. */
  1387. void ZDO_ProcessMgmtDirectJoinReq( zdoIncomingMsg_t *inMsg )
  1388. {
  1389. uint8 *deviceAddr;
  1390. uint8 capInfo;
  1391. uint8 stat;
  1392. // Parse the message
  1393. deviceAddr = inMsg->asdu;
  1394. capInfo = inMsg->asdu[Z_EXTADDR_LEN];
  1395. stat = (byte) NLME_DirectJoinRequest( deviceAddr, capInfo );
  1396. ZDP_MgmtDirectJoinRsp( inMsg->TransSeq, &(inMsg->srcAddr), stat, false );
  1397. }
  1398. /*********************************************************************
  1399. * @fn ZDO_ProcessMgmtLeaveReq
  1400. *
  1401. * @brief This function processes a Management Leave Request
  1402. * and generates the response.
  1403. *
  1404. * @param inMsg - incoming message (request)
  1405. *
  1406. * @return none
  1407. */
  1408. void ZDO_ProcessMgmtLeaveReq( zdoIncomingMsg_t *inMsg )
  1409. {
  1410. NLME_LeaveReq_t req;
  1411. ZStatus_t status;
  1412. uint8 option;
  1413. uint8 *msg = inMsg->asdu;
  1414. if ( ( AddrMgrExtAddrValid( msg ) == FALSE ) ||
  1415. ( osal_ExtAddrEqual( msg, NLME_GetExtAddr() ) == TRUE ) )
  1416. {
  1417. // Remove this device
  1418. req.extAddr = NULL;
  1419. }
  1420. else
  1421. {
  1422. // Remove child device
  1423. req.extAddr = msg;
  1424. }
  1425. option = msg[Z_EXTADDR_LEN];
  1426. if ( option & ZDP_MGMT_LEAVE_REQ_RC )
  1427. {
  1428. req.removeChildren = TRUE;
  1429. }
  1430. if ( option & ZDP_MGMT_LEAVE_REQ_REJOIN )
  1431. {
  1432. req.rejoin = TRUE;
  1433. }
  1434. req.silent = FALSE;
  1435. status = NLME_LeaveReq( &req );
  1436. ZDP_MgmtLeaveRsp( inMsg->TransSeq, &(inMsg->srcAddr), status, FALSE );
  1437. }
  1438. /*********************************************************************
  1439. * @fn ZDO_ProcessMgmtPermitJoinReq
  1440. *
  1441. * @brief This function processes a Management Permit Join Request
  1442. * and generates the response.
  1443. *
  1444. * @param inMsg - incoming message (request)
  1445. *
  1446. * @return none
  1447. */
  1448. void ZDO_ProcessMgmtPermitJoinReq( zdoIncomingMsg_t *inMsg )
  1449. {
  1450. uint8 stat;
  1451. uint8 duration;
  1452. uint8 tcsig;
  1453. duration = inMsg->asdu[ZDP_MGMT_PERMIT_JOIN_REQ_DURATION];
  1454. tcsig = inMsg->asdu[ZDP_MGMT_PERMIT_JOIN_REQ_TC_SIG];
  1455. // Set the network layer permit join duration
  1456. stat = (byte) NLME_PermitJoiningRequest( duration );
  1457. // Handle the Trust Center Significance
  1458. if ( ZG_SECURE_ENABLED && ZG_BUILD_COORDINATOR_TYPE && ZG_DEVICE_COORDINATOR_TYPE )
  1459. {
  1460. if ( tcsig == TRUE )
  1461. {
  1462. ZDSecMgrPermitJoining( duration );
  1463. }
  1464. }
  1465. // Send a response if unicast
  1466. if (inMsg->srcAddr.addr.shortAddr != NWK_BROADCAST_SHORTADDR)
  1467. {
  1468. ZDP_MgmtPermitJoinRsp( inMsg->TransSeq, &(inMsg->srcAddr), stat, false );
  1469. }
  1470. }
  1471. /*
  1472. * This function stub allows the next higher layer to be notified of
  1473. * a permit joining timeout.
  1474. */
  1475. /*********************************************************************
  1476. * @fn ZDO_ProcessMgmtPermitJoinTimeout
  1477. *
  1478. * @brief This function stub allows the next higher layer to be
  1479. * notified of a permit joining timeout. Currently, this
  1480. * directly bypasses the APS layer.
  1481. *
  1482. * @param none
  1483. *
  1484. * @return none
  1485. */
  1486. void ZDO_ProcessMgmtPermitJoinTimeout( void )
  1487. {
  1488. #if defined( ZDO_MGMT_PERMIT_JOIN_RESPONSE )
  1489. // Currently, only the ZDSecMgr needs to be notified
  1490. if ( ZG_SECURE_ENABLED && ZG_BUILD_COORDINATOR_TYPE && ZG_DEVICE_COORDINATOR_TYPE )
  1491. {
  1492. ZDSecMgrPermitJoiningTimeout();
  1493. }
  1494. #endif
  1495. }
  1496. /*********************************************************************
  1497. * @fn ZDO_ProcessUserDescReq
  1498. *
  1499. * @brief This function finishes the processing of the User
  1500. * Descriptor Request and generates the response.
  1501. *
  1502. * @param inMsg - incoming message (request)
  1503. *
  1504. * @return none
  1505. */
  1506. void ZDO_ProcessUserDescReq( zdoIncomingMsg_t *inMsg )
  1507. {
  1508. uint16 aoi = BUILD_UINT16( inMsg->asdu[0], inMsg->asdu[1] );
  1509. UserDescriptorFormat_t userDesc;
  1510. if ( (aoi == ZDAppNwkAddr.addr.shortAddr) && (ZSUCCESS == osal_nv_read(
  1511. ZCD_NV_USERDESC, 0, sizeof(UserDescriptorFormat_t), &userDesc )) )
  1512. {
  1513. ZDP_UserDescRsp( inMsg->TransSeq, &(inMsg->srcAddr), aoi, &userDesc, false );
  1514. }
  1515. else
  1516. {
  1517. ZDP_GenericRsp(inMsg->TransSeq, &(inMsg->srcAddr),
  1518. ZDP_NOT_SUPPORTED, aoi, User_Desc_rsp, inMsg->SecurityUse );
  1519. }
  1520. }
  1521. /*********************************************************************
  1522. * @fn ZDO_ProcessUserDescSet
  1523. *
  1524. * @brief This function finishes the processing of the User
  1525. * Descriptor Set and generates the response.
  1526. *
  1527. * @param inMsg - incoming message (request)
  1528. *
  1529. * @return none
  1530. */
  1531. void ZDO_ProcessUserDescSet( zdoIncomingMsg_t *inMsg )
  1532. {
  1533. uint8 *msg;
  1534. uint16 aoi;
  1535. UserDescriptorFormat_t userDesc;
  1536. uint8 outMsg[3];
  1537. uint8 status;
  1538. msg = inMsg->asdu;
  1539. aoi = BUILD_UINT16( msg[0], msg[1] );
  1540. if ( aoi == ZDAppNwkAddr.addr.shortAddr )
  1541. {
  1542. userDesc.len = (msg[2] < AF_MAX_USER_DESCRIPTOR_LEN) ? msg[2] : AF_MAX_USER_DESCRIPTOR_LEN;
  1543. msg ++; // increment one for the length field
  1544. osal_memcpy( userDesc.desc, &msg[2], userDesc.len );
  1545. osal_nv_write( ZCD_NV_USERDESC, 0, sizeof(UserDescriptorFormat_t), &userDesc );
  1546. if ( userDesc.len != 0 )
  1547. {
  1548. ZDO_Config_Node_Descriptor.UserDescAvail = TRUE;
  1549. }
  1550. else
  1551. {
  1552. ZDO_Config_Node_Descriptor.UserDescAvail = FALSE;
  1553. }
  1554. status = ZDP_SUCCESS;
  1555. }
  1556. else
  1557. {
  1558. status = ZDP_NOT_SUPPORTED;
  1559. }
  1560. outMsg[0] = status;
  1561. outMsg[1] = LO_UINT16( aoi );
  1562. outMsg[2] = LO_UINT16( aoi );
  1563. ZDP_SendData( &(inMsg->TransSeq), &(inMsg->srcAddr), User_Desc_conf, 3, outMsg,
  1564. inMsg->SecurityUse );
  1565. }
  1566. /*********************************************************************
  1567. * @fn ZDO_ProcessDeviceAnnce
  1568. *
  1569. * @brief This function processes a device annouce message.
  1570. *
  1571. * @param inMsg - incoming message
  1572. *
  1573. * @return none
  1574. */
  1575. void ZDO_ProcessDeviceAnnce( zdoIncomingMsg_t *inMsg )
  1576. {
  1577. ZDO_DeviceAnnce_t Annce;
  1578. AddrMgrEntry_t addrEntry;
  1579. uint8 parentExt[Z_EXTADDR_LEN];
  1580. // Parse incoming message
  1581. ZDO_ParseDeviceAnnce( inMsg, &Annce );
  1582. if ( ZSTACK_END_DEVICE_BUILD )
  1583. {
  1584. // Make sure the message didn't come from myself - end device only
  1585. if ( osal_ExtAddrEqual( NLME_GetExtAddr(), Annce.extAddr ) && Annce.nwkAddr == NLME_GetShortAddr() )
  1586. {
  1587. return;
  1588. }
  1589. }
  1590. #if defined ( ZIGBEE_STOCHASTIC_ADDRESSING )
  1591. // Clean up the neighbor table
  1592. nwkNeighborRemoveAllStranded();
  1593. // If address conflict is detected, no need to update the address manager
  1594. if ( NLME_CheckNewAddrSet( Annce.nwkAddr, Annce.extAddr )== ZFailure )
  1595. {
  1596. return;
  1597. }
  1598. #endif
  1599. #if defined ( ZIGBEE_STOCHASTIC_ADDRESSING )
  1600. // Check for parent's address
  1601. NLME_GetCoordExtAddr( parentExt );
  1602. if ( osal_ExtAddrEqual( parentExt, Annce.extAddr ) )
  1603. {
  1604. if ( Annce.nwkAddr != NLME_GetCoordShortAddr() )
  1605. {
  1606. // Set the Parent's MAC's new short address
  1607. _NIB.nwkCoordAddress = Annce.nwkAddr;
  1608. ZMacSetReq( ZMacCoordShortAddress, (byte*)&(_NIB.nwkCoordAddress) );
  1609. }
  1610. }
  1611. if ( ZSTACK_ROUTER_BUILD )
  1612. {
  1613. // If the device annce comes from a end device child that has moved
  1614. // to another parent, remove it from associated device list
  1615. // If the dev annce is coming from other device's children,
  1616. // (The dev annce from its own children shall be unicast to itself,
  1617. // So check the mac destination address)
  1618. // Remove it from the associated device list. If it is not
  1619. // a child, no action will be taken in AssocRemove() anyway.
  1620. if ( inMsg->macDestAddr != NLME_GetShortAddr() )
  1621. {
  1622. associated_devices_t *dev_ptr;
  1623. // If it's an end device child
  1624. dev_ptr = AssocGetWithExt( Annce.extAddr );
  1625. if ( dev_ptr )
  1626. {
  1627. if ( dev_ptr->nodeRelation == CHILD_RFD ||
  1628. dev_ptr->nodeRelation == CHILD_RFD_RX_IDLE )
  1629. {
  1630. AssocRemove( Annce.extAddr );
  1631. }
  1632. }
  1633. }
  1634. if ( Annce.nwkAddr != NLME_GetShortAddr() )
  1635. {
  1636. // If an associated device is found with matched extended Address,
  1637. // update its short address
  1638. if ( AssocChangeNwkAddr( Annce.nwkAddr, Annce.extAddr ) )
  1639. {
  1640. // Update the neighbor table
  1641. nwkNeighborUpdateNwkAddr( Annce.nwkAddr, Annce.extAddr );
  1642. // Set event to save NV
  1643. ZDApp_NVUpdate();
  1644. }
  1645. }
  1646. }
  1647. #endif // ZIGBEE_STOCHASTIC_ADDRESSING
  1648. // Fill in the extended address in address manager if we don't have it already.
  1649. addrEntry.user = ADDRMGR_USER_DEFAULT;
  1650. addrEntry.nwkAddr = Annce.nwkAddr;
  1651. if ( AddrMgrEntryLookupNwk( &addrEntry ) )
  1652. {
  1653. osal_memset( parentExt, 0, Z_EXTADDR_LEN );
  1654. if ( osal_ExtAddrEqual( parentExt, addrEntry.extAddr ) )
  1655. {
  1656. AddrMgrExtAddrSet( addrEntry.extAddr, Annce.extAddr );
  1657. AddrMgrEntryUpdate( &addrEntry );
  1658. }
  1659. }
  1660. }
  1661. /*********************************************************************
  1662. * @fn ZDO_BuildSimpleDescBuf
  1663. *
  1664. * @brief Build a byte sequence representation of a Simple Descriptor.
  1665. *
  1666. * @param buf - pointer to a byte array big enough for data.
  1667. * @param desc - SimpleDescriptionFormat_t *
  1668. *
  1669. * @return none
  1670. */
  1671. void ZDO_BuildSimpleDescBuf( uint8 *buf, SimpleDescriptionFormat_t *desc )
  1672. {
  1673. byte cnt;
  1674. uint16 *ptr;
  1675. *buf++ = desc->EndPoint;
  1676. *buf++ = HI_UINT16( desc->AppProfId );
  1677. *buf++ = LO_UINT16( desc->AppProfId );
  1678. *buf++ = HI_UINT16( desc->AppDeviceId );
  1679. *buf++ = LO_UINT16( desc->AppDeviceId );
  1680. *buf++ = (byte)(desc->AppDevVer << 4);
  1681. *buf++ = desc->AppNumInClusters;
  1682. ptr = desc->pAppInClusterList;
  1683. for ( cnt = 0; cnt < desc->AppNumInClusters; ptr++, cnt++ )
  1684. {
  1685. *buf++ = HI_UINT16( *ptr );
  1686. *buf++ = LO_UINT16( *ptr );
  1687. }
  1688. *buf++ = desc->AppNumOutClusters;
  1689. ptr = desc->pAppOutClusterList;
  1690. for ( cnt = 0; cnt < desc->AppNumOutClusters; ptr++, cnt++ )
  1691. {
  1692. *buf++ = HI_UINT16( *ptr );
  1693. *buf++ = LO_UINT16( *ptr );
  1694. }
  1695. }
  1696. /*********************************************************************
  1697. * @fn ZDO_MatchEndDeviceBind()
  1698. *
  1699. * @brief
  1700. *
  1701. * Called to match end device binding requests
  1702. *
  1703. * @param bindReq - binding request information
  1704. * @param SecurityUse - Security enable/disable
  1705. *
  1706. * @return none
  1707. */
  1708. void ZDO_MatchEndDeviceBind( ZDEndDeviceBind_t *bindReq )
  1709. {
  1710. zAddrType_t dstAddr;
  1711. uint8 sendRsp = FALSE;
  1712. uint8 status;
  1713. // Is this the first request?
  1714. if ( matchED == NULL )
  1715. {
  1716. // Create match info structure
  1717. matchED = (ZDMatchEndDeviceBind_t *)osal_mem_alloc( sizeof ( ZDMatchEndDeviceBind_t ) );
  1718. if ( matchED )
  1719. {
  1720. // Clear the structure
  1721. osal_memset( (uint8 *)matchED, 0, sizeof ( ZDMatchEndDeviceBind_t ) );
  1722. // Copy the first request's information
  1723. if ( !ZDO_CopyMatchInfo( &(matchED->ed1), bindReq ) )
  1724. {
  1725. status = ZDP_NO_ENTRY;
  1726. sendRsp = TRUE;
  1727. }
  1728. }
  1729. else
  1730. {
  1731. status = ZDP_NO_ENTRY;
  1732. sendRsp = TRUE;
  1733. }
  1734. if ( !sendRsp )
  1735. {
  1736. // Set into the correct state
  1737. matchED->state = ZDMATCH_WAIT_REQ;
  1738. // Setup the timeout
  1739. APS_SetEndDeviceBindTimeout( AIB_MaxBindingTime, ZDO_EndDeviceBindMatchTimeoutCB );
  1740. }
  1741. }
  1742. else
  1743. {
  1744. matchED->state = ZDMATCH_SENDING_BINDS;
  1745. // Copy the 2nd request's information
  1746. if ( !ZDO_CopyMatchInfo( &(matchED->ed2), bindReq ) )
  1747. {
  1748. status = ZDP_NO_ENTRY;
  1749. sendRsp = TRUE;
  1750. }
  1751. // Make a source match for ed1
  1752. matchED->ed1numMatched = ZDO_CompareClusterLists(
  1753. matchED->ed1.numOutClusters, matchED->ed1.outClusters,
  1754. matchED->ed2.numInClusters, matchED->ed2.inClusters, ZDOBuildBuf );
  1755. if ( matchED->ed1numMatched )
  1756. {
  1757. // Save the match list
  1758. matchED->ed1Matched = osal_mem_alloc( (short)(matchED->ed1numMatched * sizeof ( uint16 )) );
  1759. if ( matchED->ed1Matched )
  1760. {
  1761. osal_memcpy( matchED->ed1Matched, ZDOBuildBuf, (matchED->ed1numMatched * sizeof ( uint16 )) );
  1762. }
  1763. else
  1764. {
  1765. // Allocation error, stop
  1766. status = ZDP_NO_ENTRY;
  1767. sendRsp = TRUE;
  1768. }
  1769. }
  1770. // Make a source match for ed2
  1771. matchED->ed2numMatched = ZDO_CompareClusterLists(
  1772. matchED->ed2.numOutClusters, matchED->ed2.outClusters,
  1773. matchED->ed1.numInClusters, matchED->ed1.inClusters, ZDOBuildBuf );
  1774. if ( matchED->ed2numMatched )
  1775. {
  1776. // Save the match list
  1777. matchED->ed2Matched = osal_mem_alloc( (short)(matchED->ed2numMatched * sizeof ( uint16 )) );
  1778. if ( matchED->ed2Matched )
  1779. {
  1780. osal_memcpy( matchED->ed2Matched, ZDOBuildBuf, (matchED->ed2numMatched * sizeof ( uint16 )) );
  1781. }
  1782. else
  1783. {
  1784. // Allocation error, stop
  1785. status = ZDP_NO_ENTRY;
  1786. sendRsp = TRUE;
  1787. }
  1788. }
  1789. if ( (sendRsp == FALSE) && (matchED->ed1numMatched || matchED->ed2numMatched) )
  1790. {
  1791. // Do the first unbind/bind state
  1792. ZDMatchSendState( ZDMATCH_REASON_START, ZDP_SUCCESS, 0 );
  1793. }
  1794. else
  1795. {
  1796. status = ZDP_NO_MATCH;
  1797. sendRsp = TRUE;
  1798. }
  1799. }
  1800. if ( sendRsp )
  1801. {
  1802. // send response to this requester
  1803. dstAddr.addrMode = Addr16Bit;
  1804. dstAddr.addr.shortAddr = bindReq->srcAddr;
  1805. ZDP_EndDeviceBindRsp( bindReq->TransSeq, &dstAddr, status, bindReq->SecurityUse );
  1806. if ( matchED->state == ZDMATCH_SENDING_BINDS )
  1807. {
  1808. // send response to first requester
  1809. dstAddr.addrMode = Addr16Bit;
  1810. dstAddr.addr.shortAddr = matchED->ed1.srcAddr;
  1811. ZDP_EndDeviceBindRsp( matchED->ed1.TransSeq, &dstAddr, status, matchED->ed1.SecurityUse );
  1812. }
  1813. // Process ended - release memory used
  1814. ZDO_RemoveMatchMemory();
  1815. }
  1816. }
  1817. /*********************************************************************
  1818. * @fn ZDO_RemoveMatchMemory()
  1819. *
  1820. * @brief Called to clear the memory used for the end device bind.
  1821. *
  1822. * @param none
  1823. *
  1824. * @return none
  1825. */
  1826. static void ZDO_RemoveMatchMemory( void )
  1827. {
  1828. if ( matchED != NULL )
  1829. {
  1830. if ( matchED->ed2Matched != NULL )
  1831. osal_mem_free( matchED->ed2Matched );
  1832. if ( matchED->ed1Matched != NULL )
  1833. osal_mem_free( matchED->ed1Matched );
  1834. if ( matchED->ed1.inClusters != NULL )
  1835. osal_mem_free( matchED->ed1.inClusters );
  1836. if ( matchED->ed1.outClusters != NULL )
  1837. osal_mem_free( matchED->ed1.outClusters );
  1838. if ( matchED->ed2.inClusters != NULL )
  1839. osal_mem_free( matchED->ed2.inClusters );
  1840. if ( matchED->ed2.outClusters != NULL )
  1841. osal_mem_free( matchED->ed2.outClusters );
  1842. osal_mem_free( matchED );
  1843. matchED = (ZDMatchEndDeviceBind_t *)NULL;
  1844. }
  1845. }
  1846. /*********************************************************************
  1847. * @fn ZDO_CopyMatchInfo()
  1848. *
  1849. * @brief Called to copy memory used for the end device bind.
  1850. *
  1851. * @param srcReq - source information
  1852. * @param dstReq - destination location
  1853. *
  1854. * @return TRUE if copy was successful.
  1855. */
  1856. static uint8 ZDO_CopyMatchInfo( ZDEndDeviceBind_t *destReq, ZDEndDeviceBind_t *srcReq )
  1857. {
  1858. uint8 allOK = TRUE;
  1859. // Copy bind information into the match info structure
  1860. osal_memcpy( (uint8 *)destReq, srcReq, sizeof ( ZDEndDeviceBind_t ) );
  1861. // Initialize the destination cluster pointers
  1862. destReq->inClusters = NULL;
  1863. destReq->outClusters = NULL;
  1864. // Copy input cluster IDs
  1865. if ( srcReq->numInClusters )
  1866. {
  1867. destReq->inClusters = osal_mem_alloc( (short)(srcReq->numInClusters * sizeof ( uint16 )) );
  1868. if ( destReq->inClusters )
  1869. {
  1870. // Copy the clusters
  1871. osal_memcpy( (uint8*)(destReq->inClusters), (uint8 *)(srcReq->inClusters),
  1872. (srcReq->numInClusters * sizeof ( uint16 )) );
  1873. }
  1874. else
  1875. allOK = FALSE;
  1876. }
  1877. // Copy output cluster IDs
  1878. if ( srcReq->numOutClusters )
  1879. {
  1880. destReq->outClusters = osal_mem_alloc( (short)(srcReq->numOutClusters * sizeof ( uint16 )) );
  1881. if ( destReq->outClusters )
  1882. {
  1883. // Copy the clusters
  1884. osal_memcpy( (uint8 *)(destReq->outClusters), (uint8 *)(srcReq->outClusters),
  1885. (srcReq->numOutClusters * sizeof ( uint16 )) );
  1886. }
  1887. else
  1888. allOK = FALSE;
  1889. }
  1890. if ( !allOK )
  1891. {
  1892. if ( destReq->inClusters != NULL )
  1893. osal_mem_free( destReq->inClusters );
  1894. if ( destReq->outClusters != NULL )
  1895. osal_mem_free( destReq->outClusters );
  1896. }
  1897. return ( allOK );
  1898. }
  1899. /*********************************************************************
  1900. * @fn ZDMatchSendState()
  1901. *
  1902. * @brief State machine for the End device match message algorithm.
  1903. *
  1904. * @param reason - state of algoritm
  1905. * @param status - initial message status
  1906. * @param TransSeq - next transaction sequence number
  1907. *
  1908. * @return FALSE if error and we are not currently matching, TRUE
  1909. * if success.
  1910. */
  1911. uint8 ZDMatchSendState( uint8 reason, uint8 status, uint8 TransSeq )
  1912. {
  1913. uint8 *dstIEEEAddr;
  1914. uint8 dstEP;
  1915. zAddrType_t dstAddr;
  1916. zAddrType_t destinationAddr;
  1917. uint16 msgType;
  1918. uint16 clusterID;
  1919. ZDEndDeviceBind_t *ed = NULL;
  1920. uint8 rspStatus = ZDP_SUCCESS;
  1921. if ( matchED == NULL )
  1922. return ( FALSE );
  1923. // Check sequence number
  1924. if ( reason == ZDMATCH_REASON_BIND_RSP || reason == ZDMATCH_REASON_UNBIND_RSP )
  1925. {
  1926. if ( TransSeq != matchED->transSeq )
  1927. return( FALSE ); // ignore the message
  1928. }
  1929. // turn off timer
  1930. APS_SetEndDeviceBindTimeout( 0, ZDO_EndDeviceBindMatchTimeoutCB );
  1931. if ( reason == ZDMATCH_REASON_TIMEOUT )
  1932. {
  1933. rspStatus = ZDP_TIMEOUT; // The process will stop
  1934. }
  1935. if ( reason == ZDMATCH_REASON_START || reason == ZDMATCH_REASON_BIND_RSP )
  1936. {
  1937. matchED->sending = ZDMATCH_SENDING_UNBIND;
  1938. if ( reason == ZDMATCH_REASON_BIND_RSP && status != ZDP_SUCCESS )
  1939. {
  1940. rspStatus = status;
  1941. }
  1942. }
  1943. else if ( reason == ZDMATCH_REASON_UNBIND_RSP )
  1944. {
  1945. if ( status == ZDP_SUCCESS )
  1946. {
  1947. matchED->sending = ZDMATCH_SENDING_UNBIND;
  1948. }
  1949. else
  1950. {
  1951. matchED->sending = ZDMATCH_SENDING_BIND;
  1952. }
  1953. }
  1954. if ( reason != ZDMATCH_REASON_START && matchED->sending == ZDMATCH_SENDING_UNBIND )
  1955. {
  1956. // Move to the next cluster ID
  1957. if ( matchED->ed1numMatched )
  1958. matchED->ed1numMatched--;
  1959. else if ( matchED->ed2numMatched )
  1960. matchED->ed2numMatched--;
  1961. }
  1962. // What message do we send now
  1963. if ( matchED->ed1numMatched )
  1964. {
  1965. ed = &(matchED->ed1);
  1966. clusterID = matchED->ed1Matched[matchED->ed1numMatched-1];
  1967. dstIEEEAddr = matchED->ed2.ieeeAddr;
  1968. dstEP = matchED->ed2.endpoint;
  1969. }
  1970. else if ( matchED->ed2numMatched )
  1971. {
  1972. ed = &(matchED->ed2);
  1973. clusterID = matchED->ed2Matched[matchED->ed2numMatched-1];
  1974. dstIEEEAddr = matchED->ed1.ieeeAddr;
  1975. dstEP = matchED->ed1.endpoint;
  1976. }
  1977. dstAddr.addrMode = Addr16Bit;
  1978. // Send the next message
  1979. if ( rspStatus == ZDP_SUCCESS && ed )
  1980. {
  1981. // Send unbind/bind message to source
  1982. if ( matchED->sending == ZDMATCH_SENDING_UNBIND )
  1983. msgType = Unbind_req;
  1984. else
  1985. msgType = Bind_req;
  1986. dstAddr.addr.shortAddr = ed->srcAddr;
  1987. // Save off the transaction sequence number
  1988. matchED->transSeq = ZDP_TransID;
  1989. destinationAddr.addrMode = Addr64Bit;
  1990. osal_cpyExtAddr( destinationAddr.addr.extAddr, dstIEEEAddr );
  1991. ZDP_BindUnbindReq( msgType, &dstAddr, ed->ieeeAddr, ed->endpoint, clusterID,
  1992. &destinationAddr, dstEP, ed->SecurityUse );
  1993. // Set timeout for response
  1994. APS_SetEndDeviceBindTimeout( AIB_MaxBindingTime, ZDO_EndDeviceBindMatchTimeoutCB );
  1995. }
  1996. else
  1997. {
  1998. // Send the response messages to requesting devices
  1999. // send response to first requester
  2000. dstAddr.addr.shortAddr = matchED->ed1.srcAddr;
  2001. ZDP_EndDeviceBindRsp( matchED->ed1.TransSeq, &dstAddr, rspStatus, matchED->ed1.SecurityUse );
  2002. // send response to second requester
  2003. if ( matchED->state == ZDMATCH_SENDING_BINDS )
  2004. {
  2005. dstAddr.addr.shortAddr = matchED->ed2.srcAddr;
  2006. ZDP_EndDeviceBindRsp( matchED->ed2.TransSeq, &dstAddr, rspStatus, matchED->ed2.SecurityUse );
  2007. }
  2008. // Process ended - release memory used
  2009. ZDO_RemoveMatchMemory();
  2010. }
  2011. return ( TRUE );
  2012. }
  2013. /*********************************************************************
  2014. * @fn ZDO_EndDeviceBindMatchTimeoutCB()
  2015. *
  2016. * @brief End device bind timeout.
  2017. *
  2018. * @param none
  2019. *
  2020. * @return none
  2021. */
  2022. static void ZDO_EndDeviceBindMatchTimeoutCB( void )
  2023. {
  2024. ZDMatchSendState( ZDMATCH_REASON_TIMEOUT, ZDP_TIMEOUT, 0 );
  2025. }
  2026. /*********************************************************************
  2027. * ZDO MESSAGE PARSING API FUNCTIONS
  2028. */
  2029. /*********************************************************************
  2030. * @fn ZDO_ParseEndDeviceBindReq
  2031. *
  2032. * @brief This function parses the End_Device_Bind_req message.
  2033. *
  2034. * NOTE: The clusters lists in bindReq are allocated in this
  2035. * function and must be freed by that calling function.
  2036. *
  2037. * @param inMsg - incoming message (request)
  2038. * @param bindReq - pointer to place to parse message to
  2039. *
  2040. * @return none
  2041. */
  2042. void ZDO_ParseEndDeviceBindReq( zdoIncomingMsg_t *inMsg, ZDEndDeviceBind_t *bindReq )
  2043. {
  2044. uint8 *msg;
  2045. // Parse the message
  2046. bindReq->TransSeq = inMsg->TransSeq;
  2047. bindReq->srcAddr = inMsg->srcAddr.addr.shortAddr;
  2048. bindReq->SecurityUse = inMsg->SecurityUse;
  2049. msg = inMsg->asdu;
  2050. bindReq->localCoordinator = BUILD_UINT16( msg[0], msg[1] );
  2051. msg += 2;
  2052. osal_cpyExtAddr( bindReq->ieeeAddr, msg );
  2053. msg += Z_EXTADDR_LEN;
  2054. bindReq->endpoint = *msg++;
  2055. bindReq->profileID = BUILD_UINT16( msg[0], msg[1] );
  2056. msg += 2;
  2057. bindReq->inClusters = NULL;
  2058. bindReq->outClusters = NULL;
  2059. if ((bindReq->numInClusters = *msg++) &&
  2060. (bindReq->inClusters = (uint16*)osal_mem_alloc( (bindReq->numInClusters * sizeof( uint16 )))))
  2061. {
  2062. msg = ZDO_ConvertOTAClusters( bindReq->numInClusters, msg, bindReq->inClusters );
  2063. }
  2064. else
  2065. {
  2066. bindReq->numInClusters = 0;
  2067. }
  2068. if ((bindReq->numOutClusters = *msg++) &&
  2069. (bindReq->outClusters = (uint16*)osal_mem_alloc((bindReq->numOutClusters * sizeof(uint16)))))
  2070. {
  2071. msg = ZDO_ConvertOTAClusters( bindReq->numOutClusters, msg, bindReq->outClusters );
  2072. }
  2073. else
  2074. {
  2075. bindReq->numOutClusters = 0;
  2076. }
  2077. }
  2078. /*********************************************************************
  2079. * @fn ZDO_ParseBindUnbindReq
  2080. *
  2081. * @brief This function parses the Bind_req or Unbind_req message.
  2082. *
  2083. * @param inMsg - incoming message (request)
  2084. * @param pReq - place to put parsed information
  2085. *
  2086. * @return none
  2087. */
  2088. void ZDO_ParseBindUnbindReq( zdoIncomingMsg_t *inMsg, ZDO_BindUnbindReq_t *pReq )
  2089. {
  2090. uint8 *msg;
  2091. msg = inMsg->asdu;
  2092. osal_cpyExtAddr( pReq->srcAddress, msg );
  2093. msg += Z_EXTADDR_LEN;
  2094. pReq->srcEndpoint = *msg++;
  2095. pReq->clusterID = BUILD_UINT16( msg[0], msg[1] );
  2096. msg += 2;
  2097. pReq->dstAddress.addrMode = *msg++;
  2098. if ( pReq->dstAddress.addrMode == Addr64Bit )
  2099. {
  2100. osal_cpyExtAddr( pReq->dstAddress.addr.extAddr, msg );
  2101. msg += Z_EXTADDR_LEN;
  2102. pReq->dstEndpoint = *msg;
  2103. }
  2104. else
  2105. {
  2106. // copy group address
  2107. pReq->dstAddress.addr.shortAddr = BUILD_UINT16( msg[0], msg[1] );
  2108. }
  2109. }
  2110. /*********************************************************************
  2111. * @fn ZDO_ParseAddrRsp
  2112. *
  2113. * @brief Turns the inMsg (incoming message) into the out parsed
  2114. * structure.
  2115. *
  2116. * @param inMsg - incoming message
  2117. *
  2118. * @return pointer to parsed structures. This structure was
  2119. * allocated using osal_mem_alloc, so it must be freed
  2120. * by the calling function [osal_mem_free()].
  2121. */
  2122. ZDO_NwkIEEEAddrResp_t *ZDO_ParseAddrRsp( zdoIncomingMsg_t *inMsg )
  2123. {
  2124. ZDO_NwkIEEEAddrResp_t *rsp;
  2125. uint8 *msg;
  2126. byte cnt = 0;
  2127. // Calculate the number of items in the list
  2128. if ( inMsg->asduLen > (1 + Z_EXTADDR_LEN + 2) )
  2129. cnt = inMsg->asdu[1 + Z_EXTADDR_LEN + 2];
  2130. else
  2131. cnt = 0;
  2132. // Make buffer
  2133. rsp = (ZDO_NwkIEEEAddrResp_t *)osal_mem_alloc( sizeof(ZDO_NwkIEEEAddrResp_t) + (cnt * sizeof ( uint16 )) );
  2134. if ( rsp )
  2135. {
  2136. msg = inMsg->asdu;
  2137. rsp->status = *msg++;
  2138. if ( rsp->status == ZDO_SUCCESS )
  2139. {
  2140. osal_cpyExtAddr( rsp->extAddr, msg );
  2141. msg += Z_EXTADDR_LEN;
  2142. rsp->nwkAddr = BUILD_UINT16( msg[0], msg[1] );
  2143. msg += 2;
  2144. rsp->numAssocDevs = 0;
  2145. // StartIndex field is only present if NumAssocDev field is non-zero.
  2146. if ( cnt > 0 )
  2147. {
  2148. uint16 *pList = &(rsp->devList[0]);
  2149. byte n = cnt;
  2150. rsp->numAssocDevs = *msg++;
  2151. rsp->startIndex = *msg++;
  2152. while ( n != 0 )
  2153. {
  2154. *pList++ = BUILD_UINT16( msg[0], msg[1] );
  2155. msg += sizeof( uint16 );
  2156. n--;
  2157. }
  2158. }
  2159. }
  2160. }
  2161. return ( rsp );
  2162. }
  2163. /*********************************************************************
  2164. * @fn ZDO_ParseNodeDescRsp
  2165. *
  2166. * @brief This function parses the Node_Desc_rsp message.
  2167. *
  2168. * @param inMsg - incoming message
  2169. * @param pNDRsp - place to parse the message into
  2170. *
  2171. * @return none
  2172. */
  2173. void ZDO_ParseNodeDescRsp( zdoIncomingMsg_t *inMsg, ZDO_NodeDescRsp_t *pNDRsp )
  2174. {
  2175. uint8 *msg;
  2176. msg = inMsg->asdu;
  2177. pNDRsp->status = *msg++;
  2178. pNDRsp->nwkAddr = BUILD_UINT16( msg[0], msg[1] );
  2179. if ( pNDRsp->status == ZDP_SUCCESS )
  2180. {
  2181. msg += 2;
  2182. pNDRsp->nodeDesc.LogicalType = *msg & 0x07;
  2183. pNDRsp->nodeDesc.ComplexDescAvail = ( *msg & 0x08 ) >> 3;
  2184. pNDRsp->nodeDesc.UserDescAvail = ( *msg & 0x10 ) >> 4;
  2185. msg++; // Reserved bits.
  2186. pNDRsp->nodeDesc.FrequencyBand = (*msg >> 3) & 0x1f;
  2187. pNDRsp->nodeDesc.APSFlags = *msg++ & 0x07;
  2188. pNDRsp->nodeDesc.CapabilityFlags = *msg++;
  2189. pNDRsp->nodeDesc.ManufacturerCode[0] = *msg++;
  2190. pNDRsp->nodeDesc.ManufacturerCode[1] = *msg++;
  2191. pNDRsp->nodeDesc.MaxBufferSize = *msg++;
  2192. pNDRsp->nodeDesc.MaxInTransferSize[0] = *msg++;
  2193. pNDRsp->nodeDesc.MaxInTransferSize[1] = *msg++;
  2194. pNDRsp->nodeDesc.ServerMask = BUILD_UINT16( msg[0], msg[1] );
  2195. msg += 2;
  2196. pNDRsp->nodeDesc.MaxOutTransferSize[0] = *msg++;
  2197. pNDRsp->nodeDesc.MaxOutTransferSize[1] = *msg++;
  2198. pNDRsp->nodeDesc.DescriptorCapability = *msg;
  2199. }
  2200. }
  2201. /*********************************************************************
  2202. * @fn ZDO_ParesPowerDescRsp
  2203. *
  2204. * @brief This function parses the Power_Desc_rsp message.
  2205. *
  2206. * @param inMsg - incoming message
  2207. * @param pNPRsp - place to parse the message into
  2208. *
  2209. * @return none
  2210. */
  2211. void ZDO_ParsePowerDescRsp( zdoIncomingMsg_t *inMsg, ZDO_PowerRsp_t *pNPRsp )
  2212. {
  2213. uint8 *msg;
  2214. msg = inMsg->asdu;
  2215. pNPRsp->status = *msg++;
  2216. pNPRsp->nwkAddr = BUILD_UINT16( msg[0], msg[1] );
  2217. if ( pNPRsp->status == ZDP_SUCCESS )
  2218. {
  2219. msg += 2;
  2220. pNPRsp->pwrDesc.AvailablePowerSources = *msg >> 4;
  2221. pNPRsp->pwrDesc.PowerMode = *msg++ & 0x0F;
  2222. pNPRsp->pwrDesc.CurrentPowerSourceLevel = *msg >> 4;
  2223. pNPRsp->pwrDesc.CurrentPowerSource = *msg++ & 0x0F;
  2224. }
  2225. }
  2226. /*********************************************************************
  2227. * @fn ZDO_ParseSimpleDescRsp
  2228. *
  2229. * @brief This function parse the Simple_Desc_rsp message.
  2230. *
  2231. * NOTE: The pAppInClusterList and pAppOutClusterList fields
  2232. * in the SimpleDescriptionFormat_t structure are allocated
  2233. * and the calling function needs to free [osal_msg_free()]
  2234. * these buffers.
  2235. *
  2236. * @param inMsg - incoming message
  2237. * @param pSimpleDescRsp - place to parse the message into
  2238. *
  2239. * @return none
  2240. */
  2241. void ZDO_ParseSimpleDescRsp( zdoIncomingMsg_t *inMsg, ZDO_SimpleDescRsp_t *pSimpleDescRsp )
  2242. {
  2243. uint8 *msg;
  2244. msg = inMsg->asdu;
  2245. pSimpleDescRsp->status = *msg++;
  2246. pSimpleDescRsp->nwkAddr = BUILD_UINT16( msg[0], msg[1] );
  2247. msg += sizeof ( uint16 );
  2248. msg++; // Skip past the length field.
  2249. if ( pSimpleDescRsp->status == ZDP_SUCCESS )
  2250. {
  2251. ZDO_ParseSimpleDescBuf( msg, &(pSimpleDescRsp->simpleDesc) );
  2252. }
  2253. }
  2254. /*********************************************************************
  2255. * @fn ZDO_ParseEPListRsp
  2256. *
  2257. * @brief This parse the Active_EP_rsp or Match_Desc_rsp message.
  2258. *
  2259. * @param inMsg - incoming message
  2260. *
  2261. * @return none
  2262. */
  2263. ZDO_ActiveEndpointRsp_t *ZDO_ParseEPListRsp( zdoIncomingMsg_t *inMsg )
  2264. {
  2265. ZDO_ActiveEndpointRsp_t *pRsp;
  2266. uint8 *msg;
  2267. uint8 Status;
  2268. uint8 cnt;
  2269. msg = inMsg->asdu;
  2270. Status = *msg++;
  2271. cnt = msg[2];
  2272. pRsp = (ZDO_ActiveEndpointRsp_t *)osal_mem_alloc( sizeof( ZDO_ActiveEndpointRsp_t ) + cnt );
  2273. if ( pRsp )
  2274. {
  2275. pRsp->status = Status;
  2276. pRsp->nwkAddr = BUILD_UINT16( msg[0], msg[1] );
  2277. msg += sizeof( uint16 );
  2278. pRsp->cnt = cnt;
  2279. msg++; // pass cnt
  2280. osal_memcpy( pRsp->epList, msg, cnt );
  2281. }
  2282. return ( pRsp );
  2283. }
  2284. /*********************************************************************
  2285. * @fn ZDO_ParseServerDiscRsp
  2286. *
  2287. * @brief Parse the Server_Discovery_rsp message.
  2288. *
  2289. * @param inMsg - incoming message.
  2290. * @param pRsp - place to put the parsed information.
  2291. *
  2292. * @return none
  2293. */
  2294. void ZDO_ParseServerDiscRsp( zdoIncomingMsg_t *inMsg, ZDO_ServerDiscRsp_t *pRsp )
  2295. {
  2296. pRsp->status = inMsg->asdu[0];
  2297. pRsp->serverMask = BUILD_UINT16( inMsg->asdu[1], inMsg->asdu[2] );
  2298. }
  2299. /*********************************************************************
  2300. * @fn ZDO_ParseMgmtLqiRsp
  2301. *
  2302. * @brief This function parses the incoming Management
  2303. * LQI response
  2304. *
  2305. * @param inMsg - incoming message
  2306. *
  2307. * @return a pointer to parsed response structure (NULL if not allocated).
  2308. * This structure was allocated using osal_mem_alloc, so it must be freed
  2309. * by the calling function [osal_mem_free()].
  2310. */
  2311. ZDO_MgmtLqiRsp_t *ZDO_ParseMgmtLqiRsp( zdoIncomingMsg_t *inMsg )
  2312. {
  2313. ZDO_MgmtLqiRsp_t *pRsp;
  2314. uint8 status;
  2315. uint8 startIndex = 0;
  2316. uint8 neighborLqiCount = 0;
  2317. uint8 neighborLqiEntries = 0;
  2318. uint8 *msg;
  2319. msg = inMsg->asdu;
  2320. status = *msg++;
  2321. if ( status == ZSuccess )
  2322. {
  2323. neighborLqiEntries = *msg++;
  2324. startIndex = *msg++;
  2325. neighborLqiCount = *msg++;
  2326. }
  2327. // Allocate a buffer big enough to handle the list.
  2328. pRsp = (ZDO_MgmtLqiRsp_t *)osal_mem_alloc(
  2329. sizeof( ZDO_MgmtLqiRsp_t ) + (neighborLqiCount * sizeof( neighborLqiItem_t )) );
  2330. if ( pRsp )
  2331. {
  2332. uint8 x;
  2333. neighborLqiItem_t *pList = pRsp->list;
  2334. pRsp->status = status;
  2335. pRsp->neighborLqiEntries = neighborLqiEntries;
  2336. pRsp->startIndex = startIndex;
  2337. pRsp->neighborLqiCount = neighborLqiCount;
  2338. for ( x = 0; x < neighborLqiCount; x++ )
  2339. {
  2340. osal_cpyExtAddr(pList->extPANId, msg); //Copy extended PAN ID
  2341. msg += Z_EXTADDR_LEN;
  2342. msg += Z_EXTADDR_LEN; // Throwing away IEEE.
  2343. pList->nwkAddr = BUILD_UINT16( msg[0], msg[1] );
  2344. msg += 2 + 1 + 1 + 1; // Skip DeviceType, RxOnIdle, Rlationship, PermitJoining and Depth
  2345. pList->rxLqi = *msg++;
  2346. pList->txQuality = 0; // This is not specified OTA by ZigBee 1.1.
  2347. pList++;
  2348. }
  2349. }
  2350. return ( pRsp );
  2351. }
  2352. /*********************************************************************
  2353. * @fn ZDO_ParseMgmNwkDiscRsp
  2354. *
  2355. * @brief This function parses the incoming Management
  2356. * Network Discover response.
  2357. *
  2358. * @param inMsg - incoming message
  2359. *
  2360. * @return pointer to parsed response. This structure was
  2361. * allocated using osal_mem_alloc, so it must be freed
  2362. * by the calling function [osal_mem_free()].
  2363. */
  2364. ZDO_MgmNwkDiscRsp_t *ZDO_ParseMgmNwkDiscRsp( zdoIncomingMsg_t *inMsg )
  2365. {
  2366. ZDO_MgmNwkDiscRsp_t *pRsp;
  2367. uint8 status;
  2368. uint8 networkCount = 0;
  2369. uint8 startIndex = 0;
  2370. uint8 networkListCount = 0;
  2371. uint8 *msg;
  2372. msg = inMsg->asdu;
  2373. status = *msg++;
  2374. if ( status == ZSuccess )
  2375. {
  2376. networkCount = *msg++;
  2377. startIndex = *msg++;
  2378. networkListCount = *msg++;
  2379. }
  2380. // Allocate a buffer big enough to handle the list.
  2381. pRsp = (ZDO_MgmNwkDiscRsp_t *)osal_mem_alloc( sizeof( ZDO_MgmNwkDiscRsp_t )
  2382. + (networkListCount * sizeof( mgmtNwkDiscItem_t )) );
  2383. if ( pRsp )
  2384. {
  2385. uint8 x;
  2386. mgmtNwkDiscItem_t *pList;
  2387. pRsp->status = status;
  2388. pRsp->networkCount = networkCount;
  2389. pRsp->startIndex = startIndex;
  2390. pRsp->networkListCount = networkListCount;
  2391. pList = pRsp->list;
  2392. for ( x = 0; x < networkListCount; x++ )
  2393. {
  2394. osal_cpyExtAddr(pList->extendedPANID, msg); //Copy extended PAN ID
  2395. pList->PANId = BUILD_UINT16( msg[0], msg[1] );
  2396. msg += Z_EXTADDR_LEN;
  2397. pList->logicalChannel = *msg++;
  2398. pList->stackProfile = (*msg) & 0x0F;
  2399. pList->version = (*msg++ >> 4) & 0x0F;
  2400. pList->beaconOrder = (*msg) & 0x0F;
  2401. pList->superFrameOrder = (*msg++ >> 4) & 0x0F;
  2402. pList->permitJoining = *msg++;
  2403. pList++;
  2404. }
  2405. }
  2406. return ( pRsp );
  2407. }
  2408. /*********************************************************************
  2409. * @fn ZDO_ParseMgmtRtgRsp
  2410. *
  2411. * @brief This function parses the incoming Management
  2412. * Routing response.
  2413. *
  2414. * @param inMsg - incoming message
  2415. *
  2416. * @return a pointer to parsed response structure (NULL if not allocated).
  2417. * This structure was allocated using osal_mem_alloc, so it must be freed
  2418. * by the calling function [osal_mem_free()].
  2419. */
  2420. ZDO_MgmtRtgRsp_t *ZDO_ParseMgmtRtgRsp( zdoIncomingMsg_t *inMsg )
  2421. {
  2422. ZDO_MgmtRtgRsp_t *pRsp;
  2423. uint8 status;
  2424. uint8 rtgCount = 0;
  2425. uint8 startIndex = 0;
  2426. uint8 rtgListCount = 0;
  2427. uint8 *msg;
  2428. msg = inMsg->asdu;
  2429. status = *msg++;
  2430. if ( status == ZSuccess )
  2431. {
  2432. rtgCount = *msg++;
  2433. startIndex = *msg++;
  2434. rtgListCount = *msg++;
  2435. }
  2436. // Allocate a buffer big enough to handle the list
  2437. pRsp = (ZDO_MgmtRtgRsp_t *)osal_mem_alloc(
  2438. sizeof( ZDO_MgmtRtgRsp_t ) + (rtgListCount * sizeof( rtgItem_t )) );
  2439. if ( pRsp )
  2440. {
  2441. uint8 x;
  2442. rtgItem_t *pList = pRsp->list;
  2443. pRsp->status = status;
  2444. pRsp->rtgCount = rtgCount;
  2445. pRsp->startIndex = startIndex;
  2446. pRsp->rtgListCount = rtgListCount;
  2447. for ( x = 0; x < rtgListCount; x++ )
  2448. {
  2449. pList->dstAddress = BUILD_UINT16( msg[0], msg[1] );
  2450. msg += 2;
  2451. pList->status = *msg++;
  2452. pList->nextHopAddress = BUILD_UINT16( msg[0], msg[1] );
  2453. msg += 2;
  2454. pList++;
  2455. }
  2456. }
  2457. return ( pRsp );
  2458. }
  2459. /*********************************************************************
  2460. * @fn ZDO_ParseMgmtBindRsp
  2461. *
  2462. * @brief This function parses the incoming Management
  2463. * Binding response.
  2464. *
  2465. * @param inMsg - pointer to message to parse
  2466. *
  2467. * @return a pointer to parsed response structure (NULL if not allocated).
  2468. * This structure was allocated using osal_mem_alloc, so it must be freed
  2469. * by the calling function [osal_mem_free()].
  2470. */
  2471. ZDO_MgmtBindRsp_t *ZDO_ParseMgmtBindRsp( zdoIncomingMsg_t *inMsg )
  2472. {
  2473. ZDO_MgmtBindRsp_t *pRsp;
  2474. uint8 status;
  2475. uint8 bindingCount = 0;
  2476. uint8 startIndex = 0;
  2477. uint8 bindingListCount = 0;
  2478. uint8 *msg;
  2479. msg = inMsg->asdu;
  2480. status = *msg++;
  2481. if ( status == ZSuccess )
  2482. {
  2483. bindingCount = *msg++;
  2484. startIndex = *msg++;
  2485. bindingListCount = *msg++;
  2486. }
  2487. // Allocate a buffer big enough to handle the list
  2488. pRsp = (ZDO_MgmtBindRsp_t *)osal_mem_alloc(
  2489. (sizeof ( ZDO_MgmtBindRsp_t ) + (bindingListCount * sizeof( apsBindingItem_t ))) );
  2490. if ( pRsp )
  2491. {
  2492. uint8 x;
  2493. apsBindingItem_t *pList = pRsp->list;
  2494. pRsp->status = status;
  2495. pRsp->bindingCount = bindingCount;
  2496. pRsp->startIndex = startIndex;
  2497. pRsp->bindingListCount = bindingListCount;
  2498. for ( x = 0; x < bindingListCount; x++ )
  2499. {
  2500. osal_cpyExtAddr( pList->srcAddr, msg );
  2501. msg += Z_EXTADDR_LEN;
  2502. pList->srcEP = *msg++;
  2503. // Get the Cluster ID
  2504. pList->clusterID = BUILD_UINT16( msg[0], msg[1] );
  2505. msg += 2;
  2506. pList->dstAddr.addrMode = *msg++;
  2507. if ( pList->dstAddr.addrMode == Addr64Bit )
  2508. {
  2509. osal_cpyExtAddr( pList->dstAddr.addr.extAddr, msg );
  2510. msg += Z_EXTADDR_LEN;
  2511. pList->dstEP = *msg++;
  2512. }
  2513. else
  2514. {
  2515. pList->dstAddr.addr.shortAddr = BUILD_UINT16( msg[0], msg[1] );
  2516. msg += 2;
  2517. }
  2518. pList++;
  2519. }
  2520. }
  2521. return ( pRsp );
  2522. }
  2523. /*********************************************************************
  2524. * @fn ZDO_ParseUserDescRsp
  2525. *
  2526. * @brief This function parses the incoming User
  2527. * Descriptor Response.
  2528. *
  2529. * @param inMsg - incoming response message
  2530. *
  2531. * @return a pointer to parsed response structure (NULL if not allocated).
  2532. * This structure was allocated using osal_mem_alloc, so it must be freed
  2533. * by the calling function [osal_mem_free()].
  2534. */
  2535. ZDO_UserDescRsp_t *ZDO_ParseUserDescRsp( zdoIncomingMsg_t *inMsg )
  2536. {
  2537. ZDO_UserDescRsp_t *pRsp;
  2538. uint8 *msg;
  2539. uint8 descLen = 0;
  2540. msg = inMsg->asdu;
  2541. if ( msg[0] == ZSuccess )
  2542. descLen = msg[3];
  2543. pRsp = (ZDO_UserDescRsp_t *)osal_mem_alloc( sizeof ( ZDO_UserDescRsp_t ) + descLen );
  2544. if ( pRsp )
  2545. {
  2546. pRsp->status = msg[0];
  2547. pRsp->nwkAddr = BUILD_UINT16( msg[1], msg[2] );
  2548. pRsp->length = descLen;
  2549. if ( descLen )
  2550. osal_memcpy( pRsp->desc, &msg[4], descLen );
  2551. }
  2552. return ( pRsp );
  2553. }
  2554. /*********************************************************************
  2555. * @fn ZDO_ParseSimpleDescBuf
  2556. *
  2557. * @brief Parse a byte sequence representation of a Simple Descriptor.
  2558. *
  2559. * @param buf - pointer to a byte array representing a Simple Desc.
  2560. * @param desc - SimpleDescriptionFormat_t *
  2561. *
  2562. * This routine allocates storage for the cluster IDs because
  2563. * they are 16-bit and need to be aligned to be properly processed.
  2564. * This routine returns non-zero if an allocation fails.
  2565. *
  2566. * NOTE: This means that the caller or user of the input structure
  2567. * is responsible for freeing the memory
  2568. *
  2569. * @return 0: success
  2570. * 1: failure due to malloc failure.
  2571. */
  2572. uint8 ZDO_ParseSimpleDescBuf( uint8 *buf, SimpleDescriptionFormat_t *desc )
  2573. {
  2574. uint8 num, i;
  2575. desc->EndPoint = *buf++;
  2576. desc->AppProfId = BUILD_UINT16( buf[0], buf[1] );
  2577. buf += 2;
  2578. desc->AppDeviceId = BUILD_UINT16( buf[0], buf[1] );
  2579. buf += 2;
  2580. desc->AppDevVer = *buf >> 4;
  2581. desc->Reserved = 0;
  2582. buf++;
  2583. // move in input cluster list (if any). allocate aligned memory.
  2584. num = desc->AppNumInClusters = *buf++;
  2585. if ( num )
  2586. {
  2587. if (!(desc->pAppInClusterList = (uint16 *)osal_mem_alloc(num*sizeof(uint16))))
  2588. {
  2589. // malloc failed. we're done.
  2590. return 1;
  2591. }
  2592. for (i=0; i<num; ++i)
  2593. {
  2594. desc->pAppInClusterList[i] = BUILD_UINT16( buf[0], buf[1] );
  2595. buf += 2;
  2596. }
  2597. }
  2598. // move in output cluster list (if any). allocate aligned memory.
  2599. num = desc->AppNumOutClusters = *buf++;
  2600. if (num)
  2601. {
  2602. if (!(desc->pAppOutClusterList = (uint16 *)osal_mem_alloc(num*sizeof(uint16))))
  2603. {
  2604. // malloc failed. free input cluster list memory if there is any
  2605. if ( desc->pAppInClusterList != NULL )
  2606. {
  2607. osal_mem_free(desc->pAppInClusterList);
  2608. }
  2609. return 1;
  2610. }
  2611. for (i=0; i<num; ++i)
  2612. {
  2613. desc->pAppOutClusterList[i] = BUILD_UINT16( buf[0], buf[1] );
  2614. buf += 2;
  2615. }
  2616. }
  2617. return 0;
  2618. }
  2619. /*********************************************************************
  2620. * @fn ZDO_ParseDeviceAnnce
  2621. *
  2622. * @brief Parse a Device Announce message.
  2623. *
  2624. * @param inMsg - Incoming message
  2625. * @param pAnnce - place to put the parsed information
  2626. *
  2627. * @return none
  2628. */
  2629. void ZDO_ParseDeviceAnnce( zdoIncomingMsg_t *inMsg, ZDO_DeviceAnnce_t *pAnnce )
  2630. {
  2631. uint8 *msg;
  2632. // Parse incoming message
  2633. msg = inMsg->asdu;
  2634. pAnnce->nwkAddr = BUILD_UINT16( msg[0], msg[1] );
  2635. msg += 2;
  2636. osal_cpyExtAddr( pAnnce->extAddr, msg );
  2637. msg += Z_EXTADDR_LEN;
  2638. pAnnce->capabilities = *msg;
  2639. }
  2640. /*********************************************************************
  2641. * @fn ZDO_ParseMgmtNwkUpdateNotify
  2642. *
  2643. * @brief This function handles parsing of the incoming Management
  2644. * Network Update notify.
  2645. *
  2646. * @param inMsg - incoming message (request)
  2647. *
  2648. * @return a pointer to parsed response structure (NULL if not allocated).
  2649. * This structure was allocated using osal_mem_alloc, so it must be freed
  2650. * by the calling function [osal_mem_free()].
  2651. */
  2652. ZDO_MgmtNwkUpdateNotify_t *ZDO_ParseMgmtNwkUpdateNotify( zdoIncomingMsg_t *inMsg )
  2653. {
  2654. uint8 status;
  2655. uint32 scannedChannels = 0;
  2656. uint16 totalTransmissions = 0;
  2657. uint16 transmissionFailures = 0;
  2658. uint8 listCount = 0;
  2659. uint8 *msg = inMsg->asdu;
  2660. ZDO_MgmtNwkUpdateNotify_t *pRsp;
  2661. status = *msg++;
  2662. if ( status == ZSuccess )
  2663. {
  2664. scannedChannels = osal_build_uint32( msg, 4 );
  2665. msg += 4;
  2666. totalTransmissions = BUILD_UINT16( msg[0], msg[1] );
  2667. msg += 2;
  2668. transmissionFailures = BUILD_UINT16( msg[0], msg[1] );
  2669. msg += 2;
  2670. listCount = *msg++;
  2671. }
  2672. pRsp = (ZDO_MgmtNwkUpdateNotify_t *)osal_mem_alloc( sizeof ( ZDO_MgmtNwkUpdateNotify_t ) + listCount );
  2673. if ( pRsp )
  2674. {
  2675. pRsp->status = status;
  2676. pRsp->scannedChannels = scannedChannels;
  2677. pRsp->totalTransmissions = totalTransmissions;
  2678. pRsp->transmissionFailures = transmissionFailures;
  2679. pRsp->listCount = listCount;
  2680. // Allocate a buffer big enough to handle the list.
  2681. if ( listCount > 0 )
  2682. osal_memcpy( pRsp->energyValues, msg, listCount );
  2683. }
  2684. return ( pRsp );
  2685. }
  2686. /*********************************************************************
  2687. * @fn ZDO_ParseMgmtNwkUpdateReq
  2688. *
  2689. * @brief This function handles parsing the incoming Management
  2690. * Network Update request and starts the request (if needed).
  2691. *
  2692. * @param inMsg - incoming message (request)
  2693. * @param pReq - pointer to place to parse message to
  2694. *
  2695. * @return none
  2696. */
  2697. void ZDO_ParseMgmtNwkUpdateReq( zdoIncomingMsg_t *inMsg, ZDO_MgmtNwkUpdateReq_t *pReq )
  2698. {
  2699. uint8 *msg = inMsg->asdu;
  2700. pReq->channelMask = osal_build_uint32( msg, 4 );
  2701. msg += 4;
  2702. pReq->scanDuration = *msg++;
  2703. if ( pReq->scanDuration <= 0x05 )
  2704. {
  2705. // Request is to scan over channelMask
  2706. pReq->scanCount = *msg;
  2707. }
  2708. else if ( ( pReq->scanDuration == 0xFE ) || ( pReq->scanDuration == 0xFF ) )
  2709. {
  2710. // Request is to change Channel (0xFE) or apsChannelMask and NwkManagerAddr (0xFF)
  2711. pReq->nwkUpdateId = *msg++;
  2712. if ( pReq->scanDuration == 0xFF )
  2713. {
  2714. pReq->nwkManagerAddr = BUILD_UINT16( msg[0], msg[1] );
  2715. }
  2716. }
  2717. }
  2718. /*********************************************************************
  2719. *********************************************************************/