sapi.c 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016
  1. /**************************************************************************************************
  2. Filename: sapi.c
  3. Revised: $Date: 2009-03-18 15:53:27 -0700 (Wed, 18 Mar 2009) $
  4. Revision: $Revision: 19452 $
  5. Description: Z-Stack Simple Application Interface.
  6. Copyright 2007 Texas Instruments Incorporated. All rights reserved.
  7. IMPORTANT: Your use of this Software is limited to those specific rights
  8. granted under the terms of a software license agreement between the user
  9. who downloaded the software, his/her employer (which must be your employer)
  10. and Texas Instruments Incorporated (the "License"). You may not use this
  11. Software unless you agree to abide by the terms of the License. The License
  12. limits your use, and you acknowledge, that the Software may not be modified,
  13. copied or distributed unless embedded on a Texas Instruments microcontroller
  14. or used solely and exclusively in conjunction with a Texas Instruments radio
  15. frequency transceiver, which is integrated into your product. Other than for
  16. the foregoing purpose, you may not use, reproduce, copy, prepare derivative
  17. works of, modify, distribute, perform, display or sell this Software and/or
  18. its documentation for any purpose.
  19. YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
  20. PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
  21. INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
  22. NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
  23. TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
  24. NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
  25. LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
  26. INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
  27. OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
  28. OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
  29. (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
  30. Should you have any questions regarding your right to use this Software,
  31. contact Texas Instruments Incorporated at www.TI.com.
  32. **************************************************************************************************/
  33. /******************************************************************************
  34. * INCLUDES
  35. */
  36. #include "ZComDef.h"
  37. #include "hal_drivers.h"
  38. #include "OSAL.h"
  39. #include "OSAL_Tasks.h"
  40. //#include "OSAL_Custom.h"
  41. #if defined ( MT_TASK )
  42. #include "MT.h"
  43. #include "MT_TASK.h"
  44. #endif
  45. #include "nwk.h"
  46. #include "APS.h"
  47. #include "ZDApp.h"
  48. #include "osal_nv.h"
  49. #include "NLMEDE.h"
  50. #include "AF.h"
  51. #include "OnBoard.h"
  52. #include "nwk_util.h"
  53. #include "ZDProfile.h"
  54. #include "ZDObject.h"
  55. #include "hal_led.h"
  56. #include "hal_key.h"
  57. #include "sapi.h"
  58. #include "MT_SAPI.h"
  59. extern uint8 zgStartDelay;
  60. extern uint8 zgSapiEndpoint;
  61. /*********************************************************************
  62. * CONSTANTS
  63. */
  64. // Message ID's for application user messages must be in 0xE0-0xEF range
  65. #define ZB_USER_MSG 0xE0
  66. #define SAPICB_DATA_CNF 0xE0
  67. #define SAPICB_BIND_CNF 0xE1
  68. #define SAPICB_START_CNF 0xE2
  69. /*********************************************************************
  70. * TYPEDEFS
  71. */
  72. /*********************************************************************
  73. * GLOBAL VARIABLES
  74. */
  75. // The order in this table must be identical to the task initialization calls below in osalInitTask.
  76. const pTaskEventHandlerFn tasksArr[] = {
  77. macEventLoop,
  78. nwk_event_loop,
  79. Hal_ProcessEvent,
  80. #if defined( MT_TASK )
  81. MT_ProcessEvent,
  82. #endif
  83. APS_event_loop,
  84. ZDApp_event_loop,
  85. SAPI_ProcessEvent
  86. };
  87. const uint8 tasksCnt = sizeof( tasksArr ) / sizeof( tasksArr[0] );
  88. uint16 *tasksEvents;
  89. endPointDesc_t sapi_epDesc;
  90. uint8 sapi_TaskID;
  91. static uint16 sapi_bindInProgress;
  92. /*********************************************************************
  93. * LOCAL FUNCTIONS
  94. */
  95. void SAPI_ProcessZDOMsgs( zdoIncomingMsg_t *inMsg );
  96. static void SAPI_SendCback( uint8 event, uint8 status, uint16 data );
  97. static void SAPI_StartConfirm( uint8 status );
  98. static void SAPI_SendDataConfirm( uint8 handle, uint8 status );
  99. static void SAPI_BindConfirm( uint16 commandId, uint8 status );
  100. static void SAPI_FindDeviceConfirm( uint8 searchType,
  101. uint8 *searchKey, uint8 *result );
  102. static void SAPI_ReceiveDataIndication( uint16 source,
  103. uint16 command, uint16 len, uint8 *pData );
  104. static void SAPI_AllowBindConfirm( uint16 source );
  105. /******************************************************************************
  106. * @fn zb_SystemReset
  107. *
  108. * @brief The zb_SystemReset function reboots the ZigBee device. The
  109. * zb_SystemReset function can be called after a call to
  110. * zb_WriteConfiguration to restart Z-Stack with the updated
  111. * configuration.
  112. *
  113. * @param none
  114. *
  115. * @return none
  116. */
  117. void zb_SystemReset ( void )
  118. {
  119. SystemReset();
  120. }
  121. /******************************************************************************
  122. * @fn zb_StartRequest
  123. *
  124. * @brief The zb_StartRequest function starts the ZigBee stack. When the
  125. * ZigBee stack starts, the device reads configuration parameters
  126. * from Nonvolatile memory and the device joins its network. The
  127. * ZigBee stack calls the zb_StartConrifm callback function when
  128. * the startup process completes.
  129. *
  130. * @param none
  131. *
  132. * @return none
  133. */
  134. void zb_StartRequest()
  135. {
  136. uint8 logicalType;
  137. // Start the device
  138. // start delay = min(NWK_START_DELAY, zgStartDelay) + rand() - only for fresh start, not restore
  139. if ( zgStartDelay < NWK_START_DELAY )
  140. zgStartDelay = 0;
  141. else
  142. zgStartDelay -= NWK_START_DELAY;
  143. // check that bad combinations of compile flag definitions and device type
  144. zb_ReadConfiguration( ZCD_NV_LOGICAL_TYPE, sizeof(uint8), &logicalType );
  145. if ( ( logicalType > ZG_DEVICETYPE_ENDDEVICE ) ||
  146. #if defined( RTR_NWK )
  147. #if defined( ZDO_COORDINATOR )
  148. // Only RTR or Coord possible
  149. ( logicalType == ZG_DEVICETYPE_ENDDEVICE ) ||
  150. #else
  151. // Only RTR possible
  152. ( logicalType != ZG_DEVICETYPE_ROUTER ) ||
  153. #endif
  154. #else
  155. #if defined( ZDO_COORDINATOR )
  156. // Error
  157. ( 1 ) ||
  158. #else
  159. // only ED possible
  160. ( logicalType != ZG_DEVICETYPE_ENDDEVICE ) ||
  161. #endif
  162. #endif
  163. ( 0 ) )
  164. {
  165. // error configuration
  166. SAPI_SendCback( SAPICB_START_CNF, ZInvalidParameter, 0 );
  167. }
  168. else
  169. {
  170. ZDOInitDevice(zgStartDelay);
  171. }
  172. return;
  173. }
  174. /******************************************************************************
  175. * @fn zb_BindDevice
  176. *
  177. * @brief The zb_BindDevice function establishes or removes a ‘binding’
  178. * between two devices. Once bound, an application can send
  179. * messages to a device by referencing the commandId for the
  180. * binding.
  181. *
  182. * @param create - TRUE to create a binding, FALSE to remove a binding
  183. * commandId - The identifier of the binding
  184. * pDestination - The 64-bit IEEE address of the device to bind to
  185. *
  186. * @return The status of the bind operation is returned in the
  187. * zb_BindConfirm callback.
  188. */
  189. void zb_BindDevice ( uint8 create, uint16 commandId, uint8 *pDestination )
  190. {
  191. zAddrType_t destination;
  192. uint8 ret = ZB_ALREADY_IN_PROGRESS;
  193. if ( create )
  194. {
  195. if (sapi_bindInProgress == 0xffff)
  196. {
  197. if ( pDestination )
  198. {
  199. destination.addrMode = Addr64Bit;
  200. osal_cpyExtAddr( destination.addr.extAddr, pDestination );
  201. ret = APSME_BindRequest( sapi_epDesc.endPoint, commandId,
  202. &destination, sapi_epDesc.endPoint );
  203. if ( ret == ZSuccess )
  204. {
  205. // Find nwk addr
  206. ZDP_NwkAddrReq(pDestination, ZDP_ADDR_REQTYPE_SINGLE, 0, 0 );
  207. osal_start_timerEx( ZDAppTaskID, ZDO_NWK_UPDATE_NV, 250 );
  208. }
  209. }
  210. else
  211. {
  212. ret = ZB_INVALID_PARAMETER;
  213. destination.addrMode = Addr16Bit;
  214. destination.addr.shortAddr = NWK_BROADCAST_SHORTADDR;
  215. if ( ZDO_AnyClusterMatches( 1, &commandId, sapi_epDesc.simpleDesc->AppNumOutClusters,
  216. sapi_epDesc.simpleDesc->pAppOutClusterList ) )
  217. {
  218. // Try to match with a device in the allow bind mode
  219. ret = ZDP_MatchDescReq( &destination, NWK_BROADCAST_SHORTADDR,
  220. sapi_epDesc.simpleDesc->AppProfId, 1, &commandId, 0, (cId_t *)NULL, 0 );
  221. }
  222. else if ( ZDO_AnyClusterMatches( 1, &commandId, sapi_epDesc.simpleDesc->AppNumInClusters,
  223. sapi_epDesc.simpleDesc->pAppInClusterList ) )
  224. {
  225. ret = ZDP_MatchDescReq( &destination, NWK_BROADCAST_SHORTADDR,
  226. sapi_epDesc.simpleDesc->AppProfId, 0, (cId_t *)NULL, 1, &commandId, 0 );
  227. }
  228. if ( ret == ZB_SUCCESS )
  229. {
  230. // Set a timer to make sure bind completes
  231. #if ( ZG_BUILD_RTR_TYPE )
  232. osal_start_timerEx(sapi_TaskID, ZB_BIND_TIMER, AIB_MaxBindingTime);
  233. #else
  234. // AIB_MaxBindingTime is not defined for an End Device
  235. osal_start_timerEx(sapi_TaskID, ZB_BIND_TIMER, zgApsDefaultMaxBindingTime);
  236. #endif
  237. sapi_bindInProgress = commandId;
  238. return; // dont send cback event
  239. }
  240. }
  241. }
  242. SAPI_SendCback( SAPICB_BIND_CNF, ret, commandId );
  243. }
  244. else
  245. {
  246. // Remove local bindings for the commandId
  247. BindingEntry_t *pBind;
  248. // Loop through bindings an remove any that match the cluster
  249. while ( pBind = bindFind( sapi_epDesc.simpleDesc->EndPoint, commandId, 0 ) )
  250. {
  251. bindRemoveEntry(pBind);
  252. }
  253. osal_start_timerEx( ZDAppTaskID, ZDO_NWK_UPDATE_NV, 250 );
  254. }
  255. return;
  256. }
  257. /******************************************************************************
  258. * @fn zb_PermitJoiningRequest
  259. *
  260. * @brief The zb_PermitJoiningRequest function is used to control the
  261. * joining permissions and thus allow or disallow new devices from
  262. * joining the network.
  263. *
  264. * @param destination - The destination parameter indicates the address
  265. * of the device for which the joining permissions
  266. * should be set. This is usually the local device
  267. * address or the special broadcast address that denotes
  268. * all routers and coordinator ( 0xFFFC ). This way
  269. * the joining permissions of a single device or the
  270. * whole network can be controlled.
  271. * timeout - Indicates the amount of time in seconds for which
  272. * the joining permissions should be turned on.
  273. * If timeout is set to 0x00, the device will turn off the
  274. * joining permissions indefinitely. If it is set to 0xFF,
  275. * the joining permissions will be turned on indefinitely.
  276. *
  277. *
  278. * @return ZB_SUCCESS or a failure code
  279. *
  280. */
  281. uint8 zb_PermitJoiningRequest ( uint16 destination, uint8 timeout )
  282. {
  283. #if defined( ZDO_MGMT_PERMIT_JOIN_REQUEST )
  284. zAddrType_t dstAddr;
  285. dstAddr.addrMode = Addr16Bit;
  286. dstAddr.addr.shortAddr = destination;
  287. return( (uint8) ZDP_MgmtPermitJoinReq( &dstAddr, timeout, 0, 0 ) );
  288. #else
  289. (void)destination;
  290. (void)timeout;
  291. return ZUnsupportedMode;
  292. #endif
  293. }
  294. /******************************************************************************
  295. * @fn zb_AllowBind
  296. *
  297. * @brief The zb_AllowBind function puts the device into the
  298. * Allow Binding Mode for a given period of time. A peer device
  299. * can establish a binding to a device in the Allow Binding Mode
  300. * by calling zb_BindDevice with a destination address of NULL
  301. *
  302. * @param timeout - The number of seconds to remain in the allow binding
  303. * mode. Valid values range from 1 through 65.
  304. * If 0, the Allow Bind mode will be set false without TO
  305. * If greater than 64, the Allow Bind mode will be true
  306. *
  307. * @return ZB_SUCCESS if the device entered the allow bind mode, else
  308. * an error code.
  309. */
  310. void zb_AllowBind ( uint8 timeout )
  311. {
  312. osal_stop_timerEx(sapi_TaskID, ZB_ALLOW_BIND_TIMER);
  313. if ( timeout == 0 )
  314. {
  315. afSetMatch(sapi_epDesc.simpleDesc->EndPoint, FALSE);
  316. }
  317. else
  318. {
  319. afSetMatch(sapi_epDesc.simpleDesc->EndPoint, TRUE);
  320. if ( timeout != 0xFF )
  321. {
  322. if ( timeout > 64 )
  323. {
  324. timeout = 64;
  325. }
  326. osal_start_timerEx(sapi_TaskID, ZB_ALLOW_BIND_TIMER, timeout*1000);
  327. }
  328. }
  329. return;
  330. }
  331. /******************************************************************************
  332. * @fn zb_SendDataRequest
  333. *
  334. * @brief The zb_SendDataRequest function initiates transmission of data
  335. * to a peer device
  336. *
  337. * @param destination - The destination of the data. The destination can
  338. * be one of the following:
  339. * - 16-Bit short address of device [0-0xfffD]
  340. * - ZB_BROADCAST_ADDR sends the data to all devices
  341. * in the network.
  342. * - ZB_BINDING_ADDR sends the data to a previously
  343. * bound device.
  344. *
  345. * commandId - The command ID to send with the message. If the
  346. * ZB_BINDING_ADDR destination is used, this parameter
  347. * also indicates the binding to use.
  348. *
  349. * len - The size of the pData buffer in bytes
  350. * handle - A handle used to identify the send data request.
  351. * txOptions - TRUE if requesting acknowledgement from the destination.
  352. * radius - The max number of hops the packet can travel through
  353. * before it is dropped.
  354. *
  355. * @return none
  356. */
  357. void zb_SendDataRequest ( uint16 destination, uint16 commandId, uint8 len,
  358. uint8 *pData, uint8 handle, uint8 txOptions, uint8 radius )
  359. {
  360. afStatus_t status;
  361. afAddrType_t dstAddr;
  362. txOptions |= AF_DISCV_ROUTE;
  363. // Set the destination address
  364. if (destination == ZB_BINDING_ADDR)
  365. {
  366. // Binding
  367. dstAddr.addrMode = afAddrNotPresent;
  368. }
  369. else
  370. {
  371. // Use short address
  372. dstAddr.addr.shortAddr = destination;
  373. dstAddr.addrMode = afAddr16Bit;
  374. if ( ADDR_NOT_BCAST != NLME_IsAddressBroadcast( destination ) )
  375. {
  376. txOptions &= ~AF_ACK_REQUEST;
  377. }
  378. }
  379. // Set the endpoint
  380. dstAddr.endPoint = sapi_epDesc.simpleDesc->EndPoint;
  381. // Send the message
  382. status = AF_DataRequest(&dstAddr, &sapi_epDesc, commandId, len,
  383. pData, &handle, txOptions, radius);
  384. if (status != afStatus_SUCCESS)
  385. {
  386. SAPI_SendCback( SAPICB_DATA_CNF, status, handle );
  387. }
  388. }
  389. /******************************************************************************
  390. * @fn zb_ReadConfiguration
  391. *
  392. * @brief The zb_ReadConfiguration function is used to get a
  393. * Configuration Protperty from Nonvolatile memory.
  394. *
  395. * @param configId - The identifier for the configuration property
  396. * len - The size of the pValue buffer in bytes
  397. * pValue - A buffer to hold the configuration property
  398. *
  399. * @return none
  400. */
  401. uint8 zb_ReadConfiguration( uint8 configId, uint8 len, void *pValue )
  402. {
  403. uint8 size;
  404. size = (uint8)osal_nv_item_len( configId );
  405. if ( size > len )
  406. {
  407. return ZFailure;
  408. }
  409. else
  410. {
  411. return( osal_nv_read(configId, 0, size, pValue) );
  412. }
  413. }
  414. /******************************************************************************
  415. * @fn zb_WriteConfiguration
  416. *
  417. * @brief The zb_WriteConfiguration function is used to write a
  418. * Configuration Property to nonvolatile memory.
  419. *
  420. * @param configId - The identifier for the configuration property
  421. * len - The size of the pValue buffer in bytes
  422. * pValue - A buffer containing the new value of the
  423. * configuration property
  424. *
  425. * @return none
  426. */
  427. uint8 zb_WriteConfiguration( uint8 configId, uint8 len, void *pValue )
  428. {
  429. return( osal_nv_write(configId, 0, len, pValue) );
  430. }
  431. /******************************************************************************
  432. * @fn zb_GetDeviceInfo
  433. *
  434. * @brief The zb_GetDeviceInfo function retrieves a Device Information
  435. * Property.
  436. *
  437. * @param param - The identifier for the device information
  438. * pValue - A buffer to hold the device information
  439. *
  440. * @return none
  441. */
  442. void zb_GetDeviceInfo ( uint8 param, void *pValue )
  443. {
  444. switch(param)
  445. {
  446. case ZB_INFO_DEV_STATE:
  447. osal_memcpy(pValue, &devState, sizeof(uint8));
  448. break;
  449. case ZB_INFO_IEEE_ADDR:
  450. osal_memcpy(pValue, &aExtendedAddress, Z_EXTADDR_LEN);
  451. break;
  452. case ZB_INFO_SHORT_ADDR:
  453. osal_memcpy(pValue, &_NIB.nwkDevAddress, sizeof(uint16));
  454. break;
  455. case ZB_INFO_PARENT_SHORT_ADDR:
  456. osal_memcpy(pValue, &_NIB.nwkCoordAddress, sizeof(uint16));
  457. break;
  458. case ZB_INFO_PARENT_IEEE_ADDR:
  459. osal_memcpy(pValue, &_NIB.nwkCoordExtAddress, Z_EXTADDR_LEN);
  460. break;
  461. case ZB_INFO_CHANNEL:
  462. osal_memcpy(pValue, &_NIB.nwkLogicalChannel, sizeof(uint8));
  463. break;
  464. case ZB_INFO_PAN_ID:
  465. osal_memcpy(pValue, &_NIB.nwkPanId, sizeof(uint16));
  466. break;
  467. case ZB_INFO_EXT_PAN_ID:
  468. osal_memcpy(pValue, &_NIB.extendedPANID, Z_EXTADDR_LEN);
  469. break;
  470. }
  471. }
  472. /******************************************************************************
  473. * @fn zb_FindDeviceRequest
  474. *
  475. * @brief The zb_FindDeviceRequest function is used to determine the
  476. * short address for a device in the network. The device initiating
  477. * a call to zb_FindDeviceRequest and the device being discovered
  478. * must both be a member of the same network. When the search is
  479. * complete, the zv_FindDeviceConfirm callback function is called.
  480. *
  481. * @param searchType - The type of search to perform. Can be one of following:
  482. * ZB_IEEE_SEARCH - Search for 16-bit addr given IEEE addr.
  483. * searchKey - Value to search on.
  484. *
  485. * @return none
  486. */
  487. void zb_FindDeviceRequest( uint8 searchType, void *searchKey )
  488. {
  489. if (searchType == ZB_IEEE_SEARCH)
  490. {
  491. ZDP_NwkAddrReq((uint8*) searchKey, ZDP_ADDR_REQTYPE_SINGLE, 0, 0 );
  492. }
  493. }
  494. /******************************************************************************
  495. * @fn SAPI_StartConfirm
  496. *
  497. * @brief The SAPI_StartConfirm callback is called by the ZigBee stack
  498. * after a start request operation completes
  499. *
  500. * @param status - The status of the start operation. Status of
  501. * ZB_SUCCESS indicates the start operation completed
  502. * successfully. Else the status is an error code.
  503. *
  504. * @return none
  505. */
  506. void SAPI_StartConfirm( uint8 status )
  507. {
  508. #if defined ( MT_SAPI_CB_FUNC )
  509. /* First check if MT has subscribed for this callback. If so , pass it as
  510. a event to MonitorTest and return control to calling function after that */
  511. if ( SAPICB_CHECK( SPI_CB_SAPI_START_CNF ) )
  512. {
  513. zb_MTCallbackStartConfirm( status );
  514. }
  515. else
  516. #endif //MT_SAPI_CB_FUNC
  517. {
  518. zb_StartConfirm( status );
  519. }
  520. }
  521. /******************************************************************************
  522. * @fn SAPI_SendDataConfirm
  523. *
  524. * @brief The SAPI_SendDataConfirm callback function is called by the
  525. * ZigBee after a send data operation completes
  526. *
  527. * @param handle - The handle identifying the data transmission.
  528. * status - The status of the operation.
  529. *
  530. * @return none
  531. */
  532. void SAPI_SendDataConfirm( uint8 handle, uint8 status )
  533. {
  534. #if defined ( MT_SAPI_CB_FUNC )
  535. /* First check if MT has subscribed for this callback. If so , pass it as
  536. a event to MonitorTest and return control to calling function after that */
  537. if ( SAPICB_CHECK( SPI_CB_SAPI_SEND_DATA_CNF ) )
  538. {
  539. zb_MTCallbackSendDataConfirm( handle, status );
  540. }
  541. else
  542. #endif //MT_SAPI_CB_FUNC
  543. {
  544. zb_SendDataConfirm( handle, status );
  545. }
  546. }
  547. /******************************************************************************
  548. * @fn SAPI_BindConfirm
  549. *
  550. * @brief The SAPI_BindConfirm callback is called by the ZigBee stack
  551. * after a bind operation completes.
  552. *
  553. * @param commandId - The command ID of the binding being confirmed.
  554. * status - The status of the bind operation.
  555. * allowBind - TRUE if the bind operation was initiated by a call
  556. * to zb_AllowBindRespones. FALSE if the operation
  557. * was initiated by a call to ZB_BindDevice
  558. *
  559. * @return none
  560. */
  561. void SAPI_BindConfirm( uint16 commandId, uint8 status )
  562. {
  563. #if defined ( MT_SAPI_CB_FUNC )
  564. /* First check if MT has subscribed for this callback. If so , pass it as
  565. a event to MonitorTest and return control to calling function after that */
  566. if ( SAPICB_CHECK( SPI_CB_SAPI_BIND_CNF ) )
  567. {
  568. zb_MTCallbackBindConfirm( commandId, status );
  569. }
  570. else
  571. #endif //MT_SAPI_CB_FUNC
  572. {
  573. zb_BindConfirm( commandId, status );
  574. }
  575. }
  576. /******************************************************************************
  577. * @fn SAPI_AllowBindConfirm
  578. *
  579. * @brief Indicates when another device attempted to bind to this device
  580. *
  581. * @param
  582. *
  583. * @return none
  584. */
  585. void SAPI_AllowBindConfirm( uint16 source )
  586. {
  587. #if defined ( MT_SAPI_CB_FUNC )
  588. /* First check if MT has subscribed for this callback. If so , pass it as
  589. a event to MonitorTest and return control to calling function after that */
  590. if ( SAPICB_CHECK( SPI_CB_SAPI_ALLOW_BIND_CNF ) )
  591. {
  592. zb_MTCallbackAllowBindConfirm( source );
  593. }
  594. else
  595. #endif //MT_SAPI_CB_FUNC
  596. {
  597. zb_AllowBindConfirm( source );
  598. }
  599. }
  600. /******************************************************************************
  601. * @fn SAPI_FindDeviceConfirm
  602. *
  603. * @brief The SAPI_FindDeviceConfirm callback function is called by the
  604. * ZigBee stack when a find device operation completes.
  605. *
  606. * @param searchType - The type of search that was performed.
  607. * searchKey - Value that the search was executed on.
  608. * result - The result of the search.
  609. *
  610. * @return none
  611. */
  612. void SAPI_FindDeviceConfirm( uint8 searchType, uint8 *searchKey, uint8 *result )
  613. {
  614. #if defined ( MT_SAPI_CB_FUNC )
  615. /* First check if MT has subscribed for this callback. If so , pass it as
  616. a event to MonitorTest and return control to calling function after that */
  617. if ( SAPICB_CHECK( SPI_CB_SAPI_FIND_DEV_CNF ) )
  618. {
  619. zb_MTCallbackFindDeviceConfirm( searchType, searchKey, result );
  620. }
  621. else
  622. #endif //MT_SAPI_CB_FUNC
  623. {
  624. zb_FindDeviceConfirm( searchType, searchKey, result );
  625. }
  626. }
  627. /******************************************************************************
  628. * @fn SAPI_ReceiveDataIndication
  629. *
  630. * @brief The SAPI_ReceiveDataIndication callback function is called
  631. * asynchronously by the ZigBee stack to notify the application
  632. * when data is received from a peer device.
  633. *
  634. * @param source - The short address of the peer device that sent the data
  635. * command - The commandId associated with the data
  636. * len - The number of bytes in the pData parameter
  637. * pData - The data sent by the peer device
  638. *
  639. * @return none
  640. */
  641. void SAPI_ReceiveDataIndication( uint16 source, uint16 command, uint16 len, uint8 *pData )
  642. {
  643. #if defined ( MT_SAPI_CB_FUNC )
  644. /* First check if MT has subscribed for this callback. If so , pass it as
  645. a event to MonitorTest and return control to calling function after that */
  646. if ( SAPICB_CHECK( SPI_CB_SAPI_RCV_DATA_IND ) )
  647. {
  648. zb_MTCallbackReceiveDataIndication( source, command, len, pData );
  649. }
  650. else
  651. #endif //MT_SAPI_CB_FUNC
  652. {
  653. zb_ReceiveDataIndication( source, command, len, pData );
  654. }
  655. }
  656. /*********************************************************************
  657. * @fn SAPI_ProcessEvent
  658. *
  659. * @brief Simple API Task event processor. This function
  660. * is called to process all events for the task. Events
  661. * include timers, messages and any other user defined events.
  662. *
  663. * @param task_id - The OSAL assigned task ID.
  664. * @param events - events to process. This is a bit map and can
  665. * contain more than one event.
  666. *
  667. * @return none
  668. */
  669. UINT16 SAPI_ProcessEvent( byte task_id, UINT16 events )
  670. {
  671. osal_event_hdr_t *pMsg;
  672. afIncomingMSGPacket_t *pMSGpkt;
  673. afDataConfirm_t *pDataConfirm;
  674. if ( events & SYS_EVENT_MSG )
  675. {
  676. pMsg = (osal_event_hdr_t *) osal_msg_receive( task_id );
  677. while ( pMsg )
  678. {
  679. switch ( pMsg->event )
  680. {
  681. case ZDO_CB_MSG:
  682. SAPI_ProcessZDOMsgs( (zdoIncomingMsg_t *)pMsg );
  683. break;
  684. case AF_DATA_CONFIRM_CMD:
  685. // This message is received as a confirmation of a data packet sent.
  686. // The status is of ZStatus_t type [defined in ZComDef.h]
  687. // The message fields are defined in AF.h
  688. pDataConfirm = (afDataConfirm_t *) pMsg;
  689. SAPI_SendDataConfirm( pDataConfirm->transID, pDataConfirm->hdr.status );
  690. break;
  691. case AF_INCOMING_MSG_CMD:
  692. pMSGpkt = (afIncomingMSGPacket_t *) pMsg;
  693. SAPI_ReceiveDataIndication( pMSGpkt->srcAddr.addr.shortAddr, pMSGpkt->clusterId,
  694. pMSGpkt->cmd.DataLength, pMSGpkt->cmd.Data);
  695. break;
  696. case ZDO_STATE_CHANGE:
  697. // If the device has started up, notify the application
  698. if (pMsg->status == DEV_END_DEVICE ||
  699. pMsg->status == DEV_ROUTER ||
  700. pMsg->status == DEV_ZB_COORD )
  701. {
  702. SAPI_StartConfirm( ZB_SUCCESS );
  703. }
  704. else if (pMsg->status == DEV_HOLD ||
  705. pMsg->status == DEV_INIT)
  706. {
  707. SAPI_StartConfirm( ZB_INIT );
  708. }
  709. break;
  710. case ZDO_MATCH_DESC_RSP_SENT:
  711. SAPI_AllowBindConfirm( ((ZDO_MatchDescRspSent_t *)pMsg)->nwkAddr );
  712. break;
  713. case KEY_CHANGE:
  714. zb_HandleKeys( ((keyChange_t *)pMsg)->state, ((keyChange_t *)pMsg)->keys );
  715. break;
  716. case SAPICB_DATA_CNF:
  717. SAPI_SendDataConfirm( (uint8)((sapi_CbackEvent_t *)pMsg)->data,
  718. ((sapi_CbackEvent_t *)pMsg)->hdr.status );
  719. break;
  720. case SAPICB_BIND_CNF:
  721. SAPI_BindConfirm( ((sapi_CbackEvent_t *)pMsg)->data,
  722. ((sapi_CbackEvent_t *)pMsg)->hdr.status );
  723. break;
  724. case SAPICB_START_CNF:
  725. SAPI_StartConfirm( ((sapi_CbackEvent_t *)pMsg)->hdr.status );
  726. break;
  727. default:
  728. // User messages should be handled by user or passed to the application
  729. if ( pMsg->event >= ZB_USER_MSG )
  730. {
  731. }
  732. break;
  733. }
  734. // Release the memory
  735. osal_msg_deallocate( (uint8 *) pMsg );
  736. // Next
  737. pMsg = (osal_event_hdr_t *) osal_msg_receive( task_id );
  738. }
  739. // Return unprocessed events
  740. return (events ^ SYS_EVENT_MSG);
  741. }
  742. if ( events & ZB_ALLOW_BIND_TIMER )
  743. {
  744. afSetMatch(sapi_epDesc.simpleDesc->EndPoint, FALSE);
  745. return (events ^ ZB_ALLOW_BIND_TIMER);
  746. }
  747. if ( events & ZB_BIND_TIMER )
  748. {
  749. // Send bind confirm callback to application
  750. SAPI_BindConfirm( sapi_bindInProgress, ZB_TIMEOUT );
  751. sapi_bindInProgress = 0xffff;
  752. return (events ^ ZB_BIND_TIMER);
  753. }
  754. if ( events & ZB_ENTRY_EVENT )
  755. {
  756. uint8 startOptions;
  757. // Give indication to application of device startup
  758. zb_HandleOsalEvent( ZB_ENTRY_EVENT );
  759. // LED off cancels HOLD_AUTO_START blink set in the stack
  760. HalLedSet (HAL_LED_4, HAL_LED_MODE_OFF);
  761. zb_ReadConfiguration( ZCD_NV_STARTUP_OPTION, sizeof(uint8), &startOptions );
  762. if ( startOptions & ZCD_STARTOPT_AUTO_START )
  763. {
  764. zb_StartRequest();
  765. }
  766. else
  767. {
  768. // blink leds and wait for external input to config and restart
  769. HalLedBlink(HAL_LED_2, 0, 50, 500);
  770. }
  771. return (events ^ ZB_ENTRY_EVENT );
  772. }
  773. // This must be the last event to be processed
  774. if ( events & ( ZB_USER_EVENTS ) )
  775. {
  776. // User events are passed to the application
  777. zb_HandleOsalEvent( events );
  778. // Do not return here, return 0 later
  779. }
  780. // Discard unknown events
  781. return 0;
  782. }
  783. /*********************************************************************
  784. * @fn SAPI_ProcessZDOMsgs()
  785. *
  786. * @brief Process response messages
  787. *
  788. * @param none
  789. *
  790. * @return none
  791. */
  792. void SAPI_ProcessZDOMsgs( zdoIncomingMsg_t *inMsg )
  793. {
  794. switch ( inMsg->clusterID )
  795. {
  796. case NWK_addr_rsp:
  797. {
  798. // Send find device callback to application
  799. ZDO_NwkIEEEAddrResp_t *pNwkAddrRsp = ZDO_ParseAddrRsp( inMsg );
  800. SAPI_FindDeviceConfirm( ZB_IEEE_SEARCH, (uint8*)&pNwkAddrRsp->nwkAddr, pNwkAddrRsp->extAddr );
  801. }
  802. break;
  803. case Match_Desc_rsp:
  804. {
  805. zAddrType_t dstAddr;
  806. ZDO_ActiveEndpointRsp_t *pRsp = ZDO_ParseEPListRsp( inMsg );
  807. if ( sapi_bindInProgress != 0xffff )
  808. {
  809. // Create a binding table entry
  810. dstAddr.addrMode = Addr16Bit;
  811. dstAddr.addr.shortAddr = pRsp->nwkAddr;
  812. if ( APSME_BindRequest( sapi_epDesc.simpleDesc->EndPoint,
  813. sapi_bindInProgress, &dstAddr, pRsp->epList[0] ) == ZSuccess )
  814. {
  815. osal_stop_timerEx(sapi_TaskID, ZB_BIND_TIMER);
  816. osal_start_timerEx( ZDAppTaskID, ZDO_NWK_UPDATE_NV, 250 );
  817. // Find IEEE addr
  818. ZDP_IEEEAddrReq( pRsp->nwkAddr, ZDP_ADDR_REQTYPE_SINGLE, 0, 0 );
  819. // Send bind confirm callback to application
  820. zb_BindConfirm( sapi_bindInProgress, ZB_SUCCESS );
  821. sapi_bindInProgress = 0xffff;
  822. }
  823. }
  824. }
  825. break;
  826. }
  827. }
  828. /*********************************************************************
  829. * @fn SAPI_Init
  830. *
  831. * @brief Initialization function for the Simple API Task.
  832. * This is called during initialization and should contain
  833. * any application specific initialization (ie. hardware
  834. * initialization/setup, table initialization, power up
  835. * notification ... ).
  836. *
  837. * @param task_id - the ID assigned by OSAL. This ID should be
  838. * used to send messages and set timers.
  839. *
  840. * @return none
  841. */
  842. void SAPI_Init( byte task_id )
  843. {
  844. uint8 startOptions;
  845. sapi_TaskID = task_id;
  846. sapi_bindInProgress = 0xffff;
  847. sapi_epDesc.endPoint = zb_SimpleDesc.EndPoint;
  848. sapi_epDesc.task_id = &sapi_TaskID;
  849. sapi_epDesc.simpleDesc = (SimpleDescriptionFormat_t *)&zb_SimpleDesc;
  850. sapi_epDesc.latencyReq = noLatencyReqs;
  851. // Register the endpoint/interface description with the AF
  852. afRegister( &sapi_epDesc );
  853. // Turn off match descriptor response by default
  854. afSetMatch(sapi_epDesc.simpleDesc->EndPoint, FALSE);
  855. // Register callback evetns from the ZDApp
  856. ZDO_RegisterForZDOMsg( sapi_TaskID, NWK_addr_rsp );
  857. ZDO_RegisterForZDOMsg( sapi_TaskID, Match_Desc_rsp );
  858. #if (defined HAL_KEY) && (HAL_KEY == TRUE)
  859. // Register for HAL events
  860. RegisterForKeys( sapi_TaskID );
  861. if ( HalKeyRead () == HAL_KEY_SW_5)
  862. {
  863. // If SW5 is pressed and held while powerup, force auto-start and nv-restore off and reset
  864. startOptions = ZCD_STARTOPT_CLEAR_STATE | ZCD_STARTOPT_CLEAR_CONFIG;
  865. zb_WriteConfiguration( ZCD_NV_STARTUP_OPTION, sizeof(uint8), &startOptions );
  866. zb_SystemReset();
  867. }
  868. #endif // HAL_KEY
  869. // Set an event to start the application
  870. osal_set_event(task_id, ZB_ENTRY_EVENT);
  871. }
  872. /*********************************************************************
  873. * @fn SAPI_SendCback
  874. *
  875. * @brief Sends a message to the sapi task ( itself ) so that a
  876. * callback can be generated later.
  877. *
  878. * @return none
  879. */
  880. void SAPI_SendCback( uint8 event, uint8 status, uint16 data )
  881. {
  882. sapi_CbackEvent_t *pMsg;
  883. pMsg = (sapi_CbackEvent_t *)osal_msg_allocate( sizeof(sapi_CbackEvent_t) );
  884. if( pMsg )
  885. {
  886. pMsg->hdr.event = event;
  887. pMsg->hdr.status = status;
  888. pMsg->data = data;
  889. osal_msg_send( sapi_TaskID, (uint8 *)pMsg );
  890. }
  891. }
  892. /*********************************************************************
  893. * @fn osalInitTasks
  894. *
  895. * @brief This function invokes the initialization function for each task.
  896. *
  897. * @param void
  898. *
  899. * @return none
  900. */
  901. void osalInitTasks( void )
  902. {
  903. uint8 taskID = 0;
  904. tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);
  905. osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));
  906. macTaskInit( taskID++ );
  907. nwk_init( taskID++ );
  908. Hal_Init( taskID++ );
  909. #if defined( MT_TASK )
  910. MT_TaskInit( taskID++ );
  911. #endif
  912. APS_Init( taskID++ );
  913. ZDApp_Init( taskID++ );
  914. SAPI_Init( taskID );
  915. }
  916. /*********************************************************************
  917. *********************************************************************/