sapi.c 33 KB

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