ZDObject.c 87 KB

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