BindingTable.c 27 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073
  1. /**************************************************************************************************
  2. Filename: BindingTable.c
  3. Revised: $Date: 2012-03-28 15:40:50 -0700 (Wed, 28 Mar 2012) $
  4. Revision: $Revision: 29930 $
  5. Description: Device binding table functions.
  6. Copyright 2004-2012 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 "nwk_globals.h"
  40. #include "AddrMgr.h"
  41. #include "BindingTable.h"
  42. /*********************************************************************
  43. * MACROS
  44. */
  45. /*********************************************************************
  46. * CONSTANTS
  47. */
  48. #define NV_BIND_EMPTY 0xFF
  49. #define NV_BIND_REC_SIZE (gBIND_REC_SIZE)
  50. #define NV_BIND_ITEM_SIZE (gBIND_REC_SIZE * gNWK_MAX_BINDING_ENTRIES)
  51. /*********************************************************************
  52. * TYPEDEFS
  53. */
  54. typedef struct
  55. {
  56. uint8 srcEP;
  57. uint16 srcIndex;
  58. uint16 dstIndex;
  59. uint8 dstEP;
  60. uint8 dstAddrMode;
  61. uint8 clusterIDs;
  62. uint16* clusterIDList;
  63. } bindFields_t;
  64. /*********************************************************************
  65. * GLOBAL VARIABLES
  66. */
  67. /*********************************************************************
  68. * LOCAL FUNCTIONS
  69. */
  70. void BindAddrMgrCB( uint8 update, AddrMgrEntry_t *entryOld,
  71. AddrMgrEntry_t *entryNew );
  72. BindingEntry_t *bindFindEmpty( void );
  73. uint16 bindingAddrMgsHelperFind( zAddrType_t *addr );
  74. uint8 bindingAddrMgsHelperConvert( uint16 idx, zAddrType_t *addr );
  75. void bindAddrMgrLocalLoad( void );
  76. uint16 bindAddrIndexGet( zAddrType_t* addr );
  77. /*********************************************************************
  78. * LOCAL VARIABLES
  79. */
  80. static uint8 bindAddrMgrLocalLoaded = FALSE;
  81. /*********************************************************************
  82. * Function Pointers
  83. */
  84. BindingEntry_t *(*pbindAddEntry)( byte srcEpInt,
  85. zAddrType_t *dstAddr, byte dstEpInt,
  86. byte numClusterIds, uint16 *clusterIds ) = (void*)NULL;
  87. uint16 (*pbindNumOfEntries)( void ) = (void*)NULL;
  88. void (*pbindRemoveDev)( zAddrType_t *Addr ) = (void*)NULL;
  89. byte (*pBindInitNV)( void ) = (void*)NULL;
  90. void (*pBindSetDefaultNV)( void ) = (void*)NULL;
  91. uint16 (*pBindRestoreFromNV)( void ) = (void*)NULL;
  92. void (*pBindWriteNV)( void ) = (void*)NULL;
  93. #if ( ADDRMGR_CALLBACK_ENABLED == 1 )
  94. /*********************************************************************
  95. * @fn BindAddrMgrCB()
  96. *
  97. * @brief Address Manager Callback function
  98. *
  99. * @param update -
  100. * @param entry -
  101. *
  102. * @return pointer to
  103. */
  104. void BindAddrMgrCB( uint8 update, AddrMgrEntry_t *entryNew,
  105. AddrMgrEntry_t *entryOld )
  106. {
  107. // Check for either deleted items or changed Extended (Duplicate) addresses
  108. }
  109. #endif // ( ADDRMGR_CALLBACK_ENABLED == 1 )
  110. /*********************************************************************
  111. * @fn InitBindingTable()
  112. *
  113. * @brief
  114. *
  115. * This function is used to initialise the binding table
  116. *
  117. * @param none
  118. *
  119. * @return none
  120. */
  121. void InitBindingTable( void )
  122. {
  123. osal_memset( BindingTable, 0xFF, gBIND_REC_SIZE * gNWK_MAX_BINDING_ENTRIES );
  124. pbindAddEntry = bindAddEntry;
  125. pbindNumOfEntries = bindNumOfEntries;
  126. pbindRemoveDev = bindRemoveDev;
  127. pBindInitNV = BindInitNV;
  128. pBindSetDefaultNV = BindSetDefaultNV;
  129. pBindRestoreFromNV = BindRestoreFromNV;
  130. pBindWriteNV = BindWriteNV;
  131. bindAddrMgrLocalLoaded = FALSE;
  132. #if ( ADDRMGR_CALLBACK_ENABLED == 1 )
  133. // Register with the address manager
  134. AddrMgrRegister( ADDRMGR_REG_BINDING, BindAddrMgrCB );
  135. #endif
  136. }
  137. /*********************************************************************
  138. * @fn bindFindEmpty()
  139. *
  140. * @brief This function returns a pointer to an empty binding slot
  141. *
  142. * @param none
  143. *
  144. * @return pointer to binding table entry, NULL if not added
  145. */
  146. BindingEntry_t *bindFindEmpty( void )
  147. {
  148. uint16 x;
  149. for ( x = 0; x < gNWK_MAX_BINDING_ENTRIES; x++ )
  150. {
  151. // It's empty if the index is "Not Found"
  152. if ( BindingTable[x].srcEP == NV_BIND_EMPTY )
  153. {
  154. return ( &BindingTable[x] );
  155. }
  156. }
  157. return ( (BindingEntry_t *)NULL );
  158. }
  159. /*********************************************************************
  160. * @fn bindNumOfEntries()
  161. *
  162. * @brief This function returns the number of binding table entries.
  163. * The return for this is the number of clusters in the
  164. * table NOT the number of entries.
  165. *
  166. * @param none
  167. *
  168. * @return number of entries
  169. */
  170. uint16 bindNumOfEntries( void )
  171. {
  172. uint16 x;
  173. uint16 found;
  174. for ( found = 0, x = 0; x < gNWK_MAX_BINDING_ENTRIES; x++ )
  175. {
  176. // It's empty if the index is "Not Found"
  177. if ( BindingTable[x].srcEP != NV_BIND_EMPTY )
  178. {
  179. found += BindingTable[x].numClusterIds;
  180. }
  181. }
  182. return ( found );
  183. }
  184. /*********************************************************************
  185. * @fn bindCapacity()
  186. *
  187. * @brief This function returns the number of binding entries
  188. * possible and used.
  189. *
  190. * @param maxEntries - pointer to a place to put the max entries
  191. * @param usedEntries - pointer to a place to put the number
  192. * of used entries
  193. *
  194. * @return none
  195. */
  196. void bindCapacity( uint16 *maxEntries, uint16 *usedEntries )
  197. {
  198. uint16 x;
  199. uint16 used;
  200. for ( used = 0, x = 0; x < gNWK_MAX_BINDING_ENTRIES; x++ )
  201. {
  202. // It's empty if the index is "Not Found"
  203. if ( BindingTable[x].srcEP != NV_BIND_EMPTY )
  204. {
  205. used++;
  206. }
  207. }
  208. *maxEntries = gNWK_MAX_BINDING_ENTRIES;
  209. *usedEntries = used;
  210. }
  211. /*********************************************************************
  212. * @fn bindAddEntry()
  213. *
  214. * @brief This function is used to Add an entry to the binding table
  215. *
  216. * @param srcAddr - source Address
  217. * @param srcEpInt - source endpoint
  218. * @param dstAddr - destination Address
  219. * @param dstEpInt - destination endpoint
  220. * @param numClusterIds - number of cluster Ids in the list
  221. * @param clusterIds - pointer to the Object ID list
  222. *
  223. * @return pointer to binding table entry, NULL if not added
  224. */
  225. BindingEntry_t *bindAddEntry( byte srcEpInt,
  226. zAddrType_t *dstAddr, byte dstEpInt,
  227. byte numClusterIds, uint16 *clusterIds )
  228. {
  229. uint8 index;
  230. BindingEntry_t* entry;
  231. bindFields_t fields;
  232. // initialize results
  233. entry = NULL;
  234. // make sure local addresses have been loaded
  235. bindAddrMgrLocalLoad();
  236. // setup fields
  237. fields.dstIndex = bindAddrIndexGet( dstAddr );
  238. fields.srcEP = srcEpInt;
  239. if ( dstAddr->addrMode == AddrGroup )
  240. {
  241. fields.dstAddrMode = DSTGROUPMODE_GROUP;
  242. fields.dstEP = 0;
  243. }
  244. else
  245. {
  246. fields.dstAddrMode = DSTGROUPMODE_ADDR;
  247. fields.dstEP = dstEpInt;
  248. }
  249. if ( fields.dstIndex != INVALID_NODE_ADDR )
  250. {
  251. for ( index = 0; index < gNWK_MAX_BINDING_ENTRIES; index++ )
  252. {
  253. if ( ( fields.srcEP == BindingTable[index].srcEP ) &&
  254. ( fields.dstAddrMode == BindingTable[index].dstGroupMode ) &&
  255. ( fields.dstIndex == BindingTable[index].dstIdx ) &&
  256. ( fields.dstEP == BindingTable[index].dstEP ) )
  257. {
  258. entry = &BindingTable[index];
  259. // break from loop
  260. break;
  261. }
  262. }
  263. if ( entry != NULL )
  264. {
  265. // Loop through the cluster IDs
  266. for ( index = 0; index < numClusterIds; index++ )
  267. {
  268. // Found - is the cluster already defined?
  269. if ( bindIsClusterIDinList( entry, clusterIds[index] ) == FALSE )
  270. {
  271. // Nope, add this cluster
  272. if ( bindAddClusterIdToList( entry, clusterIds[index] ) == FALSE )
  273. {
  274. // Indicate error if cluster list was full
  275. entry = NULL;
  276. }
  277. }
  278. }
  279. }
  280. else
  281. {
  282. // Find an empty slot
  283. entry = bindFindEmpty();
  284. // Check against the maximum number allowed
  285. if ( entry != NULL )
  286. {
  287. // Add new entry
  288. entry->srcEP = fields.srcEP;
  289. entry->dstGroupMode = fields.dstAddrMode;
  290. entry->dstIdx = fields.dstIndex;
  291. entry->dstEP = fields.dstEP;
  292. if ( numClusterIds > gMAX_BINDING_CLUSTER_IDS )
  293. {
  294. numClusterIds = gMAX_BINDING_CLUSTER_IDS;
  295. }
  296. entry->numClusterIds = numClusterIds;
  297. osal_memcpy( entry->clusterIdList,
  298. clusterIds,
  299. numClusterIds * sizeof(uint16) );
  300. }
  301. }
  302. }
  303. return entry;
  304. }
  305. /*********************************************************************
  306. * @fn bindRemoveEntry
  307. *
  308. * @brief Removes a binding table entry.
  309. *
  310. * @param pBind - pointer to binding table entry to delete
  311. *
  312. * @return TRUE if Removed, FALSE if not
  313. */
  314. byte bindRemoveEntry( BindingEntry_t *pBind )
  315. {
  316. osal_memset( pBind, 0xFF, gBIND_REC_SIZE );
  317. return ( TRUE );
  318. }
  319. /*********************************************************************
  320. * @fn bindIsClusterIDinList()
  321. *
  322. * @brief Is the clusterID in the clusterID list?
  323. *
  324. * @param enter - binding table entry
  325. * @param clusterId - Cluster ID to look for
  326. *
  327. * @return TRUE if found, FALSE if not found
  328. */
  329. byte bindIsClusterIDinList( BindingEntry_t *entry, uint16 clusterId )
  330. {
  331. uint8 x;
  332. if ( entry != NULL )
  333. {
  334. for ( x = 0; x < entry->numClusterIds; x++ )
  335. {
  336. if ( entry->clusterIdList[x] == clusterId )
  337. {
  338. return ( TRUE );
  339. }
  340. }
  341. }
  342. return ( FALSE );
  343. }
  344. /*********************************************************************
  345. * @fn bindRemoveClusterIdFromList()
  346. *
  347. * @brief Removes a ClusterID from a list of ClusterIDs.
  348. *
  349. * @param enter - binding table entry
  350. * @param clusterId - Cluster ID to look for
  351. *
  352. * @return TRUE if there are at least 1 clusterID left, FALSE if none
  353. */
  354. byte bindRemoveClusterIdFromList( BindingEntry_t *entry, uint16 clusterId )
  355. {
  356. byte x;
  357. uint16 *listPtr;
  358. byte numIds;
  359. if ( entry )
  360. {
  361. if ( entry->numClusterIds > 0 )
  362. {
  363. listPtr = entry->clusterIdList;
  364. numIds = entry->numClusterIds;
  365. // Copy the new list over
  366. for ( x = 0; x < numIds; x++ )
  367. {
  368. if ( entry->clusterIdList[x] != clusterId )
  369. {
  370. *listPtr++ = entry->clusterIdList[x];
  371. }
  372. else
  373. {
  374. entry->numClusterIds--;
  375. if ( entry->numClusterIds == 0 )
  376. {
  377. break;
  378. }
  379. }
  380. }
  381. }
  382. }
  383. if ( entry && (entry->numClusterIds > 0) )
  384. {
  385. return ( TRUE );
  386. }
  387. else
  388. {
  389. return ( FALSE );
  390. }
  391. }
  392. /*********************************************************************
  393. * @fn bindAddClusterIdToList()
  394. *
  395. * @brief Adds a ClusterID to a list of ClusterIDs.
  396. *
  397. * @param enter - binding table entry
  398. * @param clusterId - Cluster ID to Add
  399. *
  400. * @return TRUE if Added, FALSE if not
  401. */
  402. byte bindAddClusterIdToList( BindingEntry_t *entry, uint16 clusterId )
  403. {
  404. if ( entry && entry->numClusterIds < gMAX_BINDING_CLUSTER_IDS )
  405. {
  406. // Add the new one
  407. entry->clusterIdList[entry->numClusterIds] = clusterId;
  408. entry->numClusterIds++;
  409. return ( TRUE );
  410. }
  411. return ( FALSE );
  412. }
  413. /*********************************************************************
  414. * @fn bindFindExisting
  415. *
  416. * @brief Finds an existing src/epint to dst/epint bind record
  417. *
  418. * @param srcAddr - Source address
  419. * @param srcEpInt - Source Endpoint/Interface
  420. * @param dstAddr - Destination address
  421. * @param dstEpInt - Destination Endpoint/Interface
  422. *
  423. * @return pointer to existing entry or NULL
  424. */
  425. BindingEntry_t *bindFindExisting( byte srcEpInt,
  426. zAddrType_t *dstAddr, byte dstEpInt )
  427. {
  428. uint16 dstIdx;
  429. uint16 x;
  430. // Find the records in the assoc list
  431. if ( dstAddr->addrMode == AddrGroup )
  432. {
  433. dstIdx = dstAddr->addr.shortAddr;
  434. }
  435. else
  436. {
  437. dstIdx = bindingAddrMgsHelperFind( dstAddr );
  438. }
  439. if ( dstIdx == INVALID_NODE_ADDR )
  440. {
  441. return ( (BindingEntry_t *)NULL );
  442. }
  443. // Start at the beginning
  444. for ( x = 0; x < gNWK_MAX_BINDING_ENTRIES; x++ )
  445. {
  446. if ( (BindingTable[x].srcEP == srcEpInt) )
  447. {
  448. if ( ((dstAddr->addrMode == AddrGroup)
  449. && (BindingTable[x].dstGroupMode == DSTGROUPMODE_GROUP)
  450. && (dstIdx == BindingTable[x].dstIdx))
  451. || ((dstAddr->addrMode != AddrGroup)
  452. && (BindingTable[x].dstGroupMode == DSTGROUPMODE_ADDR)
  453. && (dstIdx == BindingTable[x].dstIdx) && (BindingTable[x].dstEP == dstEpInt)) )
  454. {
  455. return ( &BindingTable[x] );
  456. }
  457. }
  458. }
  459. return ( (BindingEntry_t *)NULL );
  460. }
  461. /*********************************************************************
  462. * @fn bindRemoveDev()
  463. *
  464. * @brief
  465. *
  466. * Remove all bind(s) entries associated to a device address (destination).
  467. * Updates binding table.
  468. *
  469. * @param Addr - address of device to be removed from Binding Table
  470. *
  471. * @return none
  472. */
  473. void bindRemoveDev( zAddrType_t *Addr )
  474. {
  475. uint16 idx;
  476. uint16 x;
  477. if ( Addr->addrMode == AddrGroup )
  478. {
  479. idx = Addr->addr.shortAddr;
  480. }
  481. else
  482. {
  483. idx = bindingAddrMgsHelperFind( Addr );
  484. }
  485. if ( idx == INVALID_NODE_ADDR )
  486. {
  487. return;
  488. }
  489. // Removes all the entries that match the destination Address/Index
  490. for ( x = 0; x < gNWK_MAX_BINDING_ENTRIES; x++ )
  491. {
  492. if ( ( (Addr->addrMode == AddrGroup) && (BindingTable[x].dstGroupMode == DSTGROUPMODE_GROUP)
  493. && (BindingTable[x].dstIdx == idx) ) ||
  494. ( (Addr->addrMode != AddrGroup) && (BindingTable[x].dstGroupMode == DSTGROUPMODE_ADDR)
  495. && (BindingTable[x].dstIdx == idx) ) )
  496. {
  497. bindRemoveEntry( &BindingTable[x] );
  498. }
  499. }
  500. }
  501. /*********************************************************************
  502. * @fn bindRemoveSrcDev()
  503. *
  504. * @brief
  505. *
  506. * Remove binds(s) associated to device address (source).
  507. * Updates binding table.
  508. *
  509. * @param srcAddr - address of device
  510. * @param ep - endpoint to remove, 0xFF is all endpoints
  511. *
  512. * @return none
  513. */
  514. void bindRemoveSrcDev( uint8 ep )
  515. {
  516. uint16 x;
  517. for ( x = 0; x < gNWK_MAX_BINDING_ENTRIES; x++ )
  518. {
  519. if ( (ep == 0xFF) || (ep == BindingTable[x].srcEP) )
  520. {
  521. bindRemoveEntry( &BindingTable[x] );
  522. }
  523. }
  524. }
  525. /*********************************************************************
  526. * @fn bindNumBoundTo
  527. *
  528. * @brief Calculate the number items this device is bound to.
  529. * When srcMode is set to TRUE, discard what value devAddr
  530. * has, it returns number count bound to the local dev.
  531. *
  532. * @param devAddr - device Address
  533. * @param devEP - endpoint
  534. * @param srcMode - TRUE - assume devHandle is a source address
  535. * FALSE - destination address
  536. *
  537. * @return status
  538. */
  539. byte bindNumBoundTo( zAddrType_t *devAddr, byte devEpInt, byte srcMode )
  540. {
  541. BindingEntry_t *pBind;
  542. uint16 idx;
  543. byte num;
  544. uint16 x;
  545. // Init
  546. num = 0;
  547. if ( devAddr->addrMode == AddrGroup )
  548. {
  549. idx = devAddr->addr.shortAddr;
  550. }
  551. else
  552. {
  553. idx = bindingAddrMgsHelperFind( devAddr );
  554. }
  555. for ( x = 0; x < gNWK_MAX_BINDING_ENTRIES; x++ )
  556. {
  557. pBind = &BindingTable[x];
  558. if ( srcMode )
  559. {
  560. if ( pBind->srcEP == devEpInt )
  561. {
  562. num++;
  563. }
  564. }
  565. else
  566. {
  567. if ( ((devAddr->addrMode == AddrGroup)
  568. && (pBind->dstGroupMode == DSTGROUPMODE_GROUP) && (pBind->dstIdx == idx))
  569. || ((devAddr->addrMode != AddrGroup) && (pBind->dstGroupMode == DSTGROUPMODE_ADDR)
  570. && (pBind->dstIdx == idx) && (pBind->dstEP == devEpInt)) )
  571. {
  572. num++;
  573. }
  574. }
  575. }
  576. return num;
  577. }
  578. /*********************************************************************
  579. * @fn bindNumReflections
  580. *
  581. * @brief Counts the number of reflections needed for a
  582. * endpoint and cluster ID combo.
  583. *
  584. * @param ep - source endpoint
  585. * @param clusterID - matching clusterID
  586. *
  587. * @return number of reflections needed.
  588. */
  589. uint16 bindNumReflections( uint8 ep, uint16 clusterID )
  590. {
  591. uint16 x;
  592. BindingEntry_t *pBind;
  593. uint16 cnt = 0;
  594. uint8 bindEP;
  595. for ( x = 0; x < gNWK_MAX_BINDING_ENTRIES; x++ )
  596. {
  597. pBind = &BindingTable[x];
  598. bindEP = pBind->srcEP;
  599. if ( (bindEP == ep) && (bindIsClusterIDinList( pBind, clusterID )) )
  600. {
  601. cnt++;
  602. }
  603. }
  604. return ( cnt );
  605. }
  606. /*********************************************************************
  607. * @fn bindFind
  608. *
  609. * @brief Finds the binding entry for the source address, endpoint
  610. * and cluster ID passed in as a parameter.
  611. *
  612. * @param ep - source endpoint
  613. * @param clusterID - matching clusterID
  614. * @param skip - number of matches to skip before returning
  615. *
  616. * @return pointer to the binding table entry, NULL if not found
  617. */
  618. BindingEntry_t *bindFind( uint8 ep, uint16 clusterID, uint8 skipping )
  619. {
  620. BindingEntry_t *pBind;
  621. byte skipped = 0;
  622. uint16 x;
  623. for ( x = 0; x < gNWK_MAX_BINDING_ENTRIES; x++ )
  624. {
  625. pBind = &BindingTable[x];
  626. if ( ( pBind->srcEP == ep) && bindIsClusterIDinList( pBind, clusterID ))
  627. {
  628. if ( skipped < skipping )
  629. {
  630. skipped++;
  631. }
  632. else
  633. {
  634. return ( pBind );
  635. }
  636. }
  637. }
  638. return ( (BindingEntry_t *)NULL );
  639. }
  640. /*********************************************************************
  641. * @fn BindInitNV
  642. *
  643. * @brief Initialize the Binding NV Item
  644. *
  645. * @param none
  646. *
  647. * @return ZSUCCESS if successful, NV_ITEM_UNINIT if item did not
  648. * exist in NV, NV_OPER_FAILED if failure.
  649. */
  650. byte BindInitNV( void )
  651. {
  652. byte ret;
  653. // Initialize the device list
  654. ret = osal_nv_item_init( ZCD_NV_BINDING_TABLE,
  655. (uint16)(gBIND_REC_SIZE + NV_BIND_ITEM_SIZE), NULL );
  656. if ( ret != ZSUCCESS )
  657. {
  658. BindSetDefaultNV();
  659. }
  660. return ( ret );
  661. }
  662. /*********************************************************************
  663. * @fn BindSetDefaultNV
  664. *
  665. * @brief Write the defaults to NV
  666. *
  667. * @param none
  668. *
  669. * @return none
  670. */
  671. void BindSetDefaultNV( void )
  672. {
  673. nvBindingHdr_t hdr;
  674. // Initialize the header
  675. hdr.numRecs = 0;
  676. // Save off the header
  677. osal_nv_write( ZCD_NV_BINDING_TABLE, 0, sizeof( nvBindingHdr_t ), &hdr );
  678. }
  679. /*********************************************************************
  680. * @fn BindRestoreFromNV
  681. *
  682. * @brief Restore the binding table from NV
  683. *
  684. * @param none
  685. *
  686. * @return Number of entries restored
  687. */
  688. uint16 BindRestoreFromNV( void )
  689. {
  690. nvBindingHdr_t hdr;
  691. uint16 numAdded = 0;
  692. if ( osal_nv_read( ZCD_NV_BINDING_TABLE, 0, sizeof(nvBindingHdr_t), &hdr ) == ZSuccess )
  693. {
  694. if (hdr.numRecs > 0)
  695. {
  696. // Read the whole table at once
  697. if ( osal_nv_read( ZCD_NV_BINDING_TABLE,
  698. (uint16)(sizeof(nvBindingHdr_t)),
  699. (NV_BIND_REC_SIZE * gNWK_MAX_BINDING_ENTRIES), BindingTable ) == ZSUCCESS )
  700. {
  701. numAdded = gNWK_MAX_BINDING_ENTRIES;
  702. }
  703. }
  704. }
  705. return ( numAdded );
  706. }
  707. /*********************************************************************
  708. * @fn BindWriteNV
  709. *
  710. * @brief Save the Binding Table in NV
  711. *
  712. * @param none
  713. *
  714. * @return none
  715. */
  716. void BindWriteNV( void )
  717. {
  718. BindingEntry_t *pBind;
  719. BindingEntry_t bind;
  720. nvBindingHdr_t hdr;
  721. uint16 x;
  722. hdr.numRecs = 0;
  723. for ( x = 0; x < gNWK_MAX_BINDING_ENTRIES; x++ )
  724. {
  725. pBind = &BindingTable[x];
  726. osal_memcpy( &bind, pBind, gBIND_REC_SIZE );
  727. // Save the record to NV
  728. osal_nv_write( ZCD_NV_BINDING_TABLE,
  729. (uint16)((sizeof(nvBindingHdr_t)) + (x * NV_BIND_REC_SIZE)),
  730. NV_BIND_REC_SIZE, &bind );
  731. if ( pBind->srcEP != NV_BIND_EMPTY )
  732. {
  733. hdr.numRecs++;
  734. }
  735. }
  736. // Save off the header
  737. osal_nv_write( ZCD_NV_BINDING_TABLE, 0, sizeof(nvBindingHdr_t), &hdr );
  738. }
  739. /*********************************************************************
  740. * @fn bindUpdateAddr
  741. *
  742. * @brief Update the network address in the binding table.
  743. *
  744. * @param oldAddr - old network address
  745. * @param newAddr - new network address
  746. *
  747. * @return none
  748. */
  749. void bindUpdateAddr( uint16 oldAddr, uint16 newAddr )
  750. {
  751. uint16 oldIdx;
  752. uint16 newIdx;
  753. zAddrType_t addr;
  754. uint16 x;
  755. BindingEntry_t *pBind;
  756. addr.addrMode = Addr16Bit;
  757. addr.addr.shortAddr = oldAddr;
  758. oldIdx = bindingAddrMgsHelperFind( &addr );
  759. addr.addr.shortAddr = newAddr;
  760. newIdx = bindingAddrMgsHelperFind( &addr );
  761. for ( x = 0; x < gNWK_MAX_BINDING_ENTRIES; x++ )
  762. {
  763. pBind = &BindingTable[x];
  764. if ( pBind->dstIdx == oldIdx )
  765. {
  766. pBind->dstIdx = newIdx;
  767. }
  768. }
  769. }
  770. /*********************************************************************
  771. * @fn bindingAddrMgsHelperFind
  772. *
  773. * @brief Turns an zAddrType_t to an Addr Manager index
  774. *
  775. * @param addr - zAddrType_t
  776. *
  777. * @return INVALID_NODE_ADDR if not found, otherwise an index
  778. */
  779. uint16 bindingAddrMgsHelperFind( zAddrType_t *addr )
  780. {
  781. AddrMgrEntry_t entry;
  782. // Resolve addresses with the address manager
  783. entry.user = ADDRMGR_USER_BINDING;
  784. if ( addr->addrMode == Addr16Bit )
  785. {
  786. entry.nwkAddr = addr->addr.shortAddr;
  787. AddrMgrEntryLookupNwk( &entry );
  788. }
  789. else
  790. {
  791. AddrMgrExtAddrSet( entry.extAddr, addr->addr.extAddr );
  792. AddrMgrEntryLookupExt( &entry );
  793. }
  794. return ( entry.index );
  795. }
  796. /*********************************************************************
  797. * @fn bindingAddrMgsHelperConvert
  798. *
  799. * @brief Convert an index into an zAddrType_t
  800. *
  801. * @param idx -
  802. * @param addr - zAddrType_t
  803. *
  804. * @return TRUE if found, FALSE if not
  805. */
  806. uint8 bindingAddrMgsHelperConvert( uint16 idx, zAddrType_t *addr )
  807. {
  808. AddrMgrEntry_t entry;
  809. uint8 stat;
  810. // Resolve addresses with the address manager
  811. entry.user = ADDRMGR_USER_BINDING;
  812. entry.index = idx;
  813. stat = AddrMgrEntryGet( &entry );
  814. if ( stat )
  815. {
  816. addr->addrMode = Addr64Bit;
  817. osal_cpyExtAddr( addr->addr.extAddr, entry.extAddr );
  818. }
  819. return ( stat );
  820. }
  821. /*********************************************************************
  822. * @fn bindingAddrMgsHelperConvertShort
  823. *
  824. * @brief Convert an index into a short address
  825. *
  826. * @param idx -
  827. *
  828. * @return INVALID_NODE_ADDR if not available, otherwise the short address
  829. */
  830. uint16 bindingAddrMgsHelperConvertShort( uint16 idx )
  831. {
  832. AddrMgrEntry_t entry;
  833. // Resolve addresses with the address manager
  834. entry.user = ADDRMGR_USER_BINDING;
  835. entry.index = idx;
  836. AddrMgrEntryGet( &entry );
  837. return ( entry.nwkAddr );
  838. }
  839. /*********************************************************************
  840. * @fn bindAddrMgrLocalLoad
  841. *
  842. * @brief Load local(self and parent) address information into
  843. * Address Manager
  844. *
  845. * @param none
  846. *
  847. * @return none
  848. */
  849. void bindAddrMgrLocalLoad( void )
  850. {
  851. AddrMgrEntry_t entry;
  852. uint16 parent;
  853. // add "local"(self and parent) address informtion into the Address
  854. // Manager
  855. if ( bindAddrMgrLocalLoaded == FALSE )
  856. {
  857. // add the device's address information
  858. entry.user = ADDRMGR_USER_BINDING;
  859. entry.nwkAddr = _NIB.nwkDevAddress;
  860. AddrMgrExtAddrSet( entry.extAddr, NLME_GetExtAddr() );
  861. AddrMgrEntryUpdate( &entry );
  862. // make sure parent address is valid
  863. parent = NLME_GetCoordShortAddr();
  864. if ( ( parent != entry.nwkAddr ) &&
  865. ( parent != INVALID_NODE_ADDR ) )
  866. {
  867. // add the parent's address information
  868. entry.nwkAddr = parent;
  869. NLME_GetCoordExtAddr( entry.extAddr );
  870. AddrMgrEntryUpdate( &entry );
  871. }
  872. bindAddrMgrLocalLoaded = TRUE;
  873. }
  874. }
  875. /*********************************************************************
  876. * @fn bindAddrIndexGet
  877. *
  878. * @brief Get bind address index.
  879. *
  880. * @param addr - <zAddrType_t>
  881. *
  882. * @return (uint16) address index
  883. */
  884. uint16 bindAddrIndexGet( zAddrType_t* addr )
  885. {
  886. AddrMgrEntry_t entry;
  887. uint8 update;
  888. update = FALSE;
  889. // sync binding addresses with the address manager
  890. entry.user = ADDRMGR_USER_BINDING;
  891. if ( addr->addrMode == Addr16Bit )
  892. {
  893. entry.nwkAddr = addr->addr.shortAddr;
  894. if ( AddrMgrEntryLookupNwk( &entry ) == FALSE )
  895. {
  896. update = TRUE;
  897. }
  898. }
  899. else if ( addr->addrMode == Addr64Bit )
  900. {
  901. AddrMgrExtAddrSet( entry.extAddr, addr->addr.extAddr );
  902. if ( AddrMgrEntryLookupExt( &entry ) == FALSE )
  903. {
  904. update = TRUE;
  905. }
  906. }
  907. else if ( addr->addrMode == AddrGroup )
  908. {
  909. entry.index = addr->addr.shortAddr;
  910. }
  911. else
  912. {
  913. entry.index = INVALID_NODE_ADDR;
  914. }
  915. if ( update )
  916. {
  917. AddrMgrEntryUpdate( &entry );
  918. }
  919. return entry.index;
  920. }
  921. /*********************************************************************
  922. * @fn GetBindingTableEntry
  923. *
  924. * @brief Get a pointer to the Nth valid binding table entry.
  925. *
  926. * @param Nth valid entry being requested.
  927. *
  928. * @return The Nth valid binding table entry.
  929. */
  930. BindingEntry_t *GetBindingTableEntry( uint16 Nth )
  931. {
  932. BindingEntry_t *rtrn = NULL;
  933. #if defined ( REFLECTOR )
  934. uint16 idx, cnt = 0;
  935. for ( idx = 0; idx < gNWK_MAX_BINDING_ENTRIES; idx++ )
  936. {
  937. if ( BindingTable[idx].srcEP != NV_BIND_EMPTY )
  938. {
  939. if ( cnt++ == Nth )
  940. {
  941. rtrn = BindingTable+idx;
  942. break;
  943. }
  944. }
  945. }
  946. #else
  947. (void)Nth;
  948. #endif
  949. return rtrn;
  950. }
  951. /*********************************************************************
  952. *********************************************************************/