oad_app.c 59 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890
  1. /**************************************************************************************************
  2. Filename: oad_app.c
  3. Revised: $Date: 2011-05-16 10:25:15 -0700 (Mon, 16 May 2011) $
  4. Revision: $Revision: 25990 $
  5. Description: This file contains the implementation of an Over Air Download application.
  6. Copyright 2008-2011 Texas Instruments Incorporated. All rights reserved.
  7. IMPORTANT: Your use of this Software is limited to those specific rights
  8. granted under the terms of a software license agreement between the user
  9. who downloaded the software, his/her employer (which must be your employer)
  10. and Texas Instruments Incorporated (the "License"). You may not use this
  11. Software unless you agree to abide by the terms of the License. The License
  12. limits your use, and you acknowledge, that the Software may not be modified,
  13. copied or distributed unless embedded on a Texas Instruments microcontroller
  14. or used solely and exclusively in conjunction with a Texas Instruments radio
  15. frequency transceiver, which is integrated into your product. Other than for
  16. the foregoing purpose, you may not use, reproduce, copy, prepare derivative
  17. works of, modify, distribute, perform, display or sell this Software and/or
  18. its documentation for any purpose.
  19. YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
  20. PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
  21. INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
  22. NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
  23. TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
  24. NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
  25. LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
  26. INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
  27. OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
  28. OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
  29. (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
  30. Should you have any questions regarding your right to use this Software,
  31. contact Texas Instruments Incorporated at www.TI.com.
  32. **************************************************************************************************/
  33. /* ------------------------------------------------------------------------------------------------
  34. * Includes
  35. * ------------------------------------------------------------------------------------------------
  36. */
  37. #include <string.h>
  38. #include "AF.h"
  39. #include "hal_adc.h"
  40. #include "hal_board_cfg.h"
  41. #include "hal_flash.h"
  42. #include "hal_oad.h"
  43. #include "oad_app.h"
  44. #include "oad_preamble.h"
  45. #include "OnBoard.h"
  46. #include "OSAL_Nv.h"
  47. #if defined ZPORT
  48. #include "hal_key.h"
  49. #include "MT.h"
  50. #include "MT_APP.h"
  51. #include "MT_X.h"
  52. #include "ZDApp.h"
  53. #else
  54. #if (HAL_OAD_XNV_IS_INT && ((HAL_OAD_DL_OSET % HAL_FLASH_PAGE_SIZE) != 0))
  55. #include "hal_xnv.h"
  56. #endif
  57. #endif
  58. /* ------------------------------------------------------------------------------------------------
  59. * Macros
  60. * ------------------------------------------------------------------------------------------------
  61. */
  62. #define DO_EVENT_CALLBACK(e) st ( if (s_pCallback && ((e) & s_eventMask)) s_pCallback((e)); )
  63. /* ------------------------------------------------------------------------------------------------
  64. * Constants
  65. * ------------------------------------------------------------------------------------------------
  66. */
  67. #if !defined OAD_NV_ID
  68. // Arbitrarily pick the last Id available to the user Application.
  69. #define OAD_NV_ID 0x0FFF
  70. #endif
  71. #define PREAMBLE_NV_ID OAD_NV_ID
  72. // support to select callback event for which subscription is desired
  73. // this information is transmitted as a bit map.
  74. #define ZLCB_EVENT_OADBEGIN_CLIENT ((uint16)0x0001)
  75. #define ZLCB_EVENT_OADEND_CLIENT ((uint16)0x0002)
  76. #define ZLCB_EVENT_OADBEGIN_SERVER ((uint16)0x0004)
  77. #define ZLCB_EVENT_OADEND_SERVER ((uint16)0x0008)
  78. #define ZLCB_EVENT_CODE_ENABLE_RESET ((uint16)0x0010)
  79. #define ZLCB_EVENT_ALL (ZLCB_EVENT_OADBEGIN_CLIENT | \
  80. ZLCB_EVENT_OADEND_CLIENT | \
  81. ZLCB_EVENT_OADBEGIN_SERVER | \
  82. ZLCB_EVENT_OADEND_SERVER | \
  83. ZLCB_EVENT_CODE_ENABLE_RESET \
  84. )
  85. #define SDC_RETRY_COUNT (10)
  86. #define SDR_WAIT_TO (1000)
  87. // Some reasonable time to get the code enable response out.
  88. #define SDC_WAIT_TO_ENABLE (10000)
  89. /* ------------------------------------------------------------------------------------------------
  90. * Typedefs
  91. * ------------------------------------------------------------------------------------------------
  92. */
  93. #if defined ZPORT
  94. #define SIZEOF_ZAIN_HDR (sizeof(uint16) + sizeof(uint8) + sizeof(uint16) + sizeof(uint8))
  95. // Z-Architect headers
  96. // inbound to host (from dongle directly or external platform)
  97. PACK_1
  98. typedef struct {
  99. uint16 zaproxy_nwkAddr;
  100. uint8 zaproxy_endp;
  101. uint16 zaproxy_ClusterID;
  102. uint8 zaproxy_msglen;
  103. uint8 zaproxy_payload[1];
  104. } zahdrin_t;
  105. // outbound from host (to dongle directly or external platform)
  106. PACK_1
  107. typedef struct {
  108. uint16 zaproxy_nwkAddr;
  109. uint8 zaproxy_endp;
  110. uint16 zaproxy_ClusterID;
  111. uint8 zaproxy_msglen;
  112. uint8 zaproxy_payload[1];
  113. } zahdrout_t;
  114. #endif
  115. /* ------------------------------------------------------------------------------------------------
  116. * Global Variables
  117. * ------------------------------------------------------------------------------------------------
  118. */
  119. uint8 oad_app_taskId;
  120. /* ------------------------------------------------------------------------------------------------
  121. * Global Functions
  122. * ------------------------------------------------------------------------------------------------
  123. */
  124. #if defined ZPORT
  125. #define HalOADChkDL(V) 1
  126. #define HalOADInvRC(V)
  127. #define HalOADAvail(V) HAL_OAD_DL_SIZE
  128. #define HalOADRead(A, B, C, D)
  129. #define HalOADWrite(A, B, C, D)
  130. #endif
  131. /* ------------------------------------------------------------------------------------------------
  132. * Local Variables
  133. * ------------------------------------------------------------------------------------------------
  134. */
  135. static uint8 transId;
  136. static afAddrType_t dstAddr;
  137. static zlclientC_t *s_clientInfo;
  138. static uint8 s_State, s_SessionID, s_blkSize;
  139. static uint16 s_NextPacket, s_NumPktGet, s_SDCRetryCount;
  140. static zlmhdr_t *s_sdcmd;
  141. static zlsdC_t *s_sdcpayload;
  142. static zlmhdr_t *s_sdreply;
  143. #if !defined ZPORT
  144. static zlsdR_t *s_sdrpayload;
  145. static image_t s_itype;
  146. static uint8 s_lastSeen, s_firstTx = 1;
  147. #endif
  148. static void (*s_pCallback)(uint16);
  149. static uint16 s_eventMask;
  150. static uint8 s_lastTxSeqNum;
  151. #if defined ZPORT
  152. static uint8 s_serialMsg;
  153. static uint16 s_lastSeqNum;
  154. static uint16 s_myNwkAddr = 0xFFFE;
  155. // pass through stuff
  156. static uint8 s_PTSeqNum;
  157. static afIncomingMSGPacket_t s_PTClientInfo;
  158. #else
  159. #pragma location="PREAMBLE"
  160. const CODE preamble_t _preamble = {
  161. {PREAMBLE_MAGIC1, PREAMBLE_MAGIC2},
  162. HAL_OAD_DL_SIZE,
  163. HAL_OAD_VERS,
  164. HAL_OAD_MANU,
  165. HAL_OAD_PROD
  166. };
  167. #pragma required=_preamble
  168. #endif
  169. // This list should be filled with Application specific Cluster IDs.
  170. static const cId_t OAD_ClusterList[OAD_CLUSTER_CNT] =
  171. {
  172. OAD_CLUSTERID_CS
  173. //,OAD_CLUSTERID_EM
  174. };
  175. static const SimpleDescriptionFormat_t OAD_SimpleDesc =
  176. {
  177. OAD_ENDPOINT,
  178. OAD_PROFILE_ID,
  179. OAD_DEVICEID,
  180. OAD_DEVICE_VERSION,
  181. OAD_FLAGS,
  182. OAD_CLUSTER_CNT,
  183. (cId_t *)OAD_ClusterList,
  184. 0,
  185. NULL
  186. };
  187. static const endPointDesc_t OAD_epDesc=
  188. {
  189. OAD_ENDPOINT,
  190. &oad_app_taskId,
  191. (SimpleDescriptionFormat_t *)&OAD_SimpleDesc,
  192. noLatencyReqs,
  193. };
  194. #if defined HAL_OAD_BL21
  195. // this is the mailbox value that tells the boot code to flash the downloaded image
  196. // even though the operational image may be sane.
  197. #define MBOX_OAD_ENABLE 0x454E424C // 'ENBL' enable downloaded code
  198. PACK_1
  199. typedef struct mbox_s {
  200. volatile unsigned long BootRead;
  201. volatile unsigned long AppRead;
  202. } mboxMsg_t;
  203. #pragma location="MBOXMSG_ADDR"
  204. __no_init mboxMsg_t mboxMsg;
  205. PACK_1
  206. typedef struct {
  207. uint8 (*ReadFlash)(image_t, uint32 addr, uint8 *pBuf, uint16 len);
  208. uint8 (*WriteFlash)(image_t, uint32 addr, uint8 *pBuf, uint16 len);
  209. uint8 (*CheckCodeSanity)(image_t, uint32 addr1, uint32 addr2);
  210. uint8 (*GetPreamble)(image_t, uint32 addr, preamble_t *pBuf);
  211. } mbox_t;
  212. #pragma location="MBOX_ADDR"
  213. __no_init mbox_t mbox;
  214. #endif
  215. /* ------------------------------------------------------------------------------------------------
  216. * Local Functions
  217. * ------------------------------------------------------------------------------------------------
  218. */
  219. static void procSysEvtMsg(void);
  220. static void zlResetState(void);
  221. static void ZLOADApp_MessageMSGCB( afIncomingMSGPacket_t * );
  222. static void ZLOADApp_handleCommand(afIncomingMSGPacket_t *, zlmhdr_t *);
  223. static void ZLOADApp_handleReply(afIncomingMSGPacket_t *, zlmhdr_t *);
  224. static void zlCleanupOnReset(void);
  225. static void zlStartClientSession(void);
  226. static void zlProcessSDR(zlsdR_t *);
  227. static void zlRequestNextDataPacket(void);
  228. static void zlCleanupOnXferDone(void);
  229. static void zlResendSDC(void);
  230. #if defined ZPORT
  231. static void zlSendSerial(uint8 *, uint8);
  232. static void ZLOADApp_SerialMessageMSGCB(zahdrout_t *);
  233. static void zlZArchitectProxyMsg(zahdrout_t *);
  234. static uint8 zlPassOnStartSessionOK(uint8 *);
  235. static zahdrin_t *zlBuildExternalInboundSerialMSG(afIncomingMSGPacket_t *, uint8 *, uint8);
  236. static zahdrin_t *zlBuildInternalInboundSerialMSG(uint8 *, uint8);
  237. static void zlHandleKeys(uint8 shift, uint8 keys);
  238. #else
  239. static uint8 zlSendCommand(uint8, uint8 *);
  240. static void zlProcessSDC(zlsdC_t *);
  241. static uint8 zlIsReqPacketNumOK(uint16);
  242. #if (HAL_OAD_XNV_IS_INT && ((HAL_OAD_DL_OSET % HAL_FLASH_PAGE_SIZE) != 0))
  243. static Status_t zlEraseHalfPage(void);
  244. #endif
  245. #endif
  246. /**************************************************************************************************
  247. * @fn oadAppInit
  248. *
  249. * @brief This function is called by OSAL system startup.
  250. *
  251. * input parameters
  252. *
  253. * @param id - The Task ID assigned by OSAL.
  254. *
  255. * output parameters
  256. *
  257. * None.
  258. *
  259. * @return None.
  260. **************************************************************************************************
  261. */
  262. void oadAppInit(uint8 id)
  263. {
  264. oad_app_taskId = id;
  265. afRegister((endPointDesc_t *)&OAD_epDesc);
  266. s_State = ZLSTATE_IDLE;
  267. id = PREAMBLE_OFFSET;
  268. osal_nv_item_init(PREAMBLE_NV_ID, 1, &id);
  269. #if defined HAL_OAD_BL21
  270. mboxMsg.BootRead = 0;
  271. #endif
  272. #if defined ZPORT
  273. // Register for all key events - This app will handle all key events
  274. RegisterForKeys(oad_app_taskId);
  275. mtxMode = TRUE;
  276. #endif
  277. }
  278. /**************************************************************************************************
  279. * @fn oadAppEvt
  280. *
  281. * @brief This function is called to process the OSAL events for the task.
  282. *
  283. * input parameters
  284. *
  285. * @param id - The Task ID assigned by OSAL.
  286. * @param evts - A bit mask representing the OSAL events that are pending for this task.
  287. *
  288. * output parameters
  289. *
  290. * None.
  291. *
  292. * @return None.
  293. **************************************************************************************************
  294. */
  295. uint16 oadAppEvt(uint8 id, uint16 evts)
  296. {
  297. uint16 mask = 0;
  298. (void)id;
  299. if (evts & SYS_EVENT_MSG)
  300. {
  301. mask = SYS_EVENT_MSG;
  302. procSysEvtMsg();
  303. }
  304. else if (evts & ZLOAD_CODE_ENABLE_EVT)
  305. {
  306. // let the user shut down the environment if requested
  307. DO_EVENT_CALLBACK(ZLCB_EVENT_CODE_ENABLE_RESET);
  308. #if defined HAL_OAD_BL21
  309. // Set up mail box to tell the pre-2.2 boot code to flash the downloaded image.
  310. mboxMsg.BootRead = MBOX_OAD_ENABLE;
  311. #else
  312. HalOADInvRC();
  313. #endif
  314. SystemReset();
  315. }
  316. else if (evts & ZLOAD_IS_CLIENT_EVT)
  317. {
  318. mask = ZLOAD_IS_CLIENT_EVT;
  319. zlStartClientSession();
  320. }
  321. else if (evts & ZLOAD_XFER_DONE_EVT)
  322. {
  323. mask = ZLOAD_XFER_DONE_EVT;
  324. zlCleanupOnXferDone();
  325. }
  326. else if (evts & ZLOAD_RESET_EVT)
  327. {
  328. mask = ZLOAD_RESET_EVT;
  329. zlCleanupOnReset();
  330. }
  331. else if (evts & ZLOAD_SDRTIMER_EVT)
  332. {
  333. mask = ZLOAD_SDRTIMER_EVT;
  334. zlResendSDC();
  335. }
  336. else if (evts & ZLOAD_RESET_BOARD_EVT)
  337. {
  338. SystemResetSoft();
  339. }
  340. else
  341. {
  342. mask = evts; // Discard unknown events - should never happen.
  343. }
  344. return (evts ^ mask); // Return unprocessed events.
  345. }
  346. /**************************************************************************************************
  347. * @fn procSysEvtMsg
  348. *
  349. * @brief This function is called by oadAppEvt() to process all of the pending OSAL messages.
  350. *
  351. * input parameters
  352. *
  353. * None.
  354. *
  355. * output parameters
  356. *
  357. * None.
  358. *
  359. * @return None.
  360. **************************************************************************************************
  361. */
  362. static void procSysEvtMsg(void)
  363. {
  364. uint8 *msgPtr;
  365. while ((msgPtr = osal_msg_receive(oad_app_taskId)))
  366. {
  367. #if defined ZPORT
  368. s_serialMsg = 0;
  369. #endif
  370. switch ( *msgPtr )
  371. {
  372. case MT_SYS_APP_MSG:
  373. case MT_SYS_APP_RSP_MSG:
  374. #if defined ZPORT
  375. // This is how we get messages from a Host application (ZOAD.exe).
  376. s_serialMsg = 1;
  377. ZLOADApp_SerialMessageMSGCB((zahdrout_t *)(((mtSysAppMsg_t *)msgPtr)->appData));
  378. #endif
  379. break;
  380. case AF_DATA_CONFIRM_CMD:
  381. break;
  382. case AF_INCOMING_MSG_CMD:
  383. ZLOADApp_MessageMSGCB((afIncomingMSGPacket_t *)msgPtr);
  384. break;
  385. #if defined ZPORT
  386. case KEY_CHANGE:
  387. zlHandleKeys(((keyChange_t *)msgPtr)->state, ((keyChange_t *)msgPtr)->keys);
  388. break;
  389. #endif
  390. case ZDO_NEW_DSTADDR:
  391. /*
  392. dstEP = msgPtr[1];
  393. dstAddr = (zAddrType_t *)&msgPtr[2];
  394. dstAddr.addrMode = dstAddr->addrMode;
  395. dstAddr.endPoint = dstEP;
  396. if (dstAddr->addrMode == afAddr16Bit)
  397. dstAddr.addr.shortAddr = dstAddr->addr.shortAddr;
  398. else
  399. osal_memcpy(dstAddr.addr.extAddr, dstAddr->addr.extAddr, Z_EXTADDR_LEN);
  400. */
  401. break;
  402. case ZDO_STATE_CHANGE:
  403. #if defined ZPORT
  404. if (((devStates_t)(((osal_event_hdr_t *)msgPtr)->status) == DEV_END_DEVICE_UNAUTH) ||
  405. ((devStates_t)(((osal_event_hdr_t *)msgPtr)->status) == DEV_END_DEVICE))
  406. {
  407. MT_X_FakeNwkJoinCnf();
  408. }
  409. #endif
  410. break;
  411. default:
  412. break;
  413. }
  414. osal_msg_deallocate(msgPtr); // Receiving task is responsible for releasing the memory.
  415. }
  416. }
  417. /**********************************************************************************
  418. * @fn ZLOADApp_MessageMSGCB
  419. *
  420. * @brief Handle a normal ZLOAD command or reply. Forward it to proper handler
  421. *
  422. * @param MSGpkt - pointer to incoming AF packet
  423. *
  424. * @return none
  425. */
  426. static void ZLOADApp_MessageMSGCB(afIncomingMSGPacket_t *MSGpkt)
  427. {
  428. zlmhdr_t *inMsg = (zlmhdr_t *)MSGpkt->cmd.Data;
  429. if (inMsg->zlhdr_msgid & ZLMSGID_REPLY_BIT)
  430. {
  431. ZLOADApp_handleReply(MSGpkt, inMsg);
  432. }
  433. else
  434. {
  435. ZLOADApp_handleCommand(MSGpkt, inMsg);
  436. }
  437. return;
  438. }
  439. /**********************************************************************************
  440. * @fn ZLOADApp_handleCommand
  441. *
  442. * @brief Handle a normal ZLOAD command
  443. *
  444. * @param input
  445. * MSGpkt pointer to incoming AF packet. needed to get
  446. * reply address info
  447. * msg pointer to ZLOAD message
  448. *
  449. * @return none
  450. */
  451. static void ZLOADApp_handleCommand(afIncomingMSGPacket_t *MSGpkt, zlmhdr_t *msg)
  452. {
  453. uint8 *cpc, *cpr, paylSize;
  454. preamble_t preamble;
  455. #if defined ZPORT
  456. static uint8 *buf;
  457. if (!buf)
  458. {
  459. if (!(buf = osal_mem_alloc(sizeof(zlmhdr_t) + sizeof(zlreply_t))))
  460. {
  461. return;
  462. }
  463. }
  464. #else
  465. uint8 *buf = NULL;
  466. // allocate the reply buffer. use a union of the replies -- they're all pretty
  467. // small -- except for Send Data. that one is preallocated because we want
  468. // to really have it and not spend time doing malloc/free for so many transactions
  469. // besides, we don't want a malloc() to fail during the transfer.
  470. if (msg->zlhdr_msgid != ZLMSGID_SEND_DATA)
  471. {
  472. if (!(buf = osal_mem_alloc(sizeof(zlmhdr_t) + sizeof(zlreply_t))))
  473. {
  474. return;
  475. }
  476. }
  477. else
  478. {
  479. // make sure we don't have a premature send-data command. this is awkward because
  480. // in the normal case we've done a "static" allocation (for the durtion of the session)
  481. // to prevent thousands of alloc/free calls or a failed alloc. but now, we dont' have
  482. // that "static" memory yet.
  483. if (s_State != ZLSTATE_SERVER)
  484. {
  485. // uh oh. we never got a start session. now we need memory to
  486. // send the reply
  487. if (!(buf = osal_mem_alloc(sizeof(zlmhdr_t) + sizeof(zlsdR_t))))
  488. {
  489. return;
  490. }
  491. // make the rest of the code work
  492. s_sdreply = (zlmhdr_t *)buf;
  493. s_sdreply->zlhdr_msgid = ZLMSGID_SEND_DATA | ZLMSGID_REPLY_BIT;
  494. s_sdreply->zlhdr_msglen = sizeof(zlsdR_t);
  495. s_sdrpayload = (zlsdR_t *)(buf+sizeof(zlmhdr_t));
  496. s_sdrpayload->zlsdR_state = s_State;
  497. s_sdrpayload->zlsdR_errorCode = EC_SD_NOT_SERVER;
  498. }
  499. }
  500. #endif
  501. cpr = buf + sizeof(zlmhdr_t); // offset of reply payload
  502. cpc = (uint8 *)msg + sizeof(zlmhdr_t); // offset of command payload
  503. switch (msg->zlhdr_msgid) {
  504. case ZLMSGID_STATUSQ:
  505. {
  506. uint8 dlImagePreambleOffset;
  507. zlstatusR_t *reply = (zlstatusR_t *)cpr;
  508. paylSize = sizeof(zlstatusR_t);
  509. reply->zlsqR_state = s_State;
  510. reply->zlsqR_errorCode = EC_NO_ERROR;
  511. // report capabiltities and version
  512. reply->zlsqR_ProtocolVersion = ZLOAD_PROTOCOL_VERSION;
  513. reply->zlsqR_capabilties = ZLOAD_CAPABILTIES;
  514. cpr +=4;
  515. // populate the operational version values
  516. HalOADRead(PREAMBLE_OFFSET, (uint8 *)&preamble, sizeof(preamble_t), HAL_OAD_RC);
  517. cpr = osal_memcpy(cpr, &preamble.vers, ZL_IMAGE_ID_LENGTH);
  518. // do downloaded image if it's there
  519. osal_nv_read(PREAMBLE_NV_ID, 0, 1, &dlImagePreambleOffset);
  520. HalOADRead(dlImagePreambleOffset, (uint8 *)&preamble, sizeof(preamble_t), HAL_OAD_DL);
  521. if (preamble.vers != 0xFF)
  522. {
  523. cpr = osal_memcpy(cpr, &preamble.vers, ZL_IMAGE_ID_LENGTH);
  524. }
  525. else
  526. {
  527. osal_memset(cpr, 0, ZL_IMAGE_ID_LENGTH);
  528. cpr += ZL_IMAGE_ID_LENGTH;
  529. }
  530. cpr = osal_memcpy(cpr, &s_NextPacket, sizeof(s_NextPacket));
  531. osal_memcpy(cpr, &s_NumPktGet, sizeof(s_NumPktGet));
  532. }
  533. break;
  534. case ZLMSGID_SESSION_START:
  535. #if defined ZPORT
  536. // the pass through condition starts here, when a client tries
  537. // to begin a session with the dongle.
  538. if (s_State != ZLSTATE_IDLE) {
  539. ((zlbegsessR_t *)cpr)->zlbsR_errorCode = EC_BS_NOT_IDLE;
  540. }
  541. else if (s_serialMsg) {
  542. // somehow this came over the serial port and it isn't legal
  543. ((zlbegsessR_t *)cpr)->zlbsR_errorCode = EC_BS_NOT_SERVER;
  544. }
  545. else {
  546. // set mode. delay reply until we hear back from the Host
  547. s_PTSeqNum = msg->zlhdr_seqnum;
  548. s_PTClientInfo = *MSGpkt;
  549. s_SessionID = ((zlbegsessC_t *)cpc)->zlbsC_sessionID;
  550. if (zlPassOnStartSessionOK((uint8 *)msg)) {
  551. s_State = ZLSTATE_PASS_THROUGH;
  552. return;
  553. }
  554. else {
  555. ((zlbegsessR_t *)cpr)->zlbsR_errorCode = EC_BS_NO_MEM;
  556. }
  557. }
  558. #else
  559. if (!HalAdcCheckVdd(VDD_MIN_OAD))
  560. {
  561. ((zlbegsessR_t *)cpr)->zlbsR_errorCode = EC_BAD_VDD;
  562. }
  563. else
  564. do {
  565. uint8 dlImagePreambleOffset;
  566. zlbegsessR_t *reply = (zlbegsessR_t *)cpr;
  567. // assume we're OK and set up fixed part of reply here
  568. reply->zlbsR_blkSize = ZL_DATA_BLK_SIZE;
  569. reply->zlbsR_numBlks = ZL_NUM_DATA_BLKS;
  570. reply->zlbsR_state = s_State;
  571. reply->zlbsR_errorCode = EC_NO_ERROR;
  572. paylSize = sizeof(zlbegsessR_t);
  573. if (s_State != ZLSTATE_IDLE) {
  574. if (s_SessionID == ((zlbegsessC_t *)cpc)->zlbsC_sessionID)
  575. {
  576. // Ok - this must be a no ack retransmit or a retry.
  577. }
  578. else
  579. {
  580. reply->zlbsR_errorCode = EC_BS_NOT_IDLE;
  581. continue; // done
  582. }
  583. }
  584. // see if there is a DL image to send
  585. osal_nv_read(PREAMBLE_NV_ID, 0, 1, &dlImagePreambleOffset);
  586. HalOADRead(dlImagePreambleOffset, (uint8 *)&preamble, sizeof(preamble_t), HAL_OAD_DL);
  587. if (preamble.vers != 0xFFFF)
  588. {
  589. if (!memcmp(cpc, (uint8 *)&preamble.vers, ZL_IMAGE_ID_LENGTH)) {
  590. // image matches request.
  591. osal_memcpy(&reply->zlbsR_imgLen, &preamble.len, sizeof(uint32));
  592. s_State = ZLSTATE_SERVER;
  593. s_itype = HAL_OAD_DL;
  594. reply->zlbsR_preambleOffset = (uint8)PREAMBLE_OFFSET;
  595. continue; // done
  596. }
  597. }
  598. // no DL image. we know there's an operational image
  599. HalOADRead(PREAMBLE_OFFSET, (uint8 *)&preamble, sizeof(preamble_t), HAL_OAD_RC);
  600. if (!memcmp(cpc, (uint8 *)&preamble.vers, ZL_IMAGE_ID_LENGTH)) {
  601. // image matches request.
  602. osal_memcpy(&reply->zlbsR_imgLen, &preamble.len, sizeof(uint32));
  603. s_State = ZLSTATE_SERVER;
  604. s_itype = HAL_OAD_RC;
  605. reply->zlbsR_preambleOffset = (uint8)PREAMBLE_OFFSET;
  606. }
  607. else {
  608. reply->zlbsR_errorCode = EC_BS_NO_MATCHES;
  609. }
  610. } while (0);
  611. // if we're good to go, allocate the memory for the SD replies
  612. // this will make things more efficient during the transfer
  613. if (!((zlbegsessR_t *)cpr)->zlbsR_errorCode) {
  614. uint8 *cp;
  615. zlbegsessR_t *reply = (zlbegsessR_t *)cpr;
  616. // need memory for sending replies and for holding flash pages
  617. if (!(cp=osal_mem_alloc(sizeof(zlmhdr_t)+sizeof(zlsdR_t)))) {
  618. // oops -- none available. let Client decide what to do.
  619. s_State = ZLSTATE_IDLE;
  620. reply->zlbsR_errorCode = EC_BS_NO_MEM;
  621. }
  622. else {
  623. s_NumPktGet = (preamble.len + (ZL_DATA_BLK_SIZE*ZL_NUM_DATA_BLKS-1)) /
  624. (ZL_DATA_BLK_SIZE*ZL_NUM_DATA_BLKS);
  625. s_blkSize = ZL_DATA_BLK_SIZE * ZL_NUM_DATA_BLKS;
  626. s_NextPacket = 0;
  627. s_SessionID = ((zlbegsessC_t *)cpc)->zlbsC_sessionID;
  628. // set up other pointers
  629. s_sdreply = (zlmhdr_t *)cp;
  630. s_sdreply->zlhdr_msgid = ZLMSGID_SEND_DATA | ZLMSGID_REPLY_BIT;
  631. s_sdreply->zlhdr_msglen = sizeof(zlsdR_t);
  632. s_sdrpayload = (zlsdR_t *)(cp+sizeof(zlmhdr_t));
  633. DO_EVENT_CALLBACK(ZLCB_EVENT_OADBEGIN_SERVER);
  634. }
  635. }
  636. #endif
  637. break;
  638. case ZLMSGID_SESSION_TERM:
  639. {
  640. zlendsessR_t *reply = (zlendsessR_t *)cpr;
  641. reply->zlesR_state = s_State;
  642. reply->zlesR_errorCode = EC_NO_ERROR;
  643. // guard against terminating the wrong session
  644. if (((zlendsessC_t *)cpc)->zlesC_sessionID != s_SessionID) {
  645. // wrong session ID
  646. reply->zlesR_errorCode = EC_ES_BAD_SESS_ID;
  647. }
  648. #if defined ZPORT
  649. else if (s_serialMsg) {
  650. // somehow this came over the serial port and it isn't legal
  651. ((zlbegsessR_t *)cpr)->zlbsR_errorCode = EC_ES_NOT_SERVER;
  652. }
  653. #endif
  654. else {
  655. #if defined ZPORT
  656. if (ZLSTATE_PASS_THROUGH == s_State) {
  657. // everything is OK. pass this up to host if we're in pass-through mode
  658. // forward message to host
  659. zahdrin_t *zain = zlBuildExternalInboundSerialMSG(&s_PTClientInfo, (uint8 *)msg, sizeof(zlmhdr_t) + sizeof(zlendsessC_t));
  660. if (zain) {
  661. if (SUCCESS != osal_start_timerEx(oad_app_taskId, ZLOAD_XFER_DONE_EVT, SDR_WAIT_TO))
  662. {
  663. osal_set_event(oad_app_taskId, ZLOAD_XFER_DONE_EVT);
  664. }
  665. s_PTClientInfo = *MSGpkt;
  666. zlSendSerial((uint8 *)zain, SIZEOF_ZAIN_HDR + sizeof(zlmhdr_t) + sizeof(zlendsessC_t));
  667. osal_mem_free(zain);
  668. return;
  669. }
  670. else {
  671. reply->zlesR_errorCode = EC_ES_NO_MEM;
  672. }
  673. }
  674. #else
  675. if (s_State == ZLSTATE_SERVER) {
  676. // everything is OK.
  677. osal_set_event(oad_app_taskId, ZLOAD_XFER_DONE_EVT);
  678. }
  679. #endif
  680. else {
  681. // right session ID but I'm not the server
  682. reply->zlesR_errorCode = EC_ES_NOT_SERVER;
  683. }
  684. }
  685. }
  686. paylSize = sizeof(zlendsessR_t);
  687. break;
  688. case ZLMSGID_CLIENT_CMD:
  689. {
  690. zlclientR_t *reply = (zlclientR_t *)cpr;
  691. reply->zlclR_errorCode = EC_NO_ERROR;
  692. paylSize = sizeof(zlclientR_t);
  693. reply->zlclR_state = s_State;
  694. #if defined ZPORT
  695. // we can be the client only if the dongle code itself is being updated
  696. // and then only if the Host is the server
  697. if (!s_serialMsg) {
  698. reply->zlclR_errorCode = EC_CL_NOT_CLIENT;
  699. }
  700. else
  701. #endif
  702. if (!HalAdcCheckVdd(VDD_MIN_OAD))
  703. {
  704. reply->zlclR_errorCode = EC_BAD_VDD;
  705. }
  706. else
  707. if (s_State != ZLSTATE_IDLE) {
  708. if (!osal_memcmp(s_clientInfo, cpc, sizeof(zlclientC_t))) {
  709. reply->zlclR_errorCode = EC_CL_NOT_IDLE;
  710. }
  711. }
  712. #if (HAL_OAD_XNV_IS_INT && ((HAL_OAD_DL_OSET % HAL_FLASH_PAGE_SIZE) != 0))
  713. // Bug 2946 - HalXNVWrite() only triggers a page erase when the first byte of a
  714. // page boundary is written, so when dividing the available internal flash in half
  715. // results in a page being split in half, this remedial measure is necessary.
  716. else if (zlEraseHalfPage() != SUCCESS)
  717. {
  718. reply->zlclR_errorCode = EC_CL_NO_MEM;
  719. }
  720. #endif
  721. else {
  722. zlclientC_t *cmd = (zlclientC_t *)cpc;
  723. uint8 *cp;
  724. // need memory for holding client info, and current send-data cmd
  725. // do one alloc and set up the pointers
  726. cp = osal_mem_alloc(sizeof(zlclientC_t)+sizeof(zlmhdr_t)+sizeof(zlsdC_t));
  727. if (!cp) {
  728. // no more memory. let Commissioner decide what to do. maybe retry later.
  729. reply->zlclR_errorCode = EC_CL_NO_MEM;
  730. break;
  731. }
  732. else {
  733. // set up other pointers
  734. s_clientInfo = (zlclientC_t *)cp;
  735. s_sdcmd = (zlmhdr_t *)(cp+sizeof(zlclientC_t));
  736. s_sdcpayload = (zlsdC_t *)(cp+sizeof(zlclientC_t)+sizeof(zlmhdr_t));
  737. }
  738. // the info on the image to be downloaded and
  739. // the address of the Server is now saved both here
  740. // and in persistent memory
  741. osal_memcpy(s_clientInfo, cpc, sizeof(zlclientC_t));
  742. // populate destination address structure for convenience
  743. dstAddr.addrMode = afAddr16Bit;
  744. dstAddr.endPoint = cmd->zlclC_endp;
  745. osal_memcpy(&dstAddr.addr.shortAddr, &cmd->zlclC_nwk, sizeof(uint16));
  746. // set event to cause the session to begin
  747. osal_set_event(oad_app_taskId, ZLOAD_IS_CLIENT_EVT);
  748. }
  749. }
  750. break;
  751. case ZLMSGID_CODE_ENABLE:
  752. {
  753. zlceR_t *reply = (zlceR_t *)cpr;
  754. paylSize = sizeof(zlceR_t);
  755. reply->zlceR_state = s_State;
  756. #if defined ZPORT
  757. // we can enable code if the dongle code itself is being updated.
  758. if (!s_serialMsg) {
  759. reply->zlceR_errorCode = EC_CE_NOT_CLIENT;
  760. }
  761. else
  762. #endif
  763. if (s_State != ZLSTATE_IDLE) {
  764. reply->zlceR_errorCode = EC_CE_NOT_IDLE;
  765. }
  766. // see if we're supposed to enable the DL image. spec is in command payload
  767. // see if there is one...
  768. else {
  769. uint8 dlImagePreambleOset;
  770. osal_nv_read(PREAMBLE_NV_ID, 0, 1, &dlImagePreambleOset);
  771. HalOADRead(dlImagePreambleOset,(uint8 *)&preamble,sizeof(preamble_t),HAL_OAD_DL);
  772. if (preamble.vers != 0xFFFF) {
  773. // see if they match
  774. if (!memcmp(cpc, (uint8 *)&preamble.vers, ZL_IMAGE_ID_LENGTH)) {
  775. if (!HalAdcCheckVdd(VDD_MIN_OAD))
  776. {
  777. reply->zlceR_errorCode = EC_BAD_VDD;
  778. }
  779. else
  780. // DL image there and matches request, see if image is sane.
  781. if (SUCCESS == HalOADChkDL(dlImagePreambleOset)) {
  782. //set event to cause reset
  783. if (SUCCESS != osal_start_timerEx(oad_app_taskId, ZLOAD_CODE_ENABLE_EVT,
  784. SDC_WAIT_TO_ENABLE))
  785. {
  786. osal_set_event(oad_app_taskId, ZLOAD_CODE_ENABLE_EVT);
  787. }
  788. reply->zlceR_errorCode = EC_NO_ERROR;
  789. }
  790. else {
  791. reply->zlceR_errorCode = EC_CE_IMAGE_INSANE;
  792. }
  793. }
  794. else {
  795. // DL image there but doesn't match request
  796. reply->zlceR_errorCode = EC_CE_NO_MATCH;
  797. }
  798. }
  799. else {
  800. // no DL image
  801. reply->zlceR_errorCode = EC_CE_NO_IMAGE;
  802. }
  803. }
  804. }
  805. break;
  806. case ZLMSGID_SEND_DATA:
  807. #if defined ZPORT
  808. {
  809. zlsdR_t *reply = (zlsdR_t *)cpr;
  810. paylSize = sizeof(zlsdR_t);
  811. // do a sanity check.
  812. if (s_serialMsg) {
  813. reply->zlsdR_errorCode = EC_SD_NOT_SERVER;
  814. }
  815. else if (ZLSTATE_PASS_THROUGH == s_State) {
  816. // this should be good enough...
  817. if (s_PTClientInfo.srcAddr.addr.shortAddr != MSGpkt->srcAddr.addr.shortAddr) {
  818. // wrong client -- not the current client
  819. reply->zlsdR_errorCode = EC_SD_NOT_CLIENT;
  820. }
  821. else if (((zlsdC_t *)cpc)->zlsdC_sessionID != s_SessionID) {
  822. reply->zlsdR_errorCode = EC_SD_BAD_SESS_ID;
  823. }
  824. else {
  825. zahdrin_t *zain = zlBuildExternalInboundSerialMSG(&s_PTClientInfo, (uint8 *)msg, sizeof(zlmhdr_t) + sizeof(zlsdC_t));
  826. // forward message to host
  827. if (zain) {
  828. zlSendSerial((uint8 *)zain, SIZEOF_ZAIN_HDR + sizeof(zlmhdr_t) + sizeof(zlsdC_t));
  829. osal_mem_free(zain);
  830. // save the AF data. there may be AF parameters we need for the reply
  831. s_PTClientInfo = *MSGpkt;
  832. return;
  833. }
  834. else {
  835. reply->zlsdR_errorCode = EC_SD_NO_MEM;
  836. }
  837. }
  838. }
  839. else {
  840. reply->zlsdR_errorCode = EC_SD_NOT_SERVER;
  841. }
  842. }
  843. #else
  844. paylSize = sizeof(zlsdR_t);
  845. if (s_State != ZLSTATE_SERVER) {
  846. // this is the error case when we get a SD before we've started a session
  847. break;
  848. }
  849. s_sdrpayload->zlsdR_state = s_State;
  850. buf = (uint8 *)s_sdreply;
  851. if (((zlsdC_t *)cpc)->zlsdC_sessionID != s_SessionID) {
  852. s_sdrpayload->zlsdR_errorCode = EC_SD_BAD_SESS_ID;
  853. }
  854. else {
  855. // set error code first. it might get reset in the processing routine
  856. s_sdrpayload->zlsdR_errorCode = EC_NO_ERROR;
  857. // process the command
  858. zlProcessSDC((zlsdC_t *)cpc);
  859. }
  860. #endif
  861. break;
  862. case ZLMSGID_RESET:
  863. #if defined ZPORT
  864. // always legal if over serial port
  865. if (!s_serialMsg) {
  866. return;
  867. }
  868. else
  869. #endif
  870. {
  871. zlrstR_t *reply = (zlrstR_t *)cpr;
  872. reply->zlrstR_state = s_State;
  873. reply->zlrstR_errorCode = EC_NO_ERROR;
  874. }
  875. paylSize = sizeof(zlrstR_t);
  876. osal_set_event(oad_app_taskId, ZLOAD_RESET_EVT);
  877. break;
  878. default:
  879. return;
  880. }
  881. // the case above has filled in the payload. the header is the
  882. // same for all. go ahead and fill in header and send reply
  883. {
  884. zlmhdr_t *hdr = (zlmhdr_t *)buf;
  885. hdr->zlhdr_msgid = msg->zlhdr_msgid | ZLMSGID_REPLY_BIT;
  886. hdr->zlhdr_seqnum = msg->zlhdr_seqnum;
  887. hdr->zlhdr_msglen = paylSize;
  888. #if defined ZPORT
  889. if (!s_serialMsg) {
  890. #endif
  891. AF_DataRequest( &MSGpkt->srcAddr,
  892. afFindEndPointDesc( MSGpkt->endPoint),
  893. MSGpkt->clusterId,
  894. sizeof(zlmhdr_t) + paylSize, buf,
  895. &MSGpkt->cmd.TransSeqNumber,
  896. AF_DISCV_ROUTE, AF_DEFAULT_RADIUS );
  897. #if defined ZPORT
  898. } else {
  899. zahdrin_t *zain = zlBuildInternalInboundSerialMSG((uint8 *)hdr, sizeof(zlmhdr_t) + paylSize);
  900. if (zain) {
  901. zlSendSerial((uint8 *)zain, SIZEOF_ZAIN_HDR + sizeof(zlmhdr_t) + paylSize);
  902. osal_mem_free(zain);
  903. }
  904. }
  905. #else
  906. if ((buf != NULL) &&
  907. ((msg->zlhdr_msgid != ZLMSGID_SEND_DATA) || (s_State != ZLSTATE_SERVER)))
  908. {
  909. osal_mem_free(buf);
  910. }
  911. #endif
  912. }
  913. return;
  914. }
  915. #if !defined ZPORT
  916. /**********************************************************************************
  917. * @fn zlProcessSDC
  918. *
  919. * @brief Process the SDC command.
  920. *
  921. * @param cmd - A valid alsdC_t structure with valid data.
  922. *
  923. * @return none
  924. */
  925. static void zlProcessSDC(zlsdC_t *cmd)
  926. {
  927. uint16 reqPktNum;
  928. osal_memcpy(&reqPktNum, &cmd->zlsdC_pktNum, sizeof(uint16));
  929. // if the requested packet is the previous one the Client didn't get the
  930. // transmission for some reason. just resend the previous one. the data
  931. // are already in there. if we never got the command this test will fail.
  932. if (s_NextPacket && (reqPktNum == (s_NextPacket-1))) {
  933. return;
  934. }
  935. // make sure the request is otherwise valid
  936. if (!zlIsReqPacketNumOK(reqPktNum)) {
  937. s_sdrpayload->zlsdR_errorCode = EC_SD_BAD_PKT_NUM;
  938. return;
  939. }
  940. // Read data into reply buffer.
  941. HalOADRead((uint32)s_NextPacket * s_blkSize, s_sdrpayload->zlsdR_data,
  942. ZL_DATA_BLK_SIZE*ZL_NUM_DATA_BLKS, s_itype);
  943. // set packet number in reply
  944. osal_memcpy(&s_sdrpayload->zlsdR_pktNum, &reqPktNum, sizeof(uint16));
  945. s_NextPacket++;
  946. }
  947. /**********************************************************************************
  948. * @fn zlIsReqPacketNumOK
  949. *
  950. * @brief Check validity of resquested packet number as Server
  951. *
  952. * @param input
  953. * reqNum requested packet number
  954. *
  955. * @return 0: packet number request illegal
  956. * 1: packet number request is valid
  957. */
  958. static uint8 zlIsReqPacketNumOK(uint16 reqNum)
  959. {
  960. if (reqNum >= s_NumPktGet) {
  961. return 0;
  962. }
  963. return 1;
  964. }
  965. #endif
  966. /**********************************************************************************
  967. * @fn ZLOADApp_handleReply
  968. *
  969. * @brief Handle a normal ZLOAD reply
  970. *
  971. * @param input
  972. * msg pointer to ZLOAD message
  973. *
  974. * @return none.
  975. */
  976. static void ZLOADApp_handleReply(afIncomingMSGPacket_t *MSGpkt, zlmhdr_t *msg)
  977. {
  978. uint8 *cpr;
  979. #if defined ZPORT
  980. uint8 msgSize = 0;
  981. #endif
  982. #if !defined ZPORT
  983. // right reply?
  984. if (s_firstTx) {
  985. s_firstTx = 0;
  986. }
  987. else {
  988. if (msg->zlhdr_seqnum != s_lastTxSeqNum) {
  989. return;
  990. }
  991. if (msg->zlhdr_seqnum == s_lastSeen) {
  992. // duplicate reply to a resend
  993. return;
  994. }
  995. }
  996. s_lastSeen = msg->zlhdr_seqnum;
  997. #endif
  998. cpr = (uint8 *)msg + sizeof(zlmhdr_t); // offset of reply payload
  999. // generate replies to commands here. reply may generate another command out, for
  1000. // example, if data are being transfered and the dvice is acting as client.
  1001. // Commands handled here. replies in next routine
  1002. // ignore reply bit on switch()
  1003. switch (msg->zlhdr_msgid & (0xFF ^ ZLMSGID_REPLY_BIT)) {
  1004. case ZLMSGID_STATUSQ:
  1005. #if defined ZPORT
  1006. msgSize = 20;
  1007. // * * * NO BREAK * * *
  1008. case ZLMSGID_CLIENT_CMD:
  1009. case ZLMSGID_RESET:
  1010. case ZLMSGID_CODE_ENABLE:
  1011. if (!msgSize) {
  1012. msgSize = 2;
  1013. }
  1014. // right now, only the host could have sent these -- the dongle never sends these
  1015. // commands on its own. it's a proxy reply. forward it on...
  1016. if (!s_serialMsg) {
  1017. zahdrin_t *zain = zlBuildExternalInboundSerialMSG(MSGpkt, (uint8 *)msg, sizeof(zlmhdr_t) + msgSize);
  1018. if (zain) {
  1019. zlSendSerial((uint8 *)zain, SIZEOF_ZAIN_HDR + sizeof(zlmhdr_t) + msgSize);
  1020. osal_mem_free(zain);
  1021. }
  1022. }
  1023. #endif
  1024. break;
  1025. case ZLMSGID_SESSION_START:
  1026. #if defined ZPORT
  1027. // this can happen both in pass-through and client mode -- the dongle could be
  1028. // getting updated firmware and is the client receiving the start session reply.
  1029. // in any case we cannot get this reply over air. it has to have come from the Host
  1030. if (!s_serialMsg) {
  1031. break;
  1032. }
  1033. else if (ZLSTATE_PASS_THROUGH == s_State) {
  1034. // pass reply back to original client
  1035. msg->zlhdr_seqnum = s_PTSeqNum;
  1036. AF_DataRequest( &s_PTClientInfo.srcAddr,
  1037. afFindEndPointDesc( s_PTClientInfo.endPoint ),
  1038. s_PTClientInfo.clusterId,
  1039. sizeof(zlmhdr_t) + sizeof(zlbegsessR_t), (uint8 *)msg,
  1040. &s_PTClientInfo.cmd.TransSeqNumber,
  1041. AF_TX_OPTIONS_NONE, AF_DEFAULT_RADIUS );
  1042. }
  1043. else if (((zlbegsessR_t *)cpr)->zlbsR_errorCode) {
  1044. // Server rejected the real client session. back to Idle state.
  1045. osal_set_event(oad_app_taskId, ZLOAD_RESET_EVT);
  1046. }
  1047. // reply from Server to Begin Session command from Client
  1048. else if (ZLSTATE_CLIENT != s_State) {
  1049. // I didn't send it...ignore.
  1050. break;
  1051. }
  1052. #else
  1053. // reply from Server to Begin Session command from Client
  1054. if (s_State != ZLSTATE_CLIENT) {
  1055. // I didn't send it...ignore.
  1056. break;
  1057. }
  1058. else if (((zlbegsessR_t *)cpr)->zlbsR_errorCode) {
  1059. // Server rejected the session. back to Idle state.
  1060. osal_set_event(oad_app_taskId, ZLOAD_RESET_EVT);
  1061. }
  1062. #endif
  1063. else {
  1064. // get length and make sure we have room
  1065. uint32 imglen = ((zlbegsessR_t *)cpr)->zlbsR_imgLen;
  1066. if (imglen > HalOADAvail()) {
  1067. // no room. terminate session
  1068. osal_set_event(oad_app_taskId, ZLOAD_XFER_DONE_EVT);
  1069. }
  1070. else {
  1071. // TODO: The OAD Dongle Tool is broken and passes the wrong offset.
  1072. //uint8 dlImagePreambleOffset = ((zlbegsessR_t *)cpr)->zlbsR_preambleOffset;
  1073. //osal_nv_write(PREAMBLE_NV_ID, 0, 1, &dlImagePreambleOffset);
  1074. s_blkSize = ((zlbegsessR_t *)cpr)->zlbsR_blkSize;
  1075. s_blkSize *= ((zlbegsessR_t *)cpr)->zlbsR_numBlks;
  1076. // figure out how many data packets to request.
  1077. s_NumPktGet = (imglen+(s_blkSize-1)) / s_blkSize;
  1078. s_NextPacket = 0;
  1079. // request "next" (i.e., first) packet
  1080. zlRequestNextDataPacket();
  1081. }
  1082. }
  1083. break;
  1084. case ZLMSGID_SESSION_TERM:
  1085. #if defined ZPORT
  1086. // pass it back if we're in pass-through mode
  1087. if (s_serialMsg && (ZLSTATE_PASS_THROUGH == s_State)) {
  1088. AF_DataRequest( &s_PTClientInfo.srcAddr,
  1089. afFindEndPointDesc( s_PTClientInfo.endPoint),
  1090. s_PTClientInfo.clusterId,
  1091. sizeof(zlmhdr_t) + sizeof(zlendsessR_t), (uint8 *)msg,
  1092. &s_PTClientInfo.cmd.TransSeqNumber,
  1093. AF_TX_OPTIONS_NONE, AF_DEFAULT_RADIUS );
  1094. // in any case, clean up
  1095. osal_set_event(oad_app_taskId, ZLOAD_XFER_DONE_EVT);
  1096. }
  1097. #else
  1098. // don't care. right now the Commisioner can't be
  1099. // the client so it will never get a reply to the
  1100. // terminate session command because it can't send
  1101. // that command.
  1102. #endif
  1103. break;
  1104. case ZLMSGID_SEND_DATA:
  1105. #if defined ZPORT
  1106. if (!s_serialMsg) {
  1107. // reply should not be over air
  1108. break;
  1109. }
  1110. else if (ZLSTATE_CLIENT == s_State) {
  1111. // not a don't care if we're in client state
  1112. zlProcessSDR((zlsdR_t *)cpr);
  1113. }
  1114. else if (ZLSTATE_PASS_THROUGH == s_State) {
  1115. // forward to client
  1116. AF_DataRequest( &s_PTClientInfo.srcAddr,
  1117. afFindEndPointDesc( s_PTClientInfo.endPoint),
  1118. s_PTClientInfo.clusterId,
  1119. sizeof(zlmhdr_t) + sizeof(zlsdR_t), (uint8 *)msg,
  1120. &s_PTClientInfo.cmd.TransSeqNumber,
  1121. AF_TX_OPTIONS_NONE, AF_DEFAULT_RADIUS );
  1122. }
  1123. #else
  1124. // not a don't care if we're in client state
  1125. if (s_State == ZLSTATE_CLIENT) {
  1126. zlProcessSDR((zlsdR_t *)cpr);
  1127. }
  1128. #endif
  1129. break;
  1130. default:
  1131. // don't care
  1132. break;
  1133. }
  1134. }
  1135. /**********************************************************************************
  1136. * @fn zlProcessSDR
  1137. *
  1138. * @brief Process the Send Data Reply as Client
  1139. *
  1140. * @param input
  1141. * sdr pointer to received Send Data Reply
  1142. *
  1143. * @return none
  1144. */
  1145. static void zlProcessSDR(zlsdR_t *sdr)
  1146. {
  1147. uint16 tmp;
  1148. osal_memcpy(&tmp, &sdr->zlsdR_pktNum, sizeof(uint16));
  1149. // is this the right packet?
  1150. if (s_NextPacket > tmp)
  1151. {
  1152. return; // we've already seen this one. ignore it
  1153. }
  1154. else if (s_NextPacket < tmp) {
  1155. // uh oh. we've missed one. kill session...
  1156. osal_set_event(oad_app_taskId, ZLOAD_XFER_DONE_EVT);
  1157. return;
  1158. }
  1159. else if (sdr->zlsdR_errorCode) {
  1160. // there are no data here. just ignaore the packet. if things
  1161. // are relly screwed up the timer will expire and we'll quit.
  1162. return;
  1163. }
  1164. else if (!HalAdcCheckVdd(VDD_MIN_OAD))
  1165. {
  1166. osal_set_event(oad_app_taskId, ZLOAD_XFER_DONE_EVT);
  1167. return;
  1168. }
  1169. // Store the data in Xtra-NV.
  1170. HalOADWrite((uint32)s_NextPacket * s_blkSize, sdr->zlsdR_data, s_blkSize, HAL_OAD_DL);
  1171. s_NextPacket++; // OK to increment next packet number now.
  1172. zlRequestNextDataPacket(); // ask for next packet
  1173. }
  1174. /**********************************************************************************
  1175. * @fn zlRequestNextDataPacket
  1176. *
  1177. * @brief Set up the next data packet request. Takes care of knowing when
  1178. * transfer is done. Takes care of retry timer.
  1179. *
  1180. * @param none
  1181. *
  1182. * @return none
  1183. */
  1184. static void zlRequestNextDataPacket()
  1185. {
  1186. if (s_NextPacket >= s_NumPktGet) {
  1187. osal_set_event(oad_app_taskId, ZLOAD_XFER_DONE_EVT);
  1188. // kill response timeout check
  1189. osal_stop_timerEx(oad_app_taskId, ZLOAD_SDRTIMER_EVT);
  1190. return;
  1191. }
  1192. #if defined ZPORT
  1193. s_sdcpayload->zlsdC_pktNum = s_NextPacket;
  1194. s_sdcmd->zlhdr_seqnum = ++s_lastSeqNum;
  1195. {
  1196. zahdrin_t *zain = zlBuildInternalInboundSerialMSG((uint8 *)s_sdcmd, sizeof(zlmhdr_t) + sizeof(zlsdC_t));
  1197. if (zain) {
  1198. zlSendSerial((uint8 *)zain, SIZEOF_ZAIN_HDR + sizeof(zlmhdr_t) + sizeof(zlsdC_t));
  1199. osal_mem_free(zain);
  1200. }
  1201. }
  1202. #else
  1203. osal_memcpy(&s_sdcpayload->zlsdC_pktNum, &s_NextPacket, sizeof(uint16));
  1204. s_sdcmd->zlhdr_seqnum = ++s_lastTxSeqNum;
  1205. zlSendCommand(sizeof(zlmhdr_t) + sizeof(zlsdC_t), (uint8 *)s_sdcmd);
  1206. #endif
  1207. if (SUCCESS != osal_start_timerEx(oad_app_taskId, ZLOAD_SDRTIMER_EVT, SDR_WAIT_TO))
  1208. {
  1209. osal_set_event(oad_app_taskId, ZLOAD_SDRTIMER_EVT);
  1210. }
  1211. s_SDCRetryCount = SDC_RETRY_COUNT;
  1212. // set timeout timer
  1213. // need osal timer resource and set event flag and need a method to process timeout event
  1214. return;
  1215. }
  1216. /**********************************************************************************
  1217. * @fn zlCleanupOnReset
  1218. *
  1219. * @brief ZLOAD reset occurred. Free resources and reset state machine and other
  1220. * supporting constructs
  1221. *
  1222. * @param none
  1223. *
  1224. * @return none
  1225. */
  1226. static void zlCleanupOnReset()
  1227. {
  1228. #if !defined ZPORT
  1229. if (ZLSTATE_CLIENT == s_State) {
  1230. DO_EVENT_CALLBACK(ZLCB_EVENT_OADEND_CLIENT);
  1231. }
  1232. else if (ZLSTATE_SERVER == s_State) {
  1233. DO_EVENT_CALLBACK(ZLCB_EVENT_OADEND_SERVER);
  1234. }
  1235. #endif
  1236. zlResetState();
  1237. }
  1238. /**************************************************************************************
  1239. * @fn zlCleanupOnXferDone
  1240. *
  1241. * @brief Data transfer session complete (not necessarily correctly). Free resources
  1242. * and reset state machine and other supporting constructs. Send Terminate
  1243. * Session command to Server.
  1244. *
  1245. * @param none
  1246. *
  1247. * @return none
  1248. */
  1249. static void zlCleanupOnXferDone()
  1250. {
  1251. #if defined ZPORT
  1252. if (ZLSTATE_PASS_THROUGH == s_State) {
  1253. s_State = ZLSTATE_IDLE;
  1254. return;
  1255. }
  1256. #endif
  1257. // check for flashing last block and send Session Terminate command
  1258. if (ZLSTATE_CLIENT == s_State) {
  1259. zlmhdr_t *hdr = osal_mem_alloc(sizeof(zlmhdr_t) + sizeof(zlendsessC_t));
  1260. if (hdr) {
  1261. zlendsessC_t *cmd = (zlendsessC_t *)((uint8 *)hdr + sizeof(zlmhdr_t));
  1262. hdr->zlhdr_msgid = ZLMSGID_SESSION_TERM;
  1263. hdr->zlhdr_msglen = sizeof(zlendsessC_t);
  1264. cmd->zlesC_sessionID = s_SessionID;
  1265. hdr->zlhdr_seqnum = ++s_lastTxSeqNum;
  1266. #if defined ZPORT
  1267. {
  1268. zahdrin_t *zain = zlBuildInternalInboundSerialMSG((uint8 *)hdr, sizeof(zlmhdr_t) + sizeof(zlendsessC_t));
  1269. if (zain) {
  1270. zlSendSerial((uint8 *)zain, SIZEOF_ZAIN_HDR + sizeof(zlmhdr_t) + sizeof(zlendsessC_t));
  1271. osal_mem_free(zain);
  1272. }
  1273. }
  1274. #else
  1275. zlSendCommand(sizeof(zlmhdr_t) + sizeof(zlendsessC_t), (uint8 *)hdr);
  1276. #endif
  1277. osal_mem_free(hdr);
  1278. }
  1279. #if !defined ZPORT
  1280. DO_EVENT_CALLBACK(ZLCB_EVENT_OADEND_CLIENT);
  1281. #endif
  1282. }
  1283. #if !defined ZPORT
  1284. else if (ZLSTATE_SERVER == s_State) {
  1285. DO_EVENT_CALLBACK(ZLCB_EVENT_OADEND_SERVER);
  1286. }
  1287. #endif
  1288. zlResetState();
  1289. }
  1290. /**************************************************************************************
  1291. * @fn zlStartClientSession
  1292. *
  1293. * @brief We have been commanded to be in the Client role. Set up to start the
  1294. * session with the Server by sending the Begin Session command
  1295. *
  1296. * @param none
  1297. *
  1298. * @return none
  1299. */
  1300. static void zlStartClientSession()
  1301. {
  1302. uint8 *buf;
  1303. // we already have Server info. Contact Server to set up session
  1304. if (buf=osal_mem_alloc(sizeof(zlmhdr_t) + sizeof(zlbegsessC_t))) {
  1305. zlmhdr_t *hdr = (zlmhdr_t *)buf;
  1306. zlbegsessC_t *cmd = (zlbegsessC_t *)((uint8 *)buf+sizeof(zlmhdr_t));
  1307. // initialize session id as lsb of IEEE address
  1308. if (!s_SessionID) {
  1309. uint8 addr[Z_EXTADDR_LEN];
  1310. ZMacGetReq(ZMacExtAddr, addr);
  1311. s_SessionID = addr[0];
  1312. }
  1313. s_State = ZLSTATE_CLIENT;
  1314. s_SessionID++;
  1315. hdr->zlhdr_msgid = ZLMSGID_SESSION_START;
  1316. hdr->zlhdr_seqnum = ++s_lastTxSeqNum;
  1317. hdr->zlhdr_msglen = sizeof(zlbegsessC_t);
  1318. osal_memcpy(&cmd->zlbsC_ver, &s_clientInfo->zlclC_ver, sizeof(uint16));
  1319. osal_memcpy(&cmd->zlbsC_manu, &s_clientInfo->zlclC_manu, sizeof(uint16));
  1320. osal_memcpy(&cmd->zlbsC_prod, &s_clientInfo->zlclC_prod, sizeof(uint16));
  1321. cmd->zlbsC_sessionID = s_SessionID;
  1322. s_NextPacket = 0;
  1323. // populate session ID element in the Send data payload
  1324. s_sdcpayload->zlsdC_sessionID = s_SessionID;
  1325. // set up SD command header
  1326. s_sdcmd->zlhdr_msgid = ZLMSGID_SEND_DATA;
  1327. s_sdcmd->zlhdr_msglen = sizeof(zlsdC_t);
  1328. #if defined ZPORT
  1329. {
  1330. zahdrin_t *zain = zlBuildInternalInboundSerialMSG((uint8 *)hdr, sizeof(zlmhdr_t) + sizeof(zlbegsessC_t));
  1331. if (zain) {
  1332. zlSendSerial((uint8 *)zain, SIZEOF_ZAIN_HDR + sizeof(zlmhdr_t) + sizeof(zlbegsessC_t));
  1333. osal_mem_free(zain);
  1334. }
  1335. }
  1336. #else
  1337. if (zlSendCommand(sizeof(zlmhdr_t) + sizeof(zlbegsessC_t), buf))
  1338. {
  1339. }
  1340. #endif
  1341. osal_mem_free(buf);
  1342. DO_EVENT_CALLBACK(ZLCB_EVENT_OADBEGIN_CLIENT);
  1343. }
  1344. else {
  1345. // we couldn't send the Begin Session command. go back to Idle state.
  1346. osal_set_event(oad_app_taskId, ZLOAD_RESET_EVT);
  1347. }
  1348. return;
  1349. }
  1350. #if !defined ZPORT
  1351. /**************************************************************************************
  1352. * @fn zlSendCommand
  1353. *
  1354. * @brief Send command to destination. Can be either over air or to the Host. This
  1355. * routine takes care of the context.
  1356. *
  1357. * @param input
  1358. * length length of message being sent
  1359. * buf pointer to message
  1360. *
  1361. * @return 0: successful send
  1362. * 1: unseccessful send (return code for AF layer)
  1363. */
  1364. static uint8 zlSendCommand(uint8 length, uint8 *buf)
  1365. {
  1366. uint8 rc;
  1367. rc = AF_DataRequest( &dstAddr,
  1368. afFindEndPointDesc( OAD_epDesc.endPoint ),
  1369. OAD_CLUSTERID_CS,
  1370. length, buf,
  1371. &transId,
  1372. AF_DISCV_ROUTE, DEF_NWK_RADIUS );
  1373. return rc;
  1374. }
  1375. #endif
  1376. /**************************************************************************************
  1377. * @fn zlResendSDC
  1378. *
  1379. * @brief Resend the previous Send Data Command because a repply was not received
  1380. * before a timeout.
  1381. *
  1382. * @param none
  1383. *
  1384. * @return none.
  1385. */
  1386. static void zlResendSDC()
  1387. {
  1388. if (s_State != ZLSTATE_CLIENT) {
  1389. // late expiration -- don't care
  1390. return;
  1391. }
  1392. if (--s_SDCRetryCount) {
  1393. #if defined ZPORT
  1394. s_sdcmd->zlhdr_seqnum = ++s_lastSeqNum;
  1395. {
  1396. zahdrin_t *zain = zlBuildInternalInboundSerialMSG((uint8 *)s_sdcmd, sizeof(zlmhdr_t) + sizeof(zlsdC_t));
  1397. if (zain) {
  1398. zlSendSerial((uint8 *)zain, SIZEOF_ZAIN_HDR + sizeof(zlmhdr_t) + sizeof(zlsdC_t));
  1399. osal_mem_free(zain);
  1400. }
  1401. }
  1402. #else
  1403. // the static structure still contains the last packet number to be requested.
  1404. // the only way the packet number gets bumped is if a reply is received.
  1405. zlSendCommand(sizeof(zlmhdr_t) + sizeof(zlsdC_t), (uint8 *)s_sdcmd);
  1406. #endif
  1407. if (SUCCESS != osal_start_timerEx(oad_app_taskId, ZLOAD_SDRTIMER_EVT, SDR_WAIT_TO))
  1408. {
  1409. osal_set_event(oad_app_taskId, ZLOAD_SDRTIMER_EVT);
  1410. }
  1411. }
  1412. else {
  1413. // too many retries. abandon session.
  1414. osal_set_event(oad_app_taskId, ZLOAD_XFER_DONE_EVT);
  1415. }
  1416. return;
  1417. }
  1418. #if !defined ZPORT
  1419. /**************************************************************************************
  1420. * @fn oadAppRegisterCB
  1421. *
  1422. * @brief Register a callback to be referenced when OAD events occur.
  1423. *
  1424. * @param input
  1425. * pCBFunction pointer to void function with an unsigned short argument.
  1426. * eventMask bit mask of events for which the callback should be invoked.
  1427. *
  1428. * When the callback is invoked its argument will indicate via the bit mask argument
  1429. * which event occurred. A null pointer or a null bit mask will have the effect of
  1430. * deregistration.
  1431. *
  1432. * @return none.
  1433. */
  1434. void oadAppRegisterCB(void (*pCBFunction)(uint16), uint16 eventMask)
  1435. {
  1436. s_pCallback = pCBFunction;
  1437. s_eventMask = eventMask;
  1438. return;
  1439. }
  1440. #endif
  1441. /**************************************************************************************************
  1442. * @fn zlResetState
  1443. *
  1444. * @brief This function frees any memory in use and resets the zl state info.
  1445. *
  1446. * input parameters
  1447. *
  1448. * None.
  1449. *
  1450. * output parameters
  1451. *
  1452. * None.
  1453. *
  1454. * @return None.
  1455. **************************************************************************************************
  1456. */
  1457. static void zlResetState(void)
  1458. {
  1459. osal_stop_timerEx(oad_app_taskId, ZLOAD_SDRTIMER_EVT); // kill response timeout check
  1460. if (s_sdreply)
  1461. {
  1462. osal_mem_free(s_sdreply);
  1463. s_sdreply = NULL;
  1464. }
  1465. if (s_clientInfo)
  1466. {
  1467. osal_mem_free(s_clientInfo);
  1468. s_clientInfo = NULL;
  1469. }
  1470. s_State = ZLSTATE_IDLE;
  1471. s_NextPacket = 0;
  1472. s_NumPktGet = 0;
  1473. }
  1474. #if defined ZPORT
  1475. /*********************************************************************
  1476. * @fn ZLOADApp_SerialMSGCB
  1477. *
  1478. * @brief Message from Host application. It's a command, a reply,
  1479. * or a proxy command. Send it on appropriately
  1480. *
  1481. * @param input
  1482. * inMsg pointer to incoming message
  1483. *
  1484. * @return none
  1485. */
  1486. static void ZLOADApp_SerialMessageMSGCB(zahdrout_t *zaout)
  1487. {
  1488. zlmhdr_t *zlhdr = (zlmhdr_t *)zaout->zaproxy_payload;
  1489. // is this for me?
  1490. if (zaout->zaproxy_nwkAddr == s_myNwkAddr) {
  1491. // is this a reply?
  1492. if (zlhdr->zlhdr_msgid & ZLMSGID_REPLY_BIT) {
  1493. ZLOADApp_handleReply(NULL, zlhdr);
  1494. }
  1495. else {
  1496. ZLOADApp_handleCommand(NULL, zlhdr);
  1497. }
  1498. }
  1499. else {
  1500. // it's a proxy command
  1501. zlZArchitectProxyMsg(zaout);
  1502. }
  1503. return;
  1504. }
  1505. /*********************************************************************
  1506. * @fn zlSendSerial
  1507. *
  1508. * @brief Prepare message outgoing over serial port.
  1509. * malloc and copy to add serial encapsulation.
  1510. *
  1511. * @param input
  1512. * buf pointer to ougoing message buffer
  1513. * len length of message
  1514. *
  1515. * @return none
  1516. */
  1517. static void zlSendSerial(uint8 *buf, uint8 len)
  1518. {
  1519. uint8 *nbuf;
  1520. if ((nbuf=osal_mem_alloc(len+1))) {
  1521. osal_memcpy(nbuf+1, buf, len);
  1522. *nbuf = OAD_ENDPOINT;
  1523. #if !defined(ZTOOL_SUPPORT)
  1524. MTProcessAppRspMsg(nbuf, len + 1);
  1525. #else
  1526. // ZTool expects an 81 byte message
  1527. MTProcessAppRspMsg(nbuf, 81);
  1528. #endif
  1529. osal_mem_free(nbuf);
  1530. }
  1531. return;
  1532. }
  1533. /****************************************************************************
  1534. * @fn zlZArchitectProxyCommand
  1535. *
  1536. * @brief Send command to target device on behalf of ZArchitect Host App
  1537. *
  1538. * @param input
  1539. * info pointer to ZArchitect proxy message
  1540. *
  1541. * @return none
  1542. */
  1543. static void zlZArchitectProxyMsg(zahdrout_t *info)
  1544. {
  1545. afAddrType_t taddr;
  1546. zlmhdr_t *zlhdr = (zlmhdr_t *)info->zaproxy_payload;
  1547. // only certain outgoing messages are valid proxy commands
  1548. switch (zlhdr->zlhdr_msgid) {
  1549. case ZLMSGID_SESSION_START:
  1550. case ZLMSGID_SESSION_TERM:
  1551. case ZLMSGID_SEND_DATA:
  1552. return;
  1553. }
  1554. // fill in address info
  1555. taddr.addrMode = afAddr16Bit;
  1556. taddr.endPoint = info->zaproxy_endp;
  1557. taddr.addr.shortAddr = info->zaproxy_nwkAddr;
  1558. AF_DataRequest( &taddr,
  1559. afFindEndPointDesc( info->zaproxy_endp ),
  1560. info->zaproxy_ClusterID,
  1561. info->zaproxy_msglen, info->zaproxy_payload,
  1562. &transId,
  1563. AF_TX_OPTIONS_NONE, DEF_NWK_RADIUS );
  1564. }
  1565. // start a session with the host on behalf of the client from which
  1566. // the start session was received. do this by sending self a client
  1567. // command using the start session parameters. ZLOAD will think it
  1568. // is a client message coming from the host asking it to come get
  1569. // the image being requested by the real client.
  1570. static uint8 zlPassOnStartSessionOK(uint8 *msg)
  1571. {
  1572. zahdrin_t *zamsgin;
  1573. // forward the Begin Session command
  1574. zamsgin = zlBuildExternalInboundSerialMSG(&s_PTClientInfo, msg, sizeof(zlmhdr_t) + sizeof(zlbegsessC_t));
  1575. if (!zamsgin) {
  1576. return 0;
  1577. }
  1578. zlSendSerial((uint8 *)zamsgin, SIZEOF_ZAIN_HDR + sizeof(zlmhdr_t) + sizeof(zlbegsessC_t));
  1579. osal_mem_free(zamsgin);
  1580. return 1;
  1581. }
  1582. // inbound messages can be built from address information gleaned from the client
  1583. // during a pass-through session setup. but there can also be inbound messages
  1584. // such as status replies that are not part of any ongoing client session. in this
  1585. // case the address information comes from the AF message. in either case this
  1586. // information is requried to populate the header for for the host.
  1587. static zahdrin_t *zlBuildExternalInboundSerialMSG(afIncomingMSGPacket_t *addressInfo, uint8 *zlmsg, uint8 len)
  1588. {
  1589. zahdrin_t *zamsgin;
  1590. // build message
  1591. zamsgin = (zahdrin_t *)osal_mem_alloc(SIZEOF_ZAIN_HDR + len);
  1592. if (!zamsgin) {
  1593. return 0;
  1594. }
  1595. zamsgin->zaproxy_nwkAddr = addressInfo->srcAddr.addr.shortAddr;
  1596. zamsgin->zaproxy_endp = addressInfo->endPoint;
  1597. zamsgin->zaproxy_ClusterID = addressInfo->clusterId;
  1598. zamsgin->zaproxy_msglen = len;
  1599. osal_memcpy(zamsgin->zaproxy_payload, zlmsg, len);
  1600. return zamsgin;
  1601. }
  1602. static zahdrin_t *zlBuildInternalInboundSerialMSG(uint8 *zlmsg, uint8 len)
  1603. {
  1604. zahdrin_t *zamsgin;
  1605. // build message
  1606. zamsgin = (zahdrin_t *)osal_mem_alloc(SIZEOF_ZAIN_HDR + len);
  1607. if (!zamsgin) {
  1608. return 0;
  1609. }
  1610. zamsgin->zaproxy_nwkAddr = s_myNwkAddr;
  1611. zamsgin->zaproxy_endp = OAD_ENDPOINT;
  1612. zamsgin->zaproxy_ClusterID = OAD_CLUSTERID_CS;
  1613. zamsgin->zaproxy_msglen = len;
  1614. osal_memcpy(zamsgin->zaproxy_payload, zlmsg, len);
  1615. return zamsgin;
  1616. }
  1617. /*********************************************************************
  1618. * @fn zlHandleKeys
  1619. *
  1620. * @brief Handles all key events for this device.
  1621. *
  1622. * @param shift - true if in shift/alt.
  1623. * @param keys - bit field for key events. Valid entries:
  1624. * EVAL_SW4
  1625. * EVAL_SW3
  1626. * EVAL_SW2
  1627. * EVAL_SW1
  1628. *
  1629. * @return none
  1630. */
  1631. static void zlHandleKeys(uint8 shift, uint8 keys)
  1632. {
  1633. // Shift is used to make each button/switch dual purpose.
  1634. if ( shift )
  1635. {
  1636. if ( keys & HAL_KEY_SW_1 )
  1637. {
  1638. }
  1639. if ( keys & HAL_KEY_SW_2 )
  1640. {
  1641. }
  1642. if ( keys & HAL_KEY_SW_3 )
  1643. {
  1644. }
  1645. if ( keys & HAL_KEY_SW_4 )
  1646. {
  1647. }
  1648. }
  1649. else
  1650. {
  1651. if ( keys & HAL_KEY_SW_1 )
  1652. {
  1653. mtxMode = TRUE;
  1654. }
  1655. if ( keys & HAL_KEY_SW_2 )
  1656. {
  1657. }
  1658. if ( keys & HAL_KEY_SW_3 )
  1659. {
  1660. mtxMode = FALSE;
  1661. }
  1662. if ( keys & HAL_KEY_SW_4 )
  1663. {
  1664. }
  1665. }
  1666. }
  1667. #else
  1668. #if (HAL_OAD_XNV_IS_INT && ((HAL_OAD_DL_OSET % HAL_FLASH_PAGE_SIZE) != 0))
  1669. // Bug 2946 - HalXNVWrite() only triggers a page erase when the first byte of a page
  1670. // boundary is written, so when dividing the available internal flash in half results in a
  1671. // page being split in half, this remedial measure is necessary.
  1672. static Status_t zlEraseHalfPage(void)
  1673. {
  1674. const uint16 hPgSz = HAL_FLASH_PAGE_SIZE / 2;
  1675. // HalXNVRead/Write routines add HAL_OAD_DL_OSET to the 'addr' parameter, so pass in a 'negative'.
  1676. const uint32 addr = 0L - hPgSz;
  1677. uint8 *pBuf = osal_mem_alloc(hPgSz);
  1678. if (NULL == pBuf)
  1679. {
  1680. return FAILURE;
  1681. }
  1682. HalXNVRead(addr, pBuf, hPgSz);
  1683. // This triggers the full page erase and restores the lower half.
  1684. HalXNVWrite(addr, pBuf, hPgSz);
  1685. osal_mem_free(pBuf);
  1686. return SUCCESS;
  1687. }
  1688. #endif
  1689. #endif
  1690. #pragma diag_default=Pa039