123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890 |
- /**************************************************************************************************
- Filename: oad_app.c
- Revised: $Date: 2011-05-16 10:25:15 -0700 (Mon, 16 May 2011) $
- Revision: $Revision: 25990 $
- Description: This file contains the implementation of an Over Air Download application.
- Copyright 2008-2011 Texas Instruments Incorporated. All rights reserved.
- IMPORTANT: Your use of this Software is limited to those specific rights
- granted under the terms of a software license agreement between the user
- who downloaded the software, his/her employer (which must be your employer)
- and Texas Instruments Incorporated (the "License"). You may not use this
- Software unless you agree to abide by the terms of the License. The License
- limits your use, and you acknowledge, that the Software may not be modified,
- copied or distributed unless embedded on a Texas Instruments microcontroller
- or used solely and exclusively in conjunction with a Texas Instruments radio
- frequency transceiver, which is integrated into your product. Other than for
- the foregoing purpose, you may not use, reproduce, copy, prepare derivative
- works of, modify, distribute, perform, display or sell this Software and/or
- its documentation for any purpose.
- YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
- PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
- INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
- NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
- TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
- NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
- LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
- INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
- OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
- OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
- (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
- Should you have any questions regarding your right to use this Software,
- contact Texas Instruments Incorporated at www.TI.com.
- **************************************************************************************************/
- /* ------------------------------------------------------------------------------------------------
- * Includes
- * ------------------------------------------------------------------------------------------------
- */
- #include <string.h>
- #include "AF.h"
- #include "hal_adc.h"
- #include "hal_board_cfg.h"
- #include "hal_flash.h"
- #include "hal_oad.h"
- #include "oad_app.h"
- #include "oad_preamble.h"
- #include "OnBoard.h"
- #include "OSAL_Nv.h"
- #if defined ZPORT
- #include "hal_key.h"
- #include "MT.h"
- #include "MT_APP.h"
- #include "MT_X.h"
- #include "ZDApp.h"
- #else
- #if (HAL_OAD_XNV_IS_INT && ((HAL_OAD_DL_OSET % HAL_FLASH_PAGE_SIZE) != 0))
- #include "hal_xnv.h"
- #endif
- #endif
- /* ------------------------------------------------------------------------------------------------
- * Macros
- * ------------------------------------------------------------------------------------------------
- */
- #define DO_EVENT_CALLBACK(e) st ( if (s_pCallback && ((e) & s_eventMask)) s_pCallback((e)); )
- /* ------------------------------------------------------------------------------------------------
- * Constants
- * ------------------------------------------------------------------------------------------------
- */
- #if !defined OAD_NV_ID
- // Arbitrarily pick the last Id available to the user Application.
- #define OAD_NV_ID 0x0FFF
- #endif
- #define PREAMBLE_NV_ID OAD_NV_ID
- // support to select callback event for which subscription is desired
- // this information is transmitted as a bit map.
- #define ZLCB_EVENT_OADBEGIN_CLIENT ((uint16)0x0001)
- #define ZLCB_EVENT_OADEND_CLIENT ((uint16)0x0002)
- #define ZLCB_EVENT_OADBEGIN_SERVER ((uint16)0x0004)
- #define ZLCB_EVENT_OADEND_SERVER ((uint16)0x0008)
- #define ZLCB_EVENT_CODE_ENABLE_RESET ((uint16)0x0010)
- #define ZLCB_EVENT_ALL (ZLCB_EVENT_OADBEGIN_CLIENT | \
- ZLCB_EVENT_OADEND_CLIENT | \
- ZLCB_EVENT_OADBEGIN_SERVER | \
- ZLCB_EVENT_OADEND_SERVER | \
- ZLCB_EVENT_CODE_ENABLE_RESET \
- )
- #define SDC_RETRY_COUNT (10)
- #define SDR_WAIT_TO (1000)
- // Some reasonable time to get the code enable response out.
- #define SDC_WAIT_TO_ENABLE (10000)
- /* ------------------------------------------------------------------------------------------------
- * Typedefs
- * ------------------------------------------------------------------------------------------------
- */
- #if defined ZPORT
- #define SIZEOF_ZAIN_HDR (sizeof(uint16) + sizeof(uint8) + sizeof(uint16) + sizeof(uint8))
- // Z-Architect headers
- // inbound to host (from dongle directly or external platform)
- PACK_1
- typedef struct {
- uint16 zaproxy_nwkAddr;
- uint8 zaproxy_endp;
- uint16 zaproxy_ClusterID;
- uint8 zaproxy_msglen;
- uint8 zaproxy_payload[1];
- } zahdrin_t;
- // outbound from host (to dongle directly or external platform)
- PACK_1
- typedef struct {
- uint16 zaproxy_nwkAddr;
- uint8 zaproxy_endp;
- uint16 zaproxy_ClusterID;
- uint8 zaproxy_msglen;
- uint8 zaproxy_payload[1];
- } zahdrout_t;
- #endif
- /* ------------------------------------------------------------------------------------------------
- * Global Variables
- * ------------------------------------------------------------------------------------------------
- */
- uint8 oad_app_taskId;
- /* ------------------------------------------------------------------------------------------------
- * Global Functions
- * ------------------------------------------------------------------------------------------------
- */
- #if defined ZPORT
- #define HalOADChkDL(V) 1
- #define HalOADInvRC(V)
- #define HalOADAvail(V) HAL_OAD_DL_SIZE
- #define HalOADRead(A, B, C, D)
- #define HalOADWrite(A, B, C, D)
- #endif
- /* ------------------------------------------------------------------------------------------------
- * Local Variables
- * ------------------------------------------------------------------------------------------------
- */
- static uint8 transId;
- static afAddrType_t dstAddr;
- static zlclientC_t *s_clientInfo;
- static uint8 s_State, s_SessionID, s_blkSize;
- static uint16 s_NextPacket, s_NumPktGet, s_SDCRetryCount;
- static zlmhdr_t *s_sdcmd;
- static zlsdC_t *s_sdcpayload;
- static zlmhdr_t *s_sdreply;
- #if !defined ZPORT
- static zlsdR_t *s_sdrpayload;
- static image_t s_itype;
- static uint8 s_lastSeen, s_firstTx = 1;
- #endif
- static void (*s_pCallback)(uint16);
- static uint16 s_eventMask;
- static uint8 s_lastTxSeqNum;
- #if defined ZPORT
- static uint8 s_serialMsg;
- static uint16 s_lastSeqNum;
- static uint16 s_myNwkAddr = 0xFFFE;
- // pass through stuff
- static uint8 s_PTSeqNum;
- static afIncomingMSGPacket_t s_PTClientInfo;
- #else
- #pragma location="PREAMBLE"
- const CODE preamble_t _preamble = {
- {PREAMBLE_MAGIC1, PREAMBLE_MAGIC2},
- HAL_OAD_DL_SIZE,
- HAL_OAD_VERS,
- HAL_OAD_MANU,
- HAL_OAD_PROD
- };
- #pragma required=_preamble
- #endif
- // This list should be filled with Application specific Cluster IDs.
- static const cId_t OAD_ClusterList[OAD_CLUSTER_CNT] =
- {
- OAD_CLUSTERID_CS
- //,OAD_CLUSTERID_EM
- };
- static const SimpleDescriptionFormat_t OAD_SimpleDesc =
- {
- OAD_ENDPOINT,
- OAD_PROFILE_ID,
- OAD_DEVICEID,
- OAD_DEVICE_VERSION,
- OAD_FLAGS,
- OAD_CLUSTER_CNT,
- (cId_t *)OAD_ClusterList,
- 0,
- NULL
- };
- static const endPointDesc_t OAD_epDesc=
- {
- OAD_ENDPOINT,
- &oad_app_taskId,
- (SimpleDescriptionFormat_t *)&OAD_SimpleDesc,
- noLatencyReqs,
- };
- #if defined HAL_OAD_BL21
- // this is the mailbox value that tells the boot code to flash the downloaded image
- // even though the operational image may be sane.
- #define MBOX_OAD_ENABLE 0x454E424C // 'ENBL' enable downloaded code
- PACK_1
- typedef struct mbox_s {
- volatile unsigned long BootRead;
- volatile unsigned long AppRead;
- } mboxMsg_t;
- #pragma location="MBOXMSG_ADDR"
- __no_init mboxMsg_t mboxMsg;
- PACK_1
- typedef struct {
- uint8 (*ReadFlash)(image_t, uint32 addr, uint8 *pBuf, uint16 len);
- uint8 (*WriteFlash)(image_t, uint32 addr, uint8 *pBuf, uint16 len);
- uint8 (*CheckCodeSanity)(image_t, uint32 addr1, uint32 addr2);
- uint8 (*GetPreamble)(image_t, uint32 addr, preamble_t *pBuf);
- } mbox_t;
- #pragma location="MBOX_ADDR"
- __no_init mbox_t mbox;
- #endif
- /* ------------------------------------------------------------------------------------------------
- * Local Functions
- * ------------------------------------------------------------------------------------------------
- */
- static void procSysEvtMsg(void);
- static void zlResetState(void);
- static void ZLOADApp_MessageMSGCB( afIncomingMSGPacket_t * );
- static void ZLOADApp_handleCommand(afIncomingMSGPacket_t *, zlmhdr_t *);
- static void ZLOADApp_handleReply(afIncomingMSGPacket_t *, zlmhdr_t *);
- static void zlCleanupOnReset(void);
- static void zlStartClientSession(void);
- static void zlProcessSDR(zlsdR_t *);
- static void zlRequestNextDataPacket(void);
- static void zlCleanupOnXferDone(void);
- static void zlResendSDC(void);
- #if defined ZPORT
- static void zlSendSerial(uint8 *, uint8);
- static void ZLOADApp_SerialMessageMSGCB(zahdrout_t *);
- static void zlZArchitectProxyMsg(zahdrout_t *);
- static uint8 zlPassOnStartSessionOK(uint8 *);
- static zahdrin_t *zlBuildExternalInboundSerialMSG(afIncomingMSGPacket_t *, uint8 *, uint8);
- static zahdrin_t *zlBuildInternalInboundSerialMSG(uint8 *, uint8);
- static void zlHandleKeys(uint8 shift, uint8 keys);
- #else
- static uint8 zlSendCommand(uint8, uint8 *);
- static void zlProcessSDC(zlsdC_t *);
- static uint8 zlIsReqPacketNumOK(uint16);
- #if (HAL_OAD_XNV_IS_INT && ((HAL_OAD_DL_OSET % HAL_FLASH_PAGE_SIZE) != 0))
- static Status_t zlEraseHalfPage(void);
- #endif
- #endif
- /**************************************************************************************************
- * @fn oadAppInit
- *
- * @brief This function is called by OSAL system startup.
- *
- * input parameters
- *
- * @param id - The Task ID assigned by OSAL.
- *
- * output parameters
- *
- * None.
- *
- * @return None.
- **************************************************************************************************
- */
- void oadAppInit(uint8 id)
- {
- oad_app_taskId = id;
- afRegister((endPointDesc_t *)&OAD_epDesc);
- s_State = ZLSTATE_IDLE;
- id = PREAMBLE_OFFSET;
- osal_nv_item_init(PREAMBLE_NV_ID, 1, &id);
- #if defined HAL_OAD_BL21
- mboxMsg.BootRead = 0;
- #endif
- #if defined ZPORT
- // Register for all key events - This app will handle all key events
- RegisterForKeys(oad_app_taskId);
- mtxMode = TRUE;
- #endif
- }
- /**************************************************************************************************
- * @fn oadAppEvt
- *
- * @brief This function is called to process the OSAL events for the task.
- *
- * input parameters
- *
- * @param id - The Task ID assigned by OSAL.
- * @param evts - A bit mask representing the OSAL events that are pending for this task.
- *
- * output parameters
- *
- * None.
- *
- * @return None.
- **************************************************************************************************
- */
- uint16 oadAppEvt(uint8 id, uint16 evts)
- {
- uint16 mask = 0;
- (void)id;
- if (evts & SYS_EVENT_MSG)
- {
- mask = SYS_EVENT_MSG;
- procSysEvtMsg();
- }
- else if (evts & ZLOAD_CODE_ENABLE_EVT)
- {
- // let the user shut down the environment if requested
- DO_EVENT_CALLBACK(ZLCB_EVENT_CODE_ENABLE_RESET);
- #if defined HAL_OAD_BL21
- // Set up mail box to tell the pre-2.2 boot code to flash the downloaded image.
- mboxMsg.BootRead = MBOX_OAD_ENABLE;
- #else
- HalOADInvRC();
- #endif
- SystemReset();
- }
- else if (evts & ZLOAD_IS_CLIENT_EVT)
- {
- mask = ZLOAD_IS_CLIENT_EVT;
- zlStartClientSession();
- }
- else if (evts & ZLOAD_XFER_DONE_EVT)
- {
- mask = ZLOAD_XFER_DONE_EVT;
- zlCleanupOnXferDone();
- }
- else if (evts & ZLOAD_RESET_EVT)
- {
- mask = ZLOAD_RESET_EVT;
- zlCleanupOnReset();
- }
- else if (evts & ZLOAD_SDRTIMER_EVT)
- {
- mask = ZLOAD_SDRTIMER_EVT;
- zlResendSDC();
- }
- else if (evts & ZLOAD_RESET_BOARD_EVT)
- {
- SystemResetSoft();
- }
- else
- {
- mask = evts; // Discard unknown events - should never happen.
- }
- return (evts ^ mask); // Return unprocessed events.
- }
- /**************************************************************************************************
- * @fn procSysEvtMsg
- *
- * @brief This function is called by oadAppEvt() to process all of the pending OSAL messages.
- *
- * input parameters
- *
- * None.
- *
- * output parameters
- *
- * None.
- *
- * @return None.
- **************************************************************************************************
- */
- static void procSysEvtMsg(void)
- {
- uint8 *msgPtr;
- while ((msgPtr = osal_msg_receive(oad_app_taskId)))
- {
- #if defined ZPORT
- s_serialMsg = 0;
- #endif
- switch ( *msgPtr )
- {
- case MT_SYS_APP_MSG:
- case MT_SYS_APP_RSP_MSG:
- #if defined ZPORT
- // This is how we get messages from a Host application (ZOAD.exe).
- s_serialMsg = 1;
- ZLOADApp_SerialMessageMSGCB((zahdrout_t *)(((mtSysAppMsg_t *)msgPtr)->appData));
- #endif
- break;
- case AF_DATA_CONFIRM_CMD:
- break;
- case AF_INCOMING_MSG_CMD:
- ZLOADApp_MessageMSGCB((afIncomingMSGPacket_t *)msgPtr);
- break;
- #if defined ZPORT
- case KEY_CHANGE:
- zlHandleKeys(((keyChange_t *)msgPtr)->state, ((keyChange_t *)msgPtr)->keys);
- break;
- #endif
- case ZDO_NEW_DSTADDR:
- /*
- dstEP = msgPtr[1];
- dstAddr = (zAddrType_t *)&msgPtr[2];
- dstAddr.addrMode = dstAddr->addrMode;
- dstAddr.endPoint = dstEP;
- if (dstAddr->addrMode == afAddr16Bit)
- dstAddr.addr.shortAddr = dstAddr->addr.shortAddr;
- else
- osal_memcpy(dstAddr.addr.extAddr, dstAddr->addr.extAddr, Z_EXTADDR_LEN);
- */
- break;
- case ZDO_STATE_CHANGE:
- #if defined ZPORT
- if (((devStates_t)(((osal_event_hdr_t *)msgPtr)->status) == DEV_END_DEVICE_UNAUTH) ||
- ((devStates_t)(((osal_event_hdr_t *)msgPtr)->status) == DEV_END_DEVICE))
- {
- MT_X_FakeNwkJoinCnf();
- }
- #endif
- break;
- default:
- break;
- }
- osal_msg_deallocate(msgPtr); // Receiving task is responsible for releasing the memory.
- }
- }
- /**********************************************************************************
- * @fn ZLOADApp_MessageMSGCB
- *
- * @brief Handle a normal ZLOAD command or reply. Forward it to proper handler
- *
- * @param MSGpkt - pointer to incoming AF packet
- *
- * @return none
- */
- static void ZLOADApp_MessageMSGCB(afIncomingMSGPacket_t *MSGpkt)
- {
- zlmhdr_t *inMsg = (zlmhdr_t *)MSGpkt->cmd.Data;
- if (inMsg->zlhdr_msgid & ZLMSGID_REPLY_BIT)
- {
- ZLOADApp_handleReply(MSGpkt, inMsg);
- }
- else
- {
- ZLOADApp_handleCommand(MSGpkt, inMsg);
- }
- return;
- }
- /**********************************************************************************
- * @fn ZLOADApp_handleCommand
- *
- * @brief Handle a normal ZLOAD command
- *
- * @param input
- * MSGpkt pointer to incoming AF packet. needed to get
- * reply address info
- * msg pointer to ZLOAD message
- *
- * @return none
- */
- static void ZLOADApp_handleCommand(afIncomingMSGPacket_t *MSGpkt, zlmhdr_t *msg)
- {
- uint8 *cpc, *cpr, paylSize;
- preamble_t preamble;
- #if defined ZPORT
- static uint8 *buf;
- if (!buf)
- {
- if (!(buf = osal_mem_alloc(sizeof(zlmhdr_t) + sizeof(zlreply_t))))
- {
- return;
- }
- }
- #else
- uint8 *buf = NULL;
- // allocate the reply buffer. use a union of the replies -- they're all pretty
- // small -- except for Send Data. that one is preallocated because we want
- // to really have it and not spend time doing malloc/free for so many transactions
- // besides, we don't want a malloc() to fail during the transfer.
- if (msg->zlhdr_msgid != ZLMSGID_SEND_DATA)
- {
- if (!(buf = osal_mem_alloc(sizeof(zlmhdr_t) + sizeof(zlreply_t))))
- {
- return;
- }
- }
- else
- {
- // make sure we don't have a premature send-data command. this is awkward because
- // in the normal case we've done a "static" allocation (for the durtion of the session)
- // to prevent thousands of alloc/free calls or a failed alloc. but now, we dont' have
- // that "static" memory yet.
- if (s_State != ZLSTATE_SERVER)
- {
- // uh oh. we never got a start session. now we need memory to
- // send the reply
- if (!(buf = osal_mem_alloc(sizeof(zlmhdr_t) + sizeof(zlsdR_t))))
- {
- return;
- }
- // make the rest of the code work
- s_sdreply = (zlmhdr_t *)buf;
- s_sdreply->zlhdr_msgid = ZLMSGID_SEND_DATA | ZLMSGID_REPLY_BIT;
- s_sdreply->zlhdr_msglen = sizeof(zlsdR_t);
- s_sdrpayload = (zlsdR_t *)(buf+sizeof(zlmhdr_t));
- s_sdrpayload->zlsdR_state = s_State;
- s_sdrpayload->zlsdR_errorCode = EC_SD_NOT_SERVER;
- }
- }
- #endif
- cpr = buf + sizeof(zlmhdr_t); // offset of reply payload
- cpc = (uint8 *)msg + sizeof(zlmhdr_t); // offset of command payload
- switch (msg->zlhdr_msgid) {
- case ZLMSGID_STATUSQ:
- {
- uint8 dlImagePreambleOffset;
- zlstatusR_t *reply = (zlstatusR_t *)cpr;
- paylSize = sizeof(zlstatusR_t);
- reply->zlsqR_state = s_State;
- reply->zlsqR_errorCode = EC_NO_ERROR;
- // report capabiltities and version
- reply->zlsqR_ProtocolVersion = ZLOAD_PROTOCOL_VERSION;
- reply->zlsqR_capabilties = ZLOAD_CAPABILTIES;
- cpr +=4;
- // populate the operational version values
- HalOADRead(PREAMBLE_OFFSET, (uint8 *)&preamble, sizeof(preamble_t), HAL_OAD_RC);
- cpr = osal_memcpy(cpr, &preamble.vers, ZL_IMAGE_ID_LENGTH);
- // do downloaded image if it's there
- osal_nv_read(PREAMBLE_NV_ID, 0, 1, &dlImagePreambleOffset);
- HalOADRead(dlImagePreambleOffset, (uint8 *)&preamble, sizeof(preamble_t), HAL_OAD_DL);
- if (preamble.vers != 0xFF)
- {
- cpr = osal_memcpy(cpr, &preamble.vers, ZL_IMAGE_ID_LENGTH);
- }
- else
- {
- osal_memset(cpr, 0, ZL_IMAGE_ID_LENGTH);
- cpr += ZL_IMAGE_ID_LENGTH;
- }
- cpr = osal_memcpy(cpr, &s_NextPacket, sizeof(s_NextPacket));
- osal_memcpy(cpr, &s_NumPktGet, sizeof(s_NumPktGet));
- }
- break;
- case ZLMSGID_SESSION_START:
- #if defined ZPORT
- // the pass through condition starts here, when a client tries
- // to begin a session with the dongle.
- if (s_State != ZLSTATE_IDLE) {
- ((zlbegsessR_t *)cpr)->zlbsR_errorCode = EC_BS_NOT_IDLE;
- }
- else if (s_serialMsg) {
- // somehow this came over the serial port and it isn't legal
- ((zlbegsessR_t *)cpr)->zlbsR_errorCode = EC_BS_NOT_SERVER;
- }
- else {
- // set mode. delay reply until we hear back from the Host
- s_PTSeqNum = msg->zlhdr_seqnum;
- s_PTClientInfo = *MSGpkt;
- s_SessionID = ((zlbegsessC_t *)cpc)->zlbsC_sessionID;
- if (zlPassOnStartSessionOK((uint8 *)msg)) {
- s_State = ZLSTATE_PASS_THROUGH;
- return;
- }
- else {
- ((zlbegsessR_t *)cpr)->zlbsR_errorCode = EC_BS_NO_MEM;
- }
- }
- #else
- if (!HalAdcCheckVdd(VDD_MIN_OAD))
- {
- ((zlbegsessR_t *)cpr)->zlbsR_errorCode = EC_BAD_VDD;
- }
- else
- do {
- uint8 dlImagePreambleOffset;
- zlbegsessR_t *reply = (zlbegsessR_t *)cpr;
- // assume we're OK and set up fixed part of reply here
- reply->zlbsR_blkSize = ZL_DATA_BLK_SIZE;
- reply->zlbsR_numBlks = ZL_NUM_DATA_BLKS;
- reply->zlbsR_state = s_State;
- reply->zlbsR_errorCode = EC_NO_ERROR;
- paylSize = sizeof(zlbegsessR_t);
- if (s_State != ZLSTATE_IDLE) {
- if (s_SessionID == ((zlbegsessC_t *)cpc)->zlbsC_sessionID)
- {
- // Ok - this must be a no ack retransmit or a retry.
- }
- else
- {
- reply->zlbsR_errorCode = EC_BS_NOT_IDLE;
- continue; // done
- }
- }
- // see if there is a DL image to send
- osal_nv_read(PREAMBLE_NV_ID, 0, 1, &dlImagePreambleOffset);
- HalOADRead(dlImagePreambleOffset, (uint8 *)&preamble, sizeof(preamble_t), HAL_OAD_DL);
- if (preamble.vers != 0xFFFF)
- {
- if (!memcmp(cpc, (uint8 *)&preamble.vers, ZL_IMAGE_ID_LENGTH)) {
- // image matches request.
- osal_memcpy(&reply->zlbsR_imgLen, &preamble.len, sizeof(uint32));
- s_State = ZLSTATE_SERVER;
- s_itype = HAL_OAD_DL;
- reply->zlbsR_preambleOffset = (uint8)PREAMBLE_OFFSET;
- continue; // done
- }
- }
- // no DL image. we know there's an operational image
- HalOADRead(PREAMBLE_OFFSET, (uint8 *)&preamble, sizeof(preamble_t), HAL_OAD_RC);
- if (!memcmp(cpc, (uint8 *)&preamble.vers, ZL_IMAGE_ID_LENGTH)) {
- // image matches request.
- osal_memcpy(&reply->zlbsR_imgLen, &preamble.len, sizeof(uint32));
- s_State = ZLSTATE_SERVER;
- s_itype = HAL_OAD_RC;
- reply->zlbsR_preambleOffset = (uint8)PREAMBLE_OFFSET;
- }
- else {
- reply->zlbsR_errorCode = EC_BS_NO_MATCHES;
- }
- } while (0);
- // if we're good to go, allocate the memory for the SD replies
- // this will make things more efficient during the transfer
- if (!((zlbegsessR_t *)cpr)->zlbsR_errorCode) {
- uint8 *cp;
- zlbegsessR_t *reply = (zlbegsessR_t *)cpr;
- // need memory for sending replies and for holding flash pages
- if (!(cp=osal_mem_alloc(sizeof(zlmhdr_t)+sizeof(zlsdR_t)))) {
- // oops -- none available. let Client decide what to do.
- s_State = ZLSTATE_IDLE;
- reply->zlbsR_errorCode = EC_BS_NO_MEM;
- }
- else {
- s_NumPktGet = (preamble.len + (ZL_DATA_BLK_SIZE*ZL_NUM_DATA_BLKS-1)) /
- (ZL_DATA_BLK_SIZE*ZL_NUM_DATA_BLKS);
- s_blkSize = ZL_DATA_BLK_SIZE * ZL_NUM_DATA_BLKS;
- s_NextPacket = 0;
- s_SessionID = ((zlbegsessC_t *)cpc)->zlbsC_sessionID;
- // set up other pointers
- s_sdreply = (zlmhdr_t *)cp;
- s_sdreply->zlhdr_msgid = ZLMSGID_SEND_DATA | ZLMSGID_REPLY_BIT;
- s_sdreply->zlhdr_msglen = sizeof(zlsdR_t);
- s_sdrpayload = (zlsdR_t *)(cp+sizeof(zlmhdr_t));
- DO_EVENT_CALLBACK(ZLCB_EVENT_OADBEGIN_SERVER);
- }
- }
- #endif
- break;
- case ZLMSGID_SESSION_TERM:
- {
- zlendsessR_t *reply = (zlendsessR_t *)cpr;
- reply->zlesR_state = s_State;
- reply->zlesR_errorCode = EC_NO_ERROR;
- // guard against terminating the wrong session
- if (((zlendsessC_t *)cpc)->zlesC_sessionID != s_SessionID) {
- // wrong session ID
- reply->zlesR_errorCode = EC_ES_BAD_SESS_ID;
- }
- #if defined ZPORT
- else if (s_serialMsg) {
- // somehow this came over the serial port and it isn't legal
- ((zlbegsessR_t *)cpr)->zlbsR_errorCode = EC_ES_NOT_SERVER;
- }
- #endif
- else {
- #if defined ZPORT
- if (ZLSTATE_PASS_THROUGH == s_State) {
- // everything is OK. pass this up to host if we're in pass-through mode
- // forward message to host
- zahdrin_t *zain = zlBuildExternalInboundSerialMSG(&s_PTClientInfo, (uint8 *)msg, sizeof(zlmhdr_t) + sizeof(zlendsessC_t));
- if (zain) {
- if (SUCCESS != osal_start_timerEx(oad_app_taskId, ZLOAD_XFER_DONE_EVT, SDR_WAIT_TO))
- {
- osal_set_event(oad_app_taskId, ZLOAD_XFER_DONE_EVT);
- }
- s_PTClientInfo = *MSGpkt;
- zlSendSerial((uint8 *)zain, SIZEOF_ZAIN_HDR + sizeof(zlmhdr_t) + sizeof(zlendsessC_t));
- osal_mem_free(zain);
- return;
- }
- else {
- reply->zlesR_errorCode = EC_ES_NO_MEM;
- }
- }
- #else
- if (s_State == ZLSTATE_SERVER) {
- // everything is OK.
- osal_set_event(oad_app_taskId, ZLOAD_XFER_DONE_EVT);
- }
- #endif
- else {
- // right session ID but I'm not the server
- reply->zlesR_errorCode = EC_ES_NOT_SERVER;
- }
- }
- }
- paylSize = sizeof(zlendsessR_t);
- break;
- case ZLMSGID_CLIENT_CMD:
- {
- zlclientR_t *reply = (zlclientR_t *)cpr;
- reply->zlclR_errorCode = EC_NO_ERROR;
- paylSize = sizeof(zlclientR_t);
- reply->zlclR_state = s_State;
- #if defined ZPORT
- // we can be the client only if the dongle code itself is being updated
- // and then only if the Host is the server
- if (!s_serialMsg) {
- reply->zlclR_errorCode = EC_CL_NOT_CLIENT;
- }
- else
- #endif
- if (!HalAdcCheckVdd(VDD_MIN_OAD))
- {
- reply->zlclR_errorCode = EC_BAD_VDD;
- }
- else
- if (s_State != ZLSTATE_IDLE) {
- if (!osal_memcmp(s_clientInfo, cpc, sizeof(zlclientC_t))) {
- reply->zlclR_errorCode = EC_CL_NOT_IDLE;
- }
- }
- #if (HAL_OAD_XNV_IS_INT && ((HAL_OAD_DL_OSET % HAL_FLASH_PAGE_SIZE) != 0))
- // Bug 2946 - HalXNVWrite() only triggers a page erase when the first byte of a
- // page boundary is written, so when dividing the available internal flash in half
- // results in a page being split in half, this remedial measure is necessary.
- else if (zlEraseHalfPage() != SUCCESS)
- {
- reply->zlclR_errorCode = EC_CL_NO_MEM;
- }
- #endif
- else {
- zlclientC_t *cmd = (zlclientC_t *)cpc;
- uint8 *cp;
- // need memory for holding client info, and current send-data cmd
- // do one alloc and set up the pointers
- cp = osal_mem_alloc(sizeof(zlclientC_t)+sizeof(zlmhdr_t)+sizeof(zlsdC_t));
- if (!cp) {
- // no more memory. let Commissioner decide what to do. maybe retry later.
- reply->zlclR_errorCode = EC_CL_NO_MEM;
- break;
- }
- else {
- // set up other pointers
- s_clientInfo = (zlclientC_t *)cp;
- s_sdcmd = (zlmhdr_t *)(cp+sizeof(zlclientC_t));
- s_sdcpayload = (zlsdC_t *)(cp+sizeof(zlclientC_t)+sizeof(zlmhdr_t));
- }
- // the info on the image to be downloaded and
- // the address of the Server is now saved both here
- // and in persistent memory
- osal_memcpy(s_clientInfo, cpc, sizeof(zlclientC_t));
- // populate destination address structure for convenience
- dstAddr.addrMode = afAddr16Bit;
- dstAddr.endPoint = cmd->zlclC_endp;
- osal_memcpy(&dstAddr.addr.shortAddr, &cmd->zlclC_nwk, sizeof(uint16));
- // set event to cause the session to begin
- osal_set_event(oad_app_taskId, ZLOAD_IS_CLIENT_EVT);
- }
- }
- break;
- case ZLMSGID_CODE_ENABLE:
- {
- zlceR_t *reply = (zlceR_t *)cpr;
- paylSize = sizeof(zlceR_t);
- reply->zlceR_state = s_State;
- #if defined ZPORT
- // we can enable code if the dongle code itself is being updated.
- if (!s_serialMsg) {
- reply->zlceR_errorCode = EC_CE_NOT_CLIENT;
- }
- else
- #endif
- if (s_State != ZLSTATE_IDLE) {
- reply->zlceR_errorCode = EC_CE_NOT_IDLE;
- }
- // see if we're supposed to enable the DL image. spec is in command payload
- // see if there is one...
- else {
- uint8 dlImagePreambleOset;
- osal_nv_read(PREAMBLE_NV_ID, 0, 1, &dlImagePreambleOset);
- HalOADRead(dlImagePreambleOset,(uint8 *)&preamble,sizeof(preamble_t),HAL_OAD_DL);
- if (preamble.vers != 0xFFFF) {
- // see if they match
- if (!memcmp(cpc, (uint8 *)&preamble.vers, ZL_IMAGE_ID_LENGTH)) {
- if (!HalAdcCheckVdd(VDD_MIN_OAD))
- {
- reply->zlceR_errorCode = EC_BAD_VDD;
- }
- else
- // DL image there and matches request, see if image is sane.
- if (SUCCESS == HalOADChkDL(dlImagePreambleOset)) {
- //set event to cause reset
- if (SUCCESS != osal_start_timerEx(oad_app_taskId, ZLOAD_CODE_ENABLE_EVT,
- SDC_WAIT_TO_ENABLE))
- {
- osal_set_event(oad_app_taskId, ZLOAD_CODE_ENABLE_EVT);
- }
- reply->zlceR_errorCode = EC_NO_ERROR;
- }
- else {
- reply->zlceR_errorCode = EC_CE_IMAGE_INSANE;
- }
- }
- else {
- // DL image there but doesn't match request
- reply->zlceR_errorCode = EC_CE_NO_MATCH;
- }
- }
- else {
- // no DL image
- reply->zlceR_errorCode = EC_CE_NO_IMAGE;
- }
- }
- }
- break;
- case ZLMSGID_SEND_DATA:
- #if defined ZPORT
- {
- zlsdR_t *reply = (zlsdR_t *)cpr;
- paylSize = sizeof(zlsdR_t);
- // do a sanity check.
- if (s_serialMsg) {
- reply->zlsdR_errorCode = EC_SD_NOT_SERVER;
- }
- else if (ZLSTATE_PASS_THROUGH == s_State) {
- // this should be good enough...
- if (s_PTClientInfo.srcAddr.addr.shortAddr != MSGpkt->srcAddr.addr.shortAddr) {
- // wrong client -- not the current client
- reply->zlsdR_errorCode = EC_SD_NOT_CLIENT;
- }
- else if (((zlsdC_t *)cpc)->zlsdC_sessionID != s_SessionID) {
- reply->zlsdR_errorCode = EC_SD_BAD_SESS_ID;
- }
- else {
- zahdrin_t *zain = zlBuildExternalInboundSerialMSG(&s_PTClientInfo, (uint8 *)msg, sizeof(zlmhdr_t) + sizeof(zlsdC_t));
- // forward message to host
- if (zain) {
- zlSendSerial((uint8 *)zain, SIZEOF_ZAIN_HDR + sizeof(zlmhdr_t) + sizeof(zlsdC_t));
- osal_mem_free(zain);
- // save the AF data. there may be AF parameters we need for the reply
- s_PTClientInfo = *MSGpkt;
- return;
- }
- else {
- reply->zlsdR_errorCode = EC_SD_NO_MEM;
- }
- }
- }
- else {
- reply->zlsdR_errorCode = EC_SD_NOT_SERVER;
- }
- }
- #else
- paylSize = sizeof(zlsdR_t);
- if (s_State != ZLSTATE_SERVER) {
- // this is the error case when we get a SD before we've started a session
- break;
- }
- s_sdrpayload->zlsdR_state = s_State;
- buf = (uint8 *)s_sdreply;
- if (((zlsdC_t *)cpc)->zlsdC_sessionID != s_SessionID) {
- s_sdrpayload->zlsdR_errorCode = EC_SD_BAD_SESS_ID;
- }
- else {
- // set error code first. it might get reset in the processing routine
- s_sdrpayload->zlsdR_errorCode = EC_NO_ERROR;
- // process the command
- zlProcessSDC((zlsdC_t *)cpc);
- }
- #endif
- break;
- case ZLMSGID_RESET:
- #if defined ZPORT
- // always legal if over serial port
- if (!s_serialMsg) {
- return;
- }
- else
- #endif
- {
- zlrstR_t *reply = (zlrstR_t *)cpr;
- reply->zlrstR_state = s_State;
- reply->zlrstR_errorCode = EC_NO_ERROR;
- }
- paylSize = sizeof(zlrstR_t);
- osal_set_event(oad_app_taskId, ZLOAD_RESET_EVT);
- break;
- default:
- return;
- }
- // the case above has filled in the payload. the header is the
- // same for all. go ahead and fill in header and send reply
- {
- zlmhdr_t *hdr = (zlmhdr_t *)buf;
- hdr->zlhdr_msgid = msg->zlhdr_msgid | ZLMSGID_REPLY_BIT;
- hdr->zlhdr_seqnum = msg->zlhdr_seqnum;
- hdr->zlhdr_msglen = paylSize;
- #if defined ZPORT
- if (!s_serialMsg) {
- #endif
- AF_DataRequest( &MSGpkt->srcAddr,
- afFindEndPointDesc( MSGpkt->endPoint),
- MSGpkt->clusterId,
- sizeof(zlmhdr_t) + paylSize, buf,
- &MSGpkt->cmd.TransSeqNumber,
- AF_DISCV_ROUTE, AF_DEFAULT_RADIUS );
- #if defined ZPORT
- } else {
- zahdrin_t *zain = zlBuildInternalInboundSerialMSG((uint8 *)hdr, sizeof(zlmhdr_t) + paylSize);
- if (zain) {
- zlSendSerial((uint8 *)zain, SIZEOF_ZAIN_HDR + sizeof(zlmhdr_t) + paylSize);
- osal_mem_free(zain);
- }
- }
- #else
- if ((buf != NULL) &&
- ((msg->zlhdr_msgid != ZLMSGID_SEND_DATA) || (s_State != ZLSTATE_SERVER)))
- {
- osal_mem_free(buf);
- }
- #endif
- }
- return;
- }
- #if !defined ZPORT
- /**********************************************************************************
- * @fn zlProcessSDC
- *
- * @brief Process the SDC command.
- *
- * @param cmd - A valid alsdC_t structure with valid data.
- *
- * @return none
- */
- static void zlProcessSDC(zlsdC_t *cmd)
- {
- uint16 reqPktNum;
- osal_memcpy(&reqPktNum, &cmd->zlsdC_pktNum, sizeof(uint16));
- // if the requested packet is the previous one the Client didn't get the
- // transmission for some reason. just resend the previous one. the data
- // are already in there. if we never got the command this test will fail.
- if (s_NextPacket && (reqPktNum == (s_NextPacket-1))) {
- return;
- }
- // make sure the request is otherwise valid
- if (!zlIsReqPacketNumOK(reqPktNum)) {
- s_sdrpayload->zlsdR_errorCode = EC_SD_BAD_PKT_NUM;
- return;
- }
- // Read data into reply buffer.
- HalOADRead((uint32)s_NextPacket * s_blkSize, s_sdrpayload->zlsdR_data,
- ZL_DATA_BLK_SIZE*ZL_NUM_DATA_BLKS, s_itype);
- // set packet number in reply
- osal_memcpy(&s_sdrpayload->zlsdR_pktNum, &reqPktNum, sizeof(uint16));
- s_NextPacket++;
- }
- /**********************************************************************************
- * @fn zlIsReqPacketNumOK
- *
- * @brief Check validity of resquested packet number as Server
- *
- * @param input
- * reqNum requested packet number
- *
- * @return 0: packet number request illegal
- * 1: packet number request is valid
- */
- static uint8 zlIsReqPacketNumOK(uint16 reqNum)
- {
- if (reqNum >= s_NumPktGet) {
- return 0;
- }
- return 1;
- }
- #endif
- /**********************************************************************************
- * @fn ZLOADApp_handleReply
- *
- * @brief Handle a normal ZLOAD reply
- *
- * @param input
- * msg pointer to ZLOAD message
- *
- * @return none.
- */
- static void ZLOADApp_handleReply(afIncomingMSGPacket_t *MSGpkt, zlmhdr_t *msg)
- {
- uint8 *cpr;
- #if defined ZPORT
- uint8 msgSize = 0;
- #endif
- #if !defined ZPORT
- // right reply?
- if (s_firstTx) {
- s_firstTx = 0;
- }
- else {
- if (msg->zlhdr_seqnum != s_lastTxSeqNum) {
- return;
- }
- if (msg->zlhdr_seqnum == s_lastSeen) {
- // duplicate reply to a resend
- return;
- }
- }
- s_lastSeen = msg->zlhdr_seqnum;
- #endif
- cpr = (uint8 *)msg + sizeof(zlmhdr_t); // offset of reply payload
- // generate replies to commands here. reply may generate another command out, for
- // example, if data are being transfered and the dvice is acting as client.
- // Commands handled here. replies in next routine
- // ignore reply bit on switch()
- switch (msg->zlhdr_msgid & (0xFF ^ ZLMSGID_REPLY_BIT)) {
- case ZLMSGID_STATUSQ:
- #if defined ZPORT
- msgSize = 20;
- // * * * NO BREAK * * *
- case ZLMSGID_CLIENT_CMD:
- case ZLMSGID_RESET:
- case ZLMSGID_CODE_ENABLE:
- if (!msgSize) {
- msgSize = 2;
- }
- // right now, only the host could have sent these -- the dongle never sends these
- // commands on its own. it's a proxy reply. forward it on...
- if (!s_serialMsg) {
- zahdrin_t *zain = zlBuildExternalInboundSerialMSG(MSGpkt, (uint8 *)msg, sizeof(zlmhdr_t) + msgSize);
- if (zain) {
- zlSendSerial((uint8 *)zain, SIZEOF_ZAIN_HDR + sizeof(zlmhdr_t) + msgSize);
- osal_mem_free(zain);
- }
- }
- #endif
- break;
- case ZLMSGID_SESSION_START:
- #if defined ZPORT
- // this can happen both in pass-through and client mode -- the dongle could be
- // getting updated firmware and is the client receiving the start session reply.
- // in any case we cannot get this reply over air. it has to have come from the Host
- if (!s_serialMsg) {
- break;
- }
- else if (ZLSTATE_PASS_THROUGH == s_State) {
- // pass reply back to original client
- msg->zlhdr_seqnum = s_PTSeqNum;
- AF_DataRequest( &s_PTClientInfo.srcAddr,
- afFindEndPointDesc( s_PTClientInfo.endPoint ),
- s_PTClientInfo.clusterId,
- sizeof(zlmhdr_t) + sizeof(zlbegsessR_t), (uint8 *)msg,
- &s_PTClientInfo.cmd.TransSeqNumber,
- AF_TX_OPTIONS_NONE, AF_DEFAULT_RADIUS );
- }
- else if (((zlbegsessR_t *)cpr)->zlbsR_errorCode) {
- // Server rejected the real client session. back to Idle state.
- osal_set_event(oad_app_taskId, ZLOAD_RESET_EVT);
- }
- // reply from Server to Begin Session command from Client
- else if (ZLSTATE_CLIENT != s_State) {
- // I didn't send it...ignore.
- break;
- }
- #else
- // reply from Server to Begin Session command from Client
- if (s_State != ZLSTATE_CLIENT) {
- // I didn't send it...ignore.
- break;
- }
- else if (((zlbegsessR_t *)cpr)->zlbsR_errorCode) {
- // Server rejected the session. back to Idle state.
- osal_set_event(oad_app_taskId, ZLOAD_RESET_EVT);
- }
- #endif
- else {
- // get length and make sure we have room
- uint32 imglen = ((zlbegsessR_t *)cpr)->zlbsR_imgLen;
- if (imglen > HalOADAvail()) {
- // no room. terminate session
- osal_set_event(oad_app_taskId, ZLOAD_XFER_DONE_EVT);
- }
- else {
- // TODO: The OAD Dongle Tool is broken and passes the wrong offset.
- //uint8 dlImagePreambleOffset = ((zlbegsessR_t *)cpr)->zlbsR_preambleOffset;
- //osal_nv_write(PREAMBLE_NV_ID, 0, 1, &dlImagePreambleOffset);
- s_blkSize = ((zlbegsessR_t *)cpr)->zlbsR_blkSize;
- s_blkSize *= ((zlbegsessR_t *)cpr)->zlbsR_numBlks;
- // figure out how many data packets to request.
- s_NumPktGet = (imglen+(s_blkSize-1)) / s_blkSize;
- s_NextPacket = 0;
- // request "next" (i.e., first) packet
- zlRequestNextDataPacket();
- }
- }
- break;
- case ZLMSGID_SESSION_TERM:
- #if defined ZPORT
- // pass it back if we're in pass-through mode
- if (s_serialMsg && (ZLSTATE_PASS_THROUGH == s_State)) {
- AF_DataRequest( &s_PTClientInfo.srcAddr,
- afFindEndPointDesc( s_PTClientInfo.endPoint),
- s_PTClientInfo.clusterId,
- sizeof(zlmhdr_t) + sizeof(zlendsessR_t), (uint8 *)msg,
- &s_PTClientInfo.cmd.TransSeqNumber,
- AF_TX_OPTIONS_NONE, AF_DEFAULT_RADIUS );
- // in any case, clean up
- osal_set_event(oad_app_taskId, ZLOAD_XFER_DONE_EVT);
- }
- #else
- // don't care. right now the Commisioner can't be
- // the client so it will never get a reply to the
- // terminate session command because it can't send
- // that command.
- #endif
- break;
- case ZLMSGID_SEND_DATA:
- #if defined ZPORT
- if (!s_serialMsg) {
- // reply should not be over air
- break;
- }
- else if (ZLSTATE_CLIENT == s_State) {
- // not a don't care if we're in client state
- zlProcessSDR((zlsdR_t *)cpr);
- }
- else if (ZLSTATE_PASS_THROUGH == s_State) {
- // forward to client
- AF_DataRequest( &s_PTClientInfo.srcAddr,
- afFindEndPointDesc( s_PTClientInfo.endPoint),
- s_PTClientInfo.clusterId,
- sizeof(zlmhdr_t) + sizeof(zlsdR_t), (uint8 *)msg,
- &s_PTClientInfo.cmd.TransSeqNumber,
- AF_TX_OPTIONS_NONE, AF_DEFAULT_RADIUS );
- }
- #else
- // not a don't care if we're in client state
- if (s_State == ZLSTATE_CLIENT) {
- zlProcessSDR((zlsdR_t *)cpr);
- }
- #endif
- break;
- default:
- // don't care
- break;
- }
- }
- /**********************************************************************************
- * @fn zlProcessSDR
- *
- * @brief Process the Send Data Reply as Client
- *
- * @param input
- * sdr pointer to received Send Data Reply
- *
- * @return none
- */
- static void zlProcessSDR(zlsdR_t *sdr)
- {
- uint16 tmp;
- osal_memcpy(&tmp, &sdr->zlsdR_pktNum, sizeof(uint16));
- // is this the right packet?
- if (s_NextPacket > tmp)
- {
- return; // we've already seen this one. ignore it
- }
- else if (s_NextPacket < tmp) {
- // uh oh. we've missed one. kill session...
- osal_set_event(oad_app_taskId, ZLOAD_XFER_DONE_EVT);
- return;
- }
- else if (sdr->zlsdR_errorCode) {
- // there are no data here. just ignaore the packet. if things
- // are relly screwed up the timer will expire and we'll quit.
- return;
- }
- else if (!HalAdcCheckVdd(VDD_MIN_OAD))
- {
- osal_set_event(oad_app_taskId, ZLOAD_XFER_DONE_EVT);
- return;
- }
- // Store the data in Xtra-NV.
- HalOADWrite((uint32)s_NextPacket * s_blkSize, sdr->zlsdR_data, s_blkSize, HAL_OAD_DL);
- s_NextPacket++; // OK to increment next packet number now.
- zlRequestNextDataPacket(); // ask for next packet
- }
- /**********************************************************************************
- * @fn zlRequestNextDataPacket
- *
- * @brief Set up the next data packet request. Takes care of knowing when
- * transfer is done. Takes care of retry timer.
- *
- * @param none
- *
- * @return none
- */
- static void zlRequestNextDataPacket()
- {
- if (s_NextPacket >= s_NumPktGet) {
- osal_set_event(oad_app_taskId, ZLOAD_XFER_DONE_EVT);
- // kill response timeout check
- osal_stop_timerEx(oad_app_taskId, ZLOAD_SDRTIMER_EVT);
- return;
- }
- #if defined ZPORT
- s_sdcpayload->zlsdC_pktNum = s_NextPacket;
- s_sdcmd->zlhdr_seqnum = ++s_lastSeqNum;
- {
- zahdrin_t *zain = zlBuildInternalInboundSerialMSG((uint8 *)s_sdcmd, sizeof(zlmhdr_t) + sizeof(zlsdC_t));
- if (zain) {
- zlSendSerial((uint8 *)zain, SIZEOF_ZAIN_HDR + sizeof(zlmhdr_t) + sizeof(zlsdC_t));
- osal_mem_free(zain);
- }
- }
- #else
- osal_memcpy(&s_sdcpayload->zlsdC_pktNum, &s_NextPacket, sizeof(uint16));
- s_sdcmd->zlhdr_seqnum = ++s_lastTxSeqNum;
- zlSendCommand(sizeof(zlmhdr_t) + sizeof(zlsdC_t), (uint8 *)s_sdcmd);
- #endif
- if (SUCCESS != osal_start_timerEx(oad_app_taskId, ZLOAD_SDRTIMER_EVT, SDR_WAIT_TO))
- {
- osal_set_event(oad_app_taskId, ZLOAD_SDRTIMER_EVT);
- }
- s_SDCRetryCount = SDC_RETRY_COUNT;
- // set timeout timer
- // need osal timer resource and set event flag and need a method to process timeout event
- return;
- }
- /**********************************************************************************
- * @fn zlCleanupOnReset
- *
- * @brief ZLOAD reset occurred. Free resources and reset state machine and other
- * supporting constructs
- *
- * @param none
- *
- * @return none
- */
- static void zlCleanupOnReset()
- {
- #if !defined ZPORT
- if (ZLSTATE_CLIENT == s_State) {
- DO_EVENT_CALLBACK(ZLCB_EVENT_OADEND_CLIENT);
- }
- else if (ZLSTATE_SERVER == s_State) {
- DO_EVENT_CALLBACK(ZLCB_EVENT_OADEND_SERVER);
- }
- #endif
- zlResetState();
- }
- /**************************************************************************************
- * @fn zlCleanupOnXferDone
- *
- * @brief Data transfer session complete (not necessarily correctly). Free resources
- * and reset state machine and other supporting constructs. Send Terminate
- * Session command to Server.
- *
- * @param none
- *
- * @return none
- */
- static void zlCleanupOnXferDone()
- {
- #if defined ZPORT
- if (ZLSTATE_PASS_THROUGH == s_State) {
- s_State = ZLSTATE_IDLE;
- return;
- }
- #endif
- // check for flashing last block and send Session Terminate command
- if (ZLSTATE_CLIENT == s_State) {
- zlmhdr_t *hdr = osal_mem_alloc(sizeof(zlmhdr_t) + sizeof(zlendsessC_t));
- if (hdr) {
- zlendsessC_t *cmd = (zlendsessC_t *)((uint8 *)hdr + sizeof(zlmhdr_t));
- hdr->zlhdr_msgid = ZLMSGID_SESSION_TERM;
- hdr->zlhdr_msglen = sizeof(zlendsessC_t);
- cmd->zlesC_sessionID = s_SessionID;
- hdr->zlhdr_seqnum = ++s_lastTxSeqNum;
- #if defined ZPORT
- {
- zahdrin_t *zain = zlBuildInternalInboundSerialMSG((uint8 *)hdr, sizeof(zlmhdr_t) + sizeof(zlendsessC_t));
- if (zain) {
- zlSendSerial((uint8 *)zain, SIZEOF_ZAIN_HDR + sizeof(zlmhdr_t) + sizeof(zlendsessC_t));
- osal_mem_free(zain);
- }
- }
- #else
- zlSendCommand(sizeof(zlmhdr_t) + sizeof(zlendsessC_t), (uint8 *)hdr);
- #endif
- osal_mem_free(hdr);
- }
- #if !defined ZPORT
- DO_EVENT_CALLBACK(ZLCB_EVENT_OADEND_CLIENT);
- #endif
- }
- #if !defined ZPORT
- else if (ZLSTATE_SERVER == s_State) {
- DO_EVENT_CALLBACK(ZLCB_EVENT_OADEND_SERVER);
- }
- #endif
- zlResetState();
- }
- /**************************************************************************************
- * @fn zlStartClientSession
- *
- * @brief We have been commanded to be in the Client role. Set up to start the
- * session with the Server by sending the Begin Session command
- *
- * @param none
- *
- * @return none
- */
- static void zlStartClientSession()
- {
- uint8 *buf;
- // we already have Server info. Contact Server to set up session
- if (buf=osal_mem_alloc(sizeof(zlmhdr_t) + sizeof(zlbegsessC_t))) {
- zlmhdr_t *hdr = (zlmhdr_t *)buf;
- zlbegsessC_t *cmd = (zlbegsessC_t *)((uint8 *)buf+sizeof(zlmhdr_t));
- // initialize session id as lsb of IEEE address
- if (!s_SessionID) {
- uint8 addr[Z_EXTADDR_LEN];
- ZMacGetReq(ZMacExtAddr, addr);
- s_SessionID = addr[0];
- }
- s_State = ZLSTATE_CLIENT;
- s_SessionID++;
- hdr->zlhdr_msgid = ZLMSGID_SESSION_START;
- hdr->zlhdr_seqnum = ++s_lastTxSeqNum;
- hdr->zlhdr_msglen = sizeof(zlbegsessC_t);
- osal_memcpy(&cmd->zlbsC_ver, &s_clientInfo->zlclC_ver, sizeof(uint16));
- osal_memcpy(&cmd->zlbsC_manu, &s_clientInfo->zlclC_manu, sizeof(uint16));
- osal_memcpy(&cmd->zlbsC_prod, &s_clientInfo->zlclC_prod, sizeof(uint16));
- cmd->zlbsC_sessionID = s_SessionID;
- s_NextPacket = 0;
- // populate session ID element in the Send data payload
- s_sdcpayload->zlsdC_sessionID = s_SessionID;
- // set up SD command header
- s_sdcmd->zlhdr_msgid = ZLMSGID_SEND_DATA;
- s_sdcmd->zlhdr_msglen = sizeof(zlsdC_t);
- #if defined ZPORT
- {
- zahdrin_t *zain = zlBuildInternalInboundSerialMSG((uint8 *)hdr, sizeof(zlmhdr_t) + sizeof(zlbegsessC_t));
- if (zain) {
- zlSendSerial((uint8 *)zain, SIZEOF_ZAIN_HDR + sizeof(zlmhdr_t) + sizeof(zlbegsessC_t));
- osal_mem_free(zain);
- }
- }
- #else
- if (zlSendCommand(sizeof(zlmhdr_t) + sizeof(zlbegsessC_t), buf))
- {
- }
- #endif
- osal_mem_free(buf);
- DO_EVENT_CALLBACK(ZLCB_EVENT_OADBEGIN_CLIENT);
- }
- else {
- // we couldn't send the Begin Session command. go back to Idle state.
- osal_set_event(oad_app_taskId, ZLOAD_RESET_EVT);
- }
- return;
- }
- #if !defined ZPORT
- /**************************************************************************************
- * @fn zlSendCommand
- *
- * @brief Send command to destination. Can be either over air or to the Host. This
- * routine takes care of the context.
- *
- * @param input
- * length length of message being sent
- * buf pointer to message
- *
- * @return 0: successful send
- * 1: unseccessful send (return code for AF layer)
- */
- static uint8 zlSendCommand(uint8 length, uint8 *buf)
- {
- uint8 rc;
- rc = AF_DataRequest( &dstAddr,
- afFindEndPointDesc( OAD_epDesc.endPoint ),
- OAD_CLUSTERID_CS,
- length, buf,
- &transId,
- AF_DISCV_ROUTE, DEF_NWK_RADIUS );
- return rc;
- }
- #endif
- /**************************************************************************************
- * @fn zlResendSDC
- *
- * @brief Resend the previous Send Data Command because a repply was not received
- * before a timeout.
- *
- * @param none
- *
- * @return none.
- */
- static void zlResendSDC()
- {
- if (s_State != ZLSTATE_CLIENT) {
- // late expiration -- don't care
- return;
- }
- if (--s_SDCRetryCount) {
- #if defined ZPORT
- s_sdcmd->zlhdr_seqnum = ++s_lastSeqNum;
- {
- zahdrin_t *zain = zlBuildInternalInboundSerialMSG((uint8 *)s_sdcmd, sizeof(zlmhdr_t) + sizeof(zlsdC_t));
- if (zain) {
- zlSendSerial((uint8 *)zain, SIZEOF_ZAIN_HDR + sizeof(zlmhdr_t) + sizeof(zlsdC_t));
- osal_mem_free(zain);
- }
- }
- #else
- // the static structure still contains the last packet number to be requested.
- // the only way the packet number gets bumped is if a reply is received.
- zlSendCommand(sizeof(zlmhdr_t) + sizeof(zlsdC_t), (uint8 *)s_sdcmd);
- #endif
- if (SUCCESS != osal_start_timerEx(oad_app_taskId, ZLOAD_SDRTIMER_EVT, SDR_WAIT_TO))
- {
- osal_set_event(oad_app_taskId, ZLOAD_SDRTIMER_EVT);
- }
- }
- else {
- // too many retries. abandon session.
- osal_set_event(oad_app_taskId, ZLOAD_XFER_DONE_EVT);
- }
- return;
- }
- #if !defined ZPORT
- /**************************************************************************************
- * @fn oadAppRegisterCB
- *
- * @brief Register a callback to be referenced when OAD events occur.
- *
- * @param input
- * pCBFunction pointer to void function with an unsigned short argument.
- * eventMask bit mask of events for which the callback should be invoked.
- *
- * When the callback is invoked its argument will indicate via the bit mask argument
- * which event occurred. A null pointer or a null bit mask will have the effect of
- * deregistration.
- *
- * @return none.
- */
- void oadAppRegisterCB(void (*pCBFunction)(uint16), uint16 eventMask)
- {
- s_pCallback = pCBFunction;
- s_eventMask = eventMask;
- return;
- }
- #endif
- /**************************************************************************************************
- * @fn zlResetState
- *
- * @brief This function frees any memory in use and resets the zl state info.
- *
- * input parameters
- *
- * None.
- *
- * output parameters
- *
- * None.
- *
- * @return None.
- **************************************************************************************************
- */
- static void zlResetState(void)
- {
- osal_stop_timerEx(oad_app_taskId, ZLOAD_SDRTIMER_EVT); // kill response timeout check
- if (s_sdreply)
- {
- osal_mem_free(s_sdreply);
- s_sdreply = NULL;
- }
- if (s_clientInfo)
- {
- osal_mem_free(s_clientInfo);
- s_clientInfo = NULL;
- }
- s_State = ZLSTATE_IDLE;
- s_NextPacket = 0;
- s_NumPktGet = 0;
- }
- #if defined ZPORT
- /*********************************************************************
- * @fn ZLOADApp_SerialMSGCB
- *
- * @brief Message from Host application. It's a command, a reply,
- * or a proxy command. Send it on appropriately
- *
- * @param input
- * inMsg pointer to incoming message
- *
- * @return none
- */
- static void ZLOADApp_SerialMessageMSGCB(zahdrout_t *zaout)
- {
- zlmhdr_t *zlhdr = (zlmhdr_t *)zaout->zaproxy_payload;
- // is this for me?
- if (zaout->zaproxy_nwkAddr == s_myNwkAddr) {
- // is this a reply?
- if (zlhdr->zlhdr_msgid & ZLMSGID_REPLY_BIT) {
- ZLOADApp_handleReply(NULL, zlhdr);
- }
- else {
- ZLOADApp_handleCommand(NULL, zlhdr);
- }
- }
- else {
- // it's a proxy command
- zlZArchitectProxyMsg(zaout);
- }
- return;
- }
- /*********************************************************************
- * @fn zlSendSerial
- *
- * @brief Prepare message outgoing over serial port.
- * malloc and copy to add serial encapsulation.
- *
- * @param input
- * buf pointer to ougoing message buffer
- * len length of message
- *
- * @return none
- */
- static void zlSendSerial(uint8 *buf, uint8 len)
- {
- uint8 *nbuf;
- if ((nbuf=osal_mem_alloc(len+1))) {
- osal_memcpy(nbuf+1, buf, len);
- *nbuf = OAD_ENDPOINT;
- #if !defined(ZTOOL_SUPPORT)
- MTProcessAppRspMsg(nbuf, len + 1);
- #else
- // ZTool expects an 81 byte message
- MTProcessAppRspMsg(nbuf, 81);
- #endif
- osal_mem_free(nbuf);
- }
- return;
- }
- /****************************************************************************
- * @fn zlZArchitectProxyCommand
- *
- * @brief Send command to target device on behalf of ZArchitect Host App
- *
- * @param input
- * info pointer to ZArchitect proxy message
- *
- * @return none
- */
- static void zlZArchitectProxyMsg(zahdrout_t *info)
- {
- afAddrType_t taddr;
- zlmhdr_t *zlhdr = (zlmhdr_t *)info->zaproxy_payload;
- // only certain outgoing messages are valid proxy commands
- switch (zlhdr->zlhdr_msgid) {
- case ZLMSGID_SESSION_START:
- case ZLMSGID_SESSION_TERM:
- case ZLMSGID_SEND_DATA:
- return;
- }
- // fill in address info
- taddr.addrMode = afAddr16Bit;
- taddr.endPoint = info->zaproxy_endp;
- taddr.addr.shortAddr = info->zaproxy_nwkAddr;
- AF_DataRequest( &taddr,
- afFindEndPointDesc( info->zaproxy_endp ),
- info->zaproxy_ClusterID,
- info->zaproxy_msglen, info->zaproxy_payload,
- &transId,
- AF_TX_OPTIONS_NONE, DEF_NWK_RADIUS );
- }
- // start a session with the host on behalf of the client from which
- // the start session was received. do this by sending self a client
- // command using the start session parameters. ZLOAD will think it
- // is a client message coming from the host asking it to come get
- // the image being requested by the real client.
- static uint8 zlPassOnStartSessionOK(uint8 *msg)
- {
- zahdrin_t *zamsgin;
- // forward the Begin Session command
- zamsgin = zlBuildExternalInboundSerialMSG(&s_PTClientInfo, msg, sizeof(zlmhdr_t) + sizeof(zlbegsessC_t));
- if (!zamsgin) {
- return 0;
- }
- zlSendSerial((uint8 *)zamsgin, SIZEOF_ZAIN_HDR + sizeof(zlmhdr_t) + sizeof(zlbegsessC_t));
- osal_mem_free(zamsgin);
- return 1;
- }
- // inbound messages can be built from address information gleaned from the client
- // during a pass-through session setup. but there can also be inbound messages
- // such as status replies that are not part of any ongoing client session. in this
- // case the address information comes from the AF message. in either case this
- // information is requried to populate the header for for the host.
- static zahdrin_t *zlBuildExternalInboundSerialMSG(afIncomingMSGPacket_t *addressInfo, uint8 *zlmsg, uint8 len)
- {
- zahdrin_t *zamsgin;
- // build message
- zamsgin = (zahdrin_t *)osal_mem_alloc(SIZEOF_ZAIN_HDR + len);
- if (!zamsgin) {
- return 0;
- }
- zamsgin->zaproxy_nwkAddr = addressInfo->srcAddr.addr.shortAddr;
- zamsgin->zaproxy_endp = addressInfo->endPoint;
- zamsgin->zaproxy_ClusterID = addressInfo->clusterId;
- zamsgin->zaproxy_msglen = len;
- osal_memcpy(zamsgin->zaproxy_payload, zlmsg, len);
- return zamsgin;
- }
- static zahdrin_t *zlBuildInternalInboundSerialMSG(uint8 *zlmsg, uint8 len)
- {
- zahdrin_t *zamsgin;
- // build message
- zamsgin = (zahdrin_t *)osal_mem_alloc(SIZEOF_ZAIN_HDR + len);
- if (!zamsgin) {
- return 0;
- }
- zamsgin->zaproxy_nwkAddr = s_myNwkAddr;
- zamsgin->zaproxy_endp = OAD_ENDPOINT;
- zamsgin->zaproxy_ClusterID = OAD_CLUSTERID_CS;
- zamsgin->zaproxy_msglen = len;
- osal_memcpy(zamsgin->zaproxy_payload, zlmsg, len);
- return zamsgin;
- }
- /*********************************************************************
- * @fn zlHandleKeys
- *
- * @brief Handles all key events for this device.
- *
- * @param shift - true if in shift/alt.
- * @param keys - bit field for key events. Valid entries:
- * EVAL_SW4
- * EVAL_SW3
- * EVAL_SW2
- * EVAL_SW1
- *
- * @return none
- */
- static void zlHandleKeys(uint8 shift, uint8 keys)
- {
- // Shift is used to make each button/switch dual purpose.
- if ( shift )
- {
- if ( keys & HAL_KEY_SW_1 )
- {
- }
- if ( keys & HAL_KEY_SW_2 )
- {
- }
- if ( keys & HAL_KEY_SW_3 )
- {
- }
- if ( keys & HAL_KEY_SW_4 )
- {
- }
- }
- else
- {
- if ( keys & HAL_KEY_SW_1 )
- {
- mtxMode = TRUE;
- }
- if ( keys & HAL_KEY_SW_2 )
- {
- }
- if ( keys & HAL_KEY_SW_3 )
- {
- mtxMode = FALSE;
- }
- if ( keys & HAL_KEY_SW_4 )
- {
- }
- }
- }
- #else
- #if (HAL_OAD_XNV_IS_INT && ((HAL_OAD_DL_OSET % HAL_FLASH_PAGE_SIZE) != 0))
- // Bug 2946 - HalXNVWrite() only triggers a page erase when the first byte of a page
- // boundary is written, so when dividing the available internal flash in half results in a
- // page being split in half, this remedial measure is necessary.
- static Status_t zlEraseHalfPage(void)
- {
- const uint16 hPgSz = HAL_FLASH_PAGE_SIZE / 2;
- // HalXNVRead/Write routines add HAL_OAD_DL_OSET to the 'addr' parameter, so pass in a 'negative'.
- const uint32 addr = 0L - hPgSz;
- uint8 *pBuf = osal_mem_alloc(hPgSz);
- if (NULL == pBuf)
- {
- return FAILURE;
- }
- HalXNVRead(addr, pBuf, hPgSz);
- // This triggers the full page erase and restores the lower half.
- HalXNVWrite(addr, pBuf, hPgSz);
- osal_mem_free(pBuf);
- return SUCCESS;
- }
- #endif
- #endif
- #pragma diag_default=Pa039
|