123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463 |
- /******************************************************************************
- Filename: zcl_ota.c
- Revised: $Date: 2011-07-18 05:10:28 -0700 (Mon, 18 Jul 2011) $
- Revision: $Revision: 26827 $
- Description: Zigbee Cluster Library - Over-the-Air Upgrade Cluster ( OTA )
- Copyright 2010-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 "ZComDef.h"
- #include "OSAL.h"
- #include "zcl.h"
- #include "zcl_general.h"
- #include "zcl_ota.h"
- #include "ota_common.h"
- #include "hal_lcd.h"
- #include "hal_led.h"
- #include "hal_ota.h"
- #include "MT_OTA.h"
- #include "ZDProfile.h"
- #include "ZDObject.h"
- #if defined ( INTER_PAN )
- #include "stub_aps.h"
- #endif
- #if defined OTA_MMO_SIGN
- #include "ota_signature.h"
- #endif
- /******************************************************************************
- * MACROS
- */
- /******************************************************************************
- * CONSTANTS
- */
- #define OTA_MAX_TRANSACTIONS 4
- #define OTA_TRANSACTION_EXPIRATION 1500
- #define ZCL_OTA_HDR_LEN_OFFSET 6 // Header length location in OTA upgrade image
- #define ZCL_OTA_STK_VER_OFFSET 18 // Stack version location in OTA upgrade image
- /******************************************************************************
- * GLOBAL VARIABLES
- */
- // OTA attribute variables
- uint8 zclOTA_UpgradeServerID[Z_EXTADDR_LEN];
- uint32 zclOTA_FileOffset = 0xFFFFFFFF;
- uint32 zclOTA_CurrentFileVersion = 0xFFFFFFFF;
- uint16 zclOTA_CurrentZigBeeStackVersion;
- uint32 zclOTA_DownloadedFileVersion = 0xFFFFFFFF;
- uint16 zclOTA_DownloadedZigBeeStackVersion = 0xFFFF;
- uint8 zclOTA_ImageUpgradeStatus;
- // Other OTA variables
- uint16 zclOTA_ManufacturerId; // Manufacturer ID
- uint16 zclOTA_ImageType; // Image type
- afAddrType_t zclOTA_serverAddr; // Server address
- uint8 zclOTA_AppTask = 0xFF; // Callback Task ID
- zclOTA_QueryImageRspParams_t queryResponse; // Global variable for sent query response
- /******************************************************************************
- * LOCAL VARIABLES
- */
- // Other OTA variables
- // Task ID
- static uint8 zclOTA_TaskID;
- // Sequence number
- static uint8 zclOTA_SeqNo = 0;
- static uint8 zclOTA_Permit = TRUE;
- #if defined OTA_MMO_SIGN
- static OTA_MmoCtrl_t zclOTA_MmoHash;
- static uint8 zclOTA_DataToHash[OTA_MMO_HASH_SIZE];
- static uint8 zclOTA_HashPos;
- static uint8 zclOTA_SignerIEEE[Z_EXTADDR_LEN];
- static uint8 zclOTA_SignatureData[OTA_SIGNATURE_LEN];
- static uint8 zclOTA_Certificate[OTA_CERTIFICATE_LEN];
- #endif // OTA_MMO_SIGN
- #if (defined OTA_CLIENT) && (OTA_CLIENT == TRUE)
- static uint32 zclOTA_DownloadedImageSize; // Downloaded image size
- static uint16 zclOTA_HeaderLen; // Image header length
- static uint16 zclOTA_UpdateDelay;
- static zclOTA_FileID_t zclOTA_CurrentDlFileId;
- static uint16 zclOTA_ElementTag;
- static uint32 zclOTA_ElementLen;
- static uint32 zclOTA_ElementPos;
- // Retry counters
- static uint8 zclOTA_BlockRetry;
- static uint8 zclOTA_UpgradeEndRetry;
- static uint8 zclOTA_ClientPdState;
- // OTA Header Magic Number Bytes
- static const uint8 zclOTA_HdrMagic[] = {0x1E, 0xF1, 0xEE, 0x0B};
- #endif // OTA_CLIENT
- /******************************************************************************
- * LOCAL FUNCTIONS
- */
- static ZStatus_t zclOTA_HdlIncoming( zclIncoming_t *pInMsg );
- #if (defined OTA_CLIENT) && (OTA_CLIENT == TRUE)
- static void zclOTA_StartTimer(uint16 eventId, uint32 minutes);
- static ZStatus_t sendImageBlockReq(afAddrType_t *dstAddr);
- static void zclOTA_ProcessZDOMsgs( zdoIncomingMsg_t *pMsg );
- static void zclOTA_ImageBlockWaitExpired(void);
- static void zclOTA_UpgradeComplete(uint8 status);
- static uint8 zclOTA_CmpFileId(zclOTA_FileID_t *f1, zclOTA_FileID_t *f2);
- static uint8 zclOTA_ProcessImageData(uint8 *pData, uint8 len);
- static ZStatus_t zclOTA_SendQueryNextImageReq( afAddrType_t *dstAddr, zclOTA_QueryNextImageReqParams_t *pParams );
- static ZStatus_t zclOTA_SendImageBlockReq( afAddrType_t *dstAddr, zclOTA_ImageBlockReqParams_t *pParams );
- static ZStatus_t zclOTA_SendUpgradeEndReq( afAddrType_t *dstAddr, zclOTA_UpgradeEndReqParams_t *pParams );
- static ZStatus_t zclOTA_ClientHdlIncoming( zclIncoming_t *pInMsg );
- #endif // OTA_CLIENT
- #if (defined OTA_SERVER) && (OTA_SERVER == TRUE)
- static ZStatus_t zclOTA_SendQueryNextImageRsp( afAddrType_t *dstAddr, zclOTA_QueryImageRspParams_t *pParams );
- static ZStatus_t zclOTA_SendImageBlockRsp( afAddrType_t *dstAddr, zclOTA_ImageBlockRspParams_t *pParams );
- static ZStatus_t zclOTA_SendUpgradeEndRsp( afAddrType_t *dstAddr, zclOTA_UpgradeEndRspParams_t *pParams );
- static ZStatus_t zclOTA_SendQuerySpecificFileRsp( afAddrType_t *dstAddr, zclOTA_QueryImageRspParams_t *pParams );
- static ZStatus_t zclOTA_Srv_QueryNextImageReq(afAddrType_t *pSrcAddr, zclOTA_QueryNextImageReqParams_t *pParam);
- static ZStatus_t zclOTA_Srv_ImageBlockReq(afAddrType_t *pSrcAddr, zclOTA_ImageBlockReqParams_t *pParam);
- static ZStatus_t zclOTA_Srv_ImagePageReq(afAddrType_t *pSrcAddr, zclOTA_ImagePageReqParams_t *pParam);
- static ZStatus_t zclOTA_Srv_UpgradeEndReq(afAddrType_t *pSrcAddr, zclOTA_UpgradeEndReqParams_t *pParam);
- static ZStatus_t zclOTA_Srv_QuerySpecificFileReq(afAddrType_t *pSrcAddr, zclOTA_QuerySpecificFileReqParams_t *pParam);
- static void zclOTA_ProcessNextImgRsp(uint8* pMSGpkt, zclOTA_FileID_t *pFileId, afAddrType_t *pAddr);
- static void zclOTA_ProcessFileReadRsp(uint8* pMSGpkt, zclOTA_FileID_t *pFileId, afAddrType_t *pAddr);
- static void zclOTA_ServerHandleFileSysCb(OTA_MtMsg_t* pMSGpkt);
- static ZStatus_t zclOTA_ServerHdlIncoming( zclIncoming_t *pInMsg );
- #endif // OTA_SERVER
- /******************************************************************************
- * OTA ATTRIBUTE DEFINITIONS - Uses REAL cluster IDs
- */
- #define ZCL_OTA_MAX_ATTRIBUTES 7
- CONST zclAttrRec_t zclOTA_Attrs[ZCL_OTA_MAX_ATTRIBUTES] =
- {
- {
- ZCL_CLUSTER_ID_OTA, // Cluster IDs - defined in the foundation (ie. zcl.h)
- { // Attribute record
- ATTRID_UPGRADE_SERVER_ID, // Attribute ID - Found in Cluster Library header (ie. zcl_general.h)
- ZCL_DATATYPE_IEEE_ADDR, // Data Type - found in zcl.h
- ACCESS_CONTROL_READ, // Variable access control - found in zcl.h
- (void *)&zclOTA_UpgradeServerID // Pointer to attribute variable
- }
- },
- {
- ZCL_CLUSTER_ID_OTA,
- { // Attribute record
- ATTRID_FILE_OFFSET,
- ZCL_DATATYPE_UINT32,
- ACCESS_CONTROL_READ,
- (void *)&zclOTA_FileOffset
- }
- },
- {
- ZCL_CLUSTER_ID_OTA,
- { // Attribute record
- ATTRID_CURRENT_FILE_VERSION,
- ZCL_DATATYPE_UINT32,
- ACCESS_CONTROL_READ,
- (void *)&zclOTA_CurrentFileVersion
- }
- },
- {
- ZCL_CLUSTER_ID_OTA,
- { // Attribute record
- ATTRID_CURRENT_ZIGBEE_STACK_VERSION,
- ZCL_DATATYPE_UINT16,
- ACCESS_CONTROL_READ,
- (void *)&zclOTA_CurrentZigBeeStackVersion
- }
- },
- {
- ZCL_CLUSTER_ID_OTA,
- { // Attribute record
- ATTRID_DOWNLOADED_FILE_VERSION,
- ZCL_DATATYPE_UINT32,
- ACCESS_CONTROL_READ,
- (void *)&zclOTA_DownloadedFileVersion
- }
- },
- {
- ZCL_CLUSTER_ID_OTA,
- { // Attribute record
- ATTRID_DOWNLOADED_ZIGBEE_STACK_VERSION,
- ZCL_DATATYPE_UINT16,
- ACCESS_CONTROL_READ,
- (void *)&zclOTA_DownloadedZigBeeStackVersion
- }
- },
- {
- ZCL_CLUSTER_ID_OTA,
- { // Attribute record
- ATTRID_IMAGE_UPGRADE_STATUS,
- ZCL_DATATYPE_UINT8,
- ACCESS_CONTROL_READ,
- (void *)&zclOTA_ImageUpgradeStatus
- }
- }
- };
- /******************************************************************************
- * OTA SIMPLE DESCRIPTOR
- */
- #ifndef OTA_HA
- #define ZCL_OTA_MAX_OPTIONS 1
- zclOptionRec_t zclOta_Options[ZCL_OTA_MAX_OPTIONS] =
- {
- {
- ZCL_CLUSTER_ID_OTA,
- ( AF_EN_SECURITY | AF_ACK_REQUEST ),
- },
- };
- #endif // OTA_HA
- #if defined OTA_SERVER && (OTA_SERVER == TRUE)
- // Cluster ID list for match descriptor of the OTA Server.
- #define ZCL_OTA_MAX_INCLUSTERS 1
- const cId_t zclOTA_InClusterList[ZCL_OTA_MAX_INCLUSTERS] =
- {
- ZCL_CLUSTER_ID_OTA
- };
- #else
- #define ZCL_OTA_MAX_INCLUSTERS 0
- #define zclOTA_InClusterList NULL
- #endif // OTA_SERVER
- #if defined OTA_CLIENT && (OTA_CLIENT == TRUE)
- // Cluster ID list for match descriptor of the OTA Client.
- #define ZCL_OTA_MAX_OUTCLUSTERS 1
- const cId_t zclOTA_OutClusterList[ZCL_OTA_MAX_OUTCLUSTERS] =
- {
- ZCL_CLUSTER_ID_OTA
- };
- #else
- #define ZCL_OTA_MAX_OUTCLUSTERS 0
- #define zclOTA_OutClusterList NULL
- #endif // OTA_CLIENT
- SimpleDescriptionFormat_t zclOTA_SimpleDesc =
- {
- ZCL_OTA_ENDPOINT, // int Endpoint;
- ZCL_OTA_SAMPLE_PROFILE_ID, // uint16 AppProfId[2];
- ZCL_OTA_SAMPLE_DEVICEID, // uint16 AppDeviceId[2];
- ZCL_OTA_DEVICE_VERSION, // int AppDevVer:4;
- ZCL_OTA_FLAGS, // int AppFlags:4;
- ZCL_OTA_MAX_INCLUSTERS, // byte AppNumInClusters;
- (cId_t *)zclOTA_InClusterList, // byte *pAppInClusterList;
- ZCL_OTA_MAX_OUTCLUSTERS, // byte AppNumInClusters;
- (cId_t *)zclOTA_OutClusterList // byte *pAppInClusterList;
- };
- // Endpoint for OTA Cluster
- static endPointDesc_t zclOTA_Ep =
- {
- ZCL_OTA_ENDPOINT,
- &zcl_TaskID,
- (SimpleDescriptionFormat_t *)&zclOTA_SimpleDesc,
- (afNetworkLatencyReq_t) 0
- };
- /******************************************************************************
- * @fn zclOTA_PermitOta
- *
- * @brief Called to enable/disable OTA operation.
- *
- * @param permit - TRUE to enable OTA, FALSE to diable OTA
- *
- * @return none
- */
- void zclOTA_PermitOta(uint8 permit)
- {
- zclOTA_Permit = permit;
- }
- /******************************************************************************
- * @fn zclOTA_Register
- *
- * @brief Called by an application to register for callback messages
- * from the OTA.
- *
- * @param applicationTaskId - Application Task ID
- *
- * @return none
- */
- void zclOTA_Register(uint8 applicationTaskId)
- {
- zclOTA_AppTask = applicationTaskId;
- }
- /******************************************************************************
- * @fn zclOTA_RequestNextUpdate
- *
- * @brief Called by an application after discovery of the OTA server
- * to initiate the query next image of the OTA server.
- *
- * @param srvAddr - Short address of the server
- * @param srvEndPoint - Endpoint on the server
- *
- * @return ZStatus_t
- */
- void zclOTA_RequestNextUpdate(uint16 srvAddr, uint8 srvEndPoint)
- {
- // Record the server address
- zclOTA_serverAddr.addrMode = afAddr16Bit;
- zclOTA_serverAddr.endPoint = srvEndPoint;
- zclOTA_serverAddr.addr.shortAddr = srvAddr;
- // Set an event to query the server
- osal_set_event(zclOTA_TaskID, ZCL_OTA_QUERY_SERVER_EVT);
- }
- /******************************************************************************
- * @fn zclOTA_Init
- *
- * @brief Call to initialize the OTA Client Task
- *
- * @param task_id
- *
- * @return none
- */
- void zclOTA_Init( uint8 task_id )
- {
- zclOTA_TaskID = task_id;
- // Register for the cluster endpoint
- afRegister( &zclOTA_Ep );
- // Register as a ZCL Plugin
- zcl_registerPlugin( ZCL_CLUSTER_ID_OTA,
- ZCL_CLUSTER_ID_OTA,
- zclOTA_HdlIncoming );
- // Initialize attribute variables
- zclOTA_CurrentZigBeeStackVersion = OTA_STACK_VER_PRO;
- zclOTA_ImageUpgradeStatus = OTA_STATUS_NORMAL;
- // Register attribute list
- zcl_registerAttrList( ZCL_OTA_ENDPOINT,
- ZCL_OTA_MAX_ATTRIBUTES,
- zclOTA_Attrs );
- #ifndef OTA_HA
- // Register the application's cluster option list
- zcl_registerClusterOptionList( ZCL_OTA_ENDPOINT, ZCL_OTA_MAX_OPTIONS, zclOta_Options );
- #endif // OTA_HA
- // Register with the ZDO to receive Network Address Responses
- ZDO_RegisterForZDOMsg(task_id, IEEE_addr_rsp);
- // The default upgradeServerID is FF:FF:FF:FF:FF:FF:FF:FF
- osal_memset(zclOTA_UpgradeServerID, 0xFF, sizeof(zclOTA_UpgradeServerID));
- #if defined (OTA_SERVER) && (OTA_SERVER == TRUE)
- // Register with the files system
- MT_OtaRegister(task_id);
- #endif // OTA_SERVER
- }
- /******************************************************************************
- * @fn zclOTA_event_loop
- *
- * @brief Event Loop Processor for OTA Client task.
- *
- * @param task_id - TaskId
- * events - events
- *
- * @return Unprocessed event bits
- */
- uint16 zclOTA_event_loop( uint8 task_id, uint16 events )
- {
- afIncomingMSGPacket_t *MSGpkt;
- if ( events & SYS_EVENT_MSG )
- {
- while ( (MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( task_id )) )
- {
- switch ( MSGpkt->hdr.event )
- {
- #if (defined OTA_CLIENT) && (OTA_CLIENT == TRUE)
- case ZDO_CB_MSG:
- zclOTA_ProcessZDOMsgs( (zdoIncomingMsg_t *)MSGpkt );
- break;
- #endif // OTA_CLIENT
- #if (defined OTA_SERVER) && (OTA_SERVER == TRUE)
- case MT_SYS_OTA_MSG:
- zclOTA_ServerHandleFileSysCb((OTA_MtMsg_t*)MSGpkt);
- break;
- #endif
- default:
- break;
- }
- // Release the memory
- osal_msg_deallocate( (uint8 *)MSGpkt );
- }
- // return unprocessed events
- return (events ^ SYS_EVENT_MSG);
- }
- #if (defined OTA_CLIENT) && (OTA_CLIENT == TRUE)
- if ( events & ZCL_OTA_IMAGE_BLOCK_WAIT_EVT )
- {
- // If the time has expired, perform the required action
- if (zclOTA_UpdateDelay == 0)
- {
- zclOTA_ImageBlockWaitExpired();
- }
- else
- {
- // Decrement the number of minutes to wait and reset the timer
- zclOTA_UpdateDelay--;
- osal_start_timerEx(zclOTA_TaskID, ZCL_OTA_IMAGE_BLOCK_WAIT_EVT, 60000);
- }
- return ( events ^ ZCL_OTA_IMAGE_BLOCK_WAIT_EVT );
- }
- if ( events & ZCL_OTA_UPGRADE_WAIT_EVT )
- {
- // If the time has expired, perform the required action
- if (zclOTA_UpdateDelay == 0)
- {
- if (zclOTA_ImageUpgradeStatus == OTA_STATUS_COUNTDOWN)
- {
- zclOTA_UpgradeComplete(ZSuccess);
- }
- else if (zclOTA_ImageUpgradeStatus == OTA_STATUS_UPGRADE_WAIT)
- {
- if (++zclOTA_UpgradeEndRetry > OTA_MAX_END_REQ_RETRIES)
- {
- // If we have not heard from the server for N retries, perform the upgrade
- zclOTA_UpgradeComplete(ZSuccess);
- }
- else
- {
- // Send another update end request
- zclOTA_UpgradeEndReqParams_t req;
- req.status = ZSuccess;
- osal_memcpy(&req.fileId, &zclOTA_CurrentDlFileId, sizeof(zclOTA_FileID_t));
- zclOTA_SendUpgradeEndReq(&zclOTA_serverAddr, &req);
- // Restart the timer for another hour
- zclOTA_StartTimer(ZCL_OTA_UPGRADE_WAIT_EVT, 3600);
- }
- }
- }
- else
- {
- // Decrement the number of minutes to wait and reset the timer
- zclOTA_UpdateDelay--;
- osal_start_timerEx(zclOTA_TaskID, ZCL_OTA_UPGRADE_WAIT_EVT, 60000);
- }
- return ( events ^ ZCL_OTA_UPGRADE_WAIT_EVT );
- }
- if (events & ZCL_OTA_IMAGE_QUERY_TO_EVT )
- {
- if (zclOTA_ImageUpgradeStatus == OTA_STATUS_NORMAL)
- {
- // Notify the application task of the timeout waiting for the download to start
- zclOTA_CallbackMsg_t *pMsg;
- pMsg = (zclOTA_CallbackMsg_t*) osal_msg_allocate(sizeof(zclOTA_CallbackMsg_t));
- if (pMsg)
- {
- pMsg->hdr.event = ZCL_OTA_CALLBACK_IND;
- pMsg->hdr.status = ZFailure;
- pMsg->ota_event = ZCL_OTA_START_CALLBACK;
- osal_msg_send(zclOTA_AppTask, (uint8*) pMsg);
- }
- }
- return ( events ^ ZCL_OTA_IMAGE_QUERY_TO_EVT );
- }
- if (events & ZCL_OTA_BLOCK_RSP_TO_EVT )
- {
- // We timed out waiting for a Block Response
- if (++zclOTA_BlockRetry > OTA_MAX_BLOCK_RETRIES)
- {
- // Send a failed update end request
- zclOTA_UpgradeEndReqParams_t req;
- req.status = ZOtaAbort;
- osal_memcpy(&req.fileId, &zclOTA_CurrentDlFileId, sizeof(zclOTA_FileID_t));
- zclOTA_SendUpgradeEndReq(&zclOTA_serverAddr, &req);
- zclOTA_UpgradeComplete(ZOtaAbort);
- }
- else
- {
- // Send another block request
- sendImageBlockReq(&zclOTA_serverAddr);
- }
- return ( events ^ ZCL_OTA_BLOCK_RSP_TO_EVT );
- }
- if (events & ZCL_OTA_QUERY_SERVER_EVT )
- {
- zclOTA_QueryNextImageReqParams_t queryParams;
- queryParams.fieldControl = 0;
- queryParams.fileId.manufacturer = OTA_MANUFACTURER_ID;
- queryParams.fileId.type = OTA_TYPE_ID;
- queryParams.fileId.version = zclOTA_CurrentFileVersion;
- zclOTA_SendQueryNextImageReq(&zclOTA_serverAddr, &queryParams);
- // Set a timer to wait for the response
- osal_start_timerEx(zclOTA_TaskID, ZCL_OTA_IMAGE_QUERY_TO_EVT, 10000);
- return ( events ^ ZCL_OTA_QUERY_SERVER_EVT );
- }
- #endif // OTA_CLIENT
- // Discard unknown events
- return 0;
- }
- /******************************************************************************
- * @fn zclOTA_HdlIncoming
- *
- * @brief Callback from ZCL to process incoming Commands specific
- * to this cluster library or Profile commands for attributes
- * that aren't in the attribute list
- *
- * @param pInMsg - pointer to the incoming message
- *
- * @return ZStatus_t
- */
- static ZStatus_t zclOTA_HdlIncoming( zclIncoming_t *pInMsg )
- {
- ZStatus_t stat = ZSuccess;
- if ( zcl_ClusterCmd( pInMsg->hdr.fc.type ) )
- {
- // Is this a manufacturer specific command?
- if ( pInMsg->hdr.fc.manuSpecific == 0 )
- {
- // Is command for server?
- if ( zcl_ServerCmd( pInMsg->hdr.fc.direction ) )
- {
- #if (defined OTA_SERVER) && (OTA_SERVER == TRUE)
- stat = zclOTA_ServerHdlIncoming( pInMsg );
- #else
- stat = ZCL_STATUS_UNSUP_CLUSTER_COMMAND;
- #endif // OTA_SERVER
- }
- else // Else command is for client
- {
- #if (defined OTA_CLIENT) && (OTA_CLIENT == TRUE)
- stat = zclOTA_ClientHdlIncoming( pInMsg );
- #else
- stat = ZCL_STATUS_UNSUP_CLUSTER_COMMAND;
- #endif // OTA_CLIENT
- }
- }
- else
- {
- // We don't support any manufacturer specific command.
- stat = ZCL_STATUS_UNSUP_MANU_CLUSTER_COMMAND;
- }
- }
- else
- {
- // Handle all the normal (Read, Write...) commands -- should never get here
- stat = ZFailure;
- }
- return ( stat );
- }
- #if (defined OTA_SERVER) && (OTA_SERVER == TRUE)
- /******************************************************************************
- * @fn zclOTA_SendImageNotify
- *
- * @brief Send an OTA Image Notify message.
- *
- * @param dstAddr - where you want the message to go
- * @param pParams - message parameters
- *
- * @return ZStatus_t
- */
- ZStatus_t zclOTA_SendImageNotify( afAddrType_t *dstAddr,
- zclOTA_ImageNotifyParams_t *pParams )
- {
- ZStatus_t status;
- uint8 buf[PAYLOAD_MAX_LEN_IMAGE_NOTIFY];
- uint8 *pBuf = buf;
- *pBuf++ = pParams->payloadType;
- *pBuf++ = pParams->queryJitter;
- if (pParams->payloadType >= NOTIFY_PAYLOAD_JITTER_MFG)
- {
- *pBuf++ = LO_UINT16(pParams->fileId.manufacturer);
- *pBuf++ = HI_UINT16(pParams->fileId.manufacturer);
- }
- if (pParams->payloadType >= NOTIFY_PAYLOAD_JITTER_MFG_TYPE)
- {
- *pBuf++ = LO_UINT16(pParams->fileId.type);
- *pBuf++ = HI_UINT16(pParams->fileId.type);
- }
- if (pParams->payloadType == NOTIFY_PAYLOAD_JITTER_MFG_TYPE_VERS)
- {
- pBuf = osal_buffer_uint32(pBuf, pParams->fileId.version);
- }
- status = zcl_SendCommand( ZCL_OTA_ENDPOINT, dstAddr, ZCL_CLUSTER_ID_OTA,
- COMMAND_IMAGE_NOTIFY, TRUE,
- ZCL_FRAME_SERVER_CLIENT_DIR, TRUE, 0,
- zclOTA_SeqNo++, (uint16) (pBuf - buf), buf );
- return status;
- }
- /******************************************************************************
- * @fn zclOTA_SendQueryNextImageRsp
- *
- * @brief Send an OTA Query Next Image Response message.
- *
- * @param dstAddr - where you want the message to go
- * @param pParams - message parameters
- *
- * @return ZStatus_t
- */
- ZStatus_t zclOTA_SendQueryNextImageRsp( afAddrType_t *dstAddr,
- zclOTA_QueryImageRspParams_t *pParams )
- {
- ZStatus_t status;
- uint8 buf[PAYLOAD_MAX_LEN_QUERY_NEXT_IMAGE_RSP];
- uint8 *pBuf = buf;
- *pBuf++ = pParams->status;
- if (pParams->status == ZCL_STATUS_SUCCESS)
- {
- *pBuf++ = LO_UINT16(pParams->fileId.manufacturer);
- *pBuf++ = HI_UINT16(pParams->fileId.manufacturer);
- *pBuf++ = LO_UINT16(pParams->fileId.type);
- *pBuf++ = HI_UINT16(pParams->fileId.type);
- pBuf = osal_buffer_uint32(pBuf, pParams->fileId.version);
- pBuf = osal_buffer_uint32(pBuf, pParams->imageSize);
- }
- status = zcl_SendCommand( ZCL_OTA_ENDPOINT, dstAddr, ZCL_CLUSTER_ID_OTA,
- COMMAND_QUERY_NEXT_IMAGE_RSP, TRUE,
- ZCL_FRAME_SERVER_CLIENT_DIR, TRUE, 0,
- zclOTA_SeqNo++, (uint16) (pBuf - buf), buf );
- return status;
- }
- /******************************************************************************
- * @fn zclOTA_SendImageBlockRsp
- *
- * @brief Send an OTA Image Block Response mesage.
- *
- * @param dstAddr - where you want the message to go
- * @param pParams - message parameters
- *
- * @return ZStatus_t
- */
- ZStatus_t zclOTA_SendImageBlockRsp( afAddrType_t *dstAddr,
- zclOTA_ImageBlockRspParams_t *pParams )
- {
- uint8 *buf;
- uint8 *pBuf;
- ZStatus_t status;
- uint8 len;
- if (pParams->status == ZCL_STATUS_SUCCESS)
- {
- len = PAYLOAD_MAX_LEN_IMAGE_BLOCK_RSP + pParams->rsp.success.dataSize;
- }
- else if (pParams->status == ZCL_STATUS_WAIT_FOR_DATA)
- {
- len = PAYLOAD_MIN_LEN_IMAGE_BLOCK_WAIT;
- }
- else
- {
- len = 1;
- }
- buf = osal_mem_alloc( len );
- if ( buf == NULL )
- {
- return (ZMemError);
- }
- pBuf = buf;
- *pBuf++ = pParams->status;
- if (pParams->status == ZCL_STATUS_SUCCESS)
- {
- *pBuf++ = LO_UINT16(pParams->rsp.success.fileId.manufacturer);
- *pBuf++ = HI_UINT16(pParams->rsp.success.fileId.manufacturer);
- *pBuf++ = LO_UINT16(pParams->rsp.success.fileId.type);
- *pBuf++ = HI_UINT16(pParams->rsp.success.fileId.type);
- pBuf = osal_buffer_uint32(pBuf, pParams->rsp.success.fileId.version);
- pBuf = osal_buffer_uint32(pBuf, pParams->rsp.success.fileOffset);
- *pBuf++ = pParams->rsp.success.dataSize;
- osal_memcpy(pBuf, pParams->rsp.success.pData, pParams->rsp.success.dataSize);
- }
- else if (pParams->status == ZCL_STATUS_WAIT_FOR_DATA)
- {
- pBuf = osal_buffer_uint32(pBuf, pParams->rsp.wait.currentTime);
- pBuf = osal_buffer_uint32(pBuf, pParams->rsp.wait.requestTime);
- }
- status = zcl_SendCommand( ZCL_OTA_ENDPOINT, dstAddr, ZCL_CLUSTER_ID_OTA,
- COMMAND_IMAGE_BLOCK_RSP, TRUE,
- ZCL_FRAME_SERVER_CLIENT_DIR, TRUE, 0,
- zclOTA_SeqNo++, len, buf );
- osal_mem_free(buf);
- return status;
- }
- /******************************************************************************
- * @fn zclOTA_SendUpgradeEndRsp
- *
- * @brief Send an OTA Upgrade End Response mesage.
- *
- * @param dstAddr - where you want the message to go
- * @param pParams - message parameters
- *
- * @return ZStatus_t
- */
- ZStatus_t zclOTA_SendUpgradeEndRsp( afAddrType_t *dstAddr,
- zclOTA_UpgradeEndRspParams_t *pParams )
- {
- ZStatus_t status;
- uint8 buf[PAYLOAD_MAX_LEN_UPGRADE_END_RSP];
- uint8 *pBuf = buf;
- *pBuf++ = LO_UINT16(pParams->fileId.manufacturer);
- *pBuf++ = HI_UINT16(pParams->fileId.manufacturer);
- *pBuf++ = LO_UINT16(pParams->fileId.type);
- *pBuf++ = HI_UINT16(pParams->fileId.type);
- pBuf = osal_buffer_uint32(pBuf, pParams->fileId.version);
- pBuf = osal_buffer_uint32(pBuf, pParams->currentTime);
- pBuf = osal_buffer_uint32(pBuf, pParams->upgradeTime);
- status = zcl_SendCommand( ZCL_OTA_ENDPOINT, dstAddr, ZCL_CLUSTER_ID_OTA,
- COMMAND_UPGRADE_END_RSP, TRUE,
- ZCL_FRAME_SERVER_CLIENT_DIR, TRUE, 0,
- zclOTA_SeqNo++, PAYLOAD_MAX_LEN_UPGRADE_END_RSP, buf );
- return status;
- }
- /******************************************************************************
- * @fn zclOTA_SendQuerySpecificFileRsp
- *
- * @brief Send an OTA Query Specific File Response mesage.
- *
- * @param dstAddr - where you want the message to go
- * @param pParams - message parameters
- *
- * @return ZStatus_t
- */
- ZStatus_t zclOTA_SendQuerySpecificFileRsp( afAddrType_t *dstAddr,
- zclOTA_QueryImageRspParams_t *pParams )
- {
- ZStatus_t status;
- uint8 buf[PAYLOAD_MAX_LEN_QUERY_SPECIFIC_FILE_RSP];
- uint8 *pBuf = buf;
- *pBuf++ = pParams->status;
- if (pParams->status == ZCL_STATUS_SUCCESS)
- {
- *pBuf++ = LO_UINT16(pParams->fileId.manufacturer);
- *pBuf++ = HI_UINT16(pParams->fileId.manufacturer);
- *pBuf++ = LO_UINT16(pParams->fileId.type);
- *pBuf++ = HI_UINT16(pParams->fileId.type);
- pBuf = osal_buffer_uint32(pBuf, pParams->fileId.version);
- pBuf = osal_buffer_uint32(pBuf, pParams->imageSize);
- }
- status = zcl_SendCommand( ZCL_OTA_ENDPOINT, dstAddr, ZCL_CLUSTER_ID_OTA,
- COMMAND_QUERY_SPECIFIC_FILE_RSP, TRUE,
- ZCL_FRAME_SERVER_CLIENT_DIR, TRUE, 0,
- zclOTA_SeqNo++, (uint16) (pBuf - buf), buf );
- return status;
- }
- #endif // OTA_SERVER
- #if (defined OTA_CLIENT) && (OTA_CLIENT == TRUE)
- /******************************************************************************
- * @fn zclOTA_SendQueryNextImageReq
- *
- * @brief Send an OTA Query Next Image Request mesage.
- *
- * @param dstAddr - where you want the message to go
- * @param pParams - message parameters
- *
- * @return ZStatus_t
- */
- ZStatus_t zclOTA_SendQueryNextImageReq( afAddrType_t *dstAddr,
- zclOTA_QueryNextImageReqParams_t *pParams )
- {
- ZStatus_t status;
- uint8 buf[PAYLOAD_MAX_LEN_QUERY_NEXT_IMAGE_REQ];
- uint8 *pBuf = buf;
- *pBuf++ = pParams->fieldControl;
- *pBuf++ = LO_UINT16(pParams->fileId.manufacturer);
- *pBuf++ = HI_UINT16(pParams->fileId.manufacturer);
- *pBuf++ = LO_UINT16(pParams->fileId.type);
- *pBuf++ = HI_UINT16(pParams->fileId.type);
- pBuf = osal_buffer_uint32(pBuf, pParams->fileId.version);
- if (pParams->fieldControl == 1)
- {
- *pBuf++ = LO_UINT16(pParams->hardwareVersion);
- *pBuf++ = HI_UINT16(pParams->hardwareVersion);
- }
- status = zcl_SendCommand( ZCL_OTA_ENDPOINT, dstAddr, ZCL_CLUSTER_ID_OTA,
- COMMAND_QUERY_NEXT_IMAGE_REQ, TRUE,
- ZCL_FRAME_CLIENT_SERVER_DIR, FALSE, 0,
- zclOTA_SeqNo++, (uint16) (pBuf - buf), buf );
- return status;
- }
- /******************************************************************************
- * @fn zclOTA_SendImageBlockReq
- *
- * @brief Send an OTA Image Block Request mesage.
- *
- * @param dstAddr - where you want the message to go
- * @param pParams - message parameters
- *
- * @return ZStatus_t
- */
- ZStatus_t zclOTA_SendImageBlockReq( afAddrType_t *dstAddr,
- zclOTA_ImageBlockReqParams_t *pParams )
- {
- ZStatus_t status;
- uint8 buf[PAYLOAD_MAX_LEN_IMAGE_BLOCK_REQ];
- uint8 *pBuf = buf;
- *pBuf++ = pParams->fieldControl;
- *pBuf++ = LO_UINT16(pParams->fileId.manufacturer);
- *pBuf++ = HI_UINT16(pParams->fileId.manufacturer);
- *pBuf++ = LO_UINT16(pParams->fileId.type);
- *pBuf++ = HI_UINT16(pParams->fileId.type);
- pBuf = osal_buffer_uint32(pBuf, pParams->fileId.version);
- pBuf = osal_buffer_uint32(pBuf, pParams->fileOffset);
- *pBuf++ = pParams->maxDataSize;
- if (pParams->fieldControl == 1)
- {
- osal_cpyExtAddr(pBuf, pParams->nodeAddr);
- pBuf += Z_EXTADDR_LEN;
- }
- status = zcl_SendCommand( ZCL_OTA_ENDPOINT, dstAddr, ZCL_CLUSTER_ID_OTA,
- COMMAND_IMAGE_BLOCK_REQ, TRUE,
- ZCL_FRAME_CLIENT_SERVER_DIR, FALSE, 0,
- zclOTA_SeqNo++, (uint16) (pBuf - buf), buf );
- return status;
- }
- /******************************************************************************
- * @fn zclOTA_SendUpgradeEndReq
- *
- * @brief Send an OTA Upgrade End Request mesage.
- *
- * @param dstAddr - where you want the message to go
- * @param pParams - message parameters
- *
- * @return ZStatus_t
- */
- ZStatus_t zclOTA_SendUpgradeEndReq( afAddrType_t *dstAddr,
- zclOTA_UpgradeEndReqParams_t *pParams )
- {
- ZStatus_t status;
- uint8 buf[PAYLOAD_MAX_LEN_UPGRADE_END_REQ];
- uint8 *pBuf = buf;
- *pBuf++ = pParams->status;
- *pBuf++ = LO_UINT16(pParams->fileId.manufacturer);
- *pBuf++ = HI_UINT16(pParams->fileId.manufacturer);
- *pBuf++ = LO_UINT16(pParams->fileId.type);
- *pBuf++ = HI_UINT16(pParams->fileId.type);
- pBuf = osal_buffer_uint32(pBuf, pParams->fileId.version);
- status = zcl_SendCommand( ZCL_OTA_ENDPOINT, dstAddr, ZCL_CLUSTER_ID_OTA,
- COMMAND_UPGRADE_END_REQ, TRUE,
- ZCL_FRAME_CLIENT_SERVER_DIR, FALSE, 0,
- zclOTA_SeqNo++, (uint16) (pBuf - buf), buf );
- return status;
- }
- /******************************************************************************
- * @fn zclOTA_StartTimer
- *
- * @brief Start a ZCL OTA timer.
- *
- * @param eventId - OSAL event set on timer expiration
- * @param seconds - timeout in seconds
- *
- * @return None
- */
- static void zclOTA_StartTimer(uint16 eventId, uint32 seconds)
- {
- // Record the number of whole minutes to wait
- zclOTA_UpdateDelay = (seconds / 60);
- // Set a timer for the remaining seconds to wait.
- osal_start_timerEx(zclOTA_TaskID, eventId, (seconds % 60) * 1000);
- }
- /******************************************************************************
- * @fn sendImageBlockReq
- *
- * @brief Send an Image Block Request.
- *
- * @param dstAddr - where you want the message to go
- *
- * @return ZStatus_t
- */
- static ZStatus_t sendImageBlockReq(afAddrType_t *dstAddr)
- {
- zclOTA_ImageBlockReqParams_t req;
- req.fieldControl = 0;
- req.fileId.manufacturer = zclOTA_ManufacturerId;
- req.fileId.type = zclOTA_ImageType;
- req.fileId.version = zclOTA_DownloadedFileVersion;
- req.fileOffset = zclOTA_FileOffset;
- if (zclOTA_DownloadedImageSize - zclOTA_FileOffset < OTA_MAX_MTU)
- {
- req.maxDataSize = zclOTA_DownloadedImageSize - zclOTA_FileOffset;
- }
- else
- {
- req.maxDataSize = OTA_MAX_MTU;
- }
- // Start a timer waiting for a response
- osal_start_timerEx(zclOTA_TaskID, ZCL_OTA_BLOCK_RSP_TO_EVT, OTA_MAX_BLOCK_RSP_WAIT_TIME);
- return zclOTA_SendImageBlockReq( dstAddr, &req);
- }
- /******************************************************************************
- * @fn zclOTA_ProcessImageData
- *
- * @brief Process image data as it is received from the host.
- *
- * @param pData - pointer to the data
- * @param len - length of the data
- *
- * @return status of the operation
- */
- uint8 zclOTA_ProcessImageData(uint8 *pData, uint8 len)
- {
- int8 i;
- #if defined OTA_MMO_SIGN
- uint8 skipHash = FALSE;
- #endif
- if (zclOTA_ImageUpgradeStatus != OTA_STATUS_IN_PROGRESS)
- {
- return ZCL_STATUS_ABORT;
- }
- #if (defined HAL_LED) && (HAL_LED == TRUE)
- // Toggle an LED to indicate we received a new block
- HalLedSet(HAL_LED_2, HAL_LED_MODE_TOGGLE);
- #endif
- // write data to secondary storage
- HalOTAWrite(zclOTA_FileOffset, pData, len, HAL_OTA_DL);
- for (i=0; i<len; i++)
- {
- #if defined OTA_MMO_SIGN
- // Skip the hash if we are receiving the signature element
- if ((zclOTA_ClientPdState >= ZCL_OTA_PD_ELEM_LEN1_STATE) &&
- (zclOTA_ClientPdState <= ZCL_OTA_PD_ELEMENT_STATE))
- {
- if (zclOTA_ElementTag == OTA_ECDSA_SIGNATURE_TAG_ID)
- {
- skipHash = TRUE;
- }
- }
- #endif
- switch (zclOTA_ClientPdState)
- {
- // verify header magic number
- case ZCL_OTA_PD_MAGIC_0_STATE:
- // Initialize control variables
- #if defined OTA_MMO_SIGN
- osal_memset(&zclOTA_MmoHash, 0, sizeof(zclOTA_MmoHash));
- zclOTA_HashPos = 0;
- #endif
- // Missing break intended
- case ZCL_OTA_PD_MAGIC_1_STATE:
- case ZCL_OTA_PD_MAGIC_2_STATE:
- case ZCL_OTA_PD_MAGIC_3_STATE:
- if (pData[i] != zclOTA_HdrMagic[zclOTA_ClientPdState])
- {
- return ZCL_STATUS_INVALID_IMAGE;
- }
- zclOTA_ClientPdState++;
- break;
- case ZCL_OTA_PD_HDR_LEN1_STATE:
- // get header length
- if (zclOTA_FileOffset == ZCL_OTA_HDR_LEN_OFFSET)
- {
- zclOTA_HeaderLen = pData[i];
- zclOTA_ClientPdState = ZCL_OTA_PD_HDR_LEN2_STATE;
- }
- break;
- case ZCL_OTA_PD_HDR_LEN2_STATE:
- zclOTA_HeaderLen |= (((uint16)pData[i]) << 8) & 0xFF00;
- zclOTA_ClientPdState = ZCL_OTA_PD_STK_VER1_STATE;
- break;
- case ZCL_OTA_PD_STK_VER1_STATE:
- // get stack version
- if (zclOTA_FileOffset == ZCL_OTA_STK_VER_OFFSET)
- {
- zclOTA_DownloadedZigBeeStackVersion = pData[i];
- zclOTA_ClientPdState = ZCL_OTA_PD_STK_VER2_STATE;
- }
- break;
- case ZCL_OTA_PD_STK_VER2_STATE:
- zclOTA_DownloadedZigBeeStackVersion |= (((uint16)pData[i]) << 8) & 0xFF00;
- zclOTA_ClientPdState = ZCL_OTA_PD_CONT_HDR_STATE;
- if (zclOTA_DownloadedZigBeeStackVersion != OTA_HDR_STACK_VERSION)
- {
- return ZCL_STATUS_INVALID_IMAGE;
- }
- break;
- case ZCL_OTA_PD_CONT_HDR_STATE:
- // Complete the header
- if (zclOTA_FileOffset == zclOTA_HeaderLen-1)
- {
- zclOTA_ClientPdState = ZCL_OTA_PD_ELEM_TAG1_STATE;
- }
- break;
- case ZCL_OTA_PD_ELEM_TAG1_STATE:
- zclOTA_ElementTag = pData[i];
- zclOTA_ClientPdState = ZCL_OTA_PD_ELEM_TAG2_STATE;
- break;
- case ZCL_OTA_PD_ELEM_TAG2_STATE:
- zclOTA_ElementTag |= (((uint16)pData[i]) << 8) & 0xFF00;
- zclOTA_ElementPos = 0;
- zclOTA_ClientPdState = ZCL_OTA_PD_ELEM_LEN1_STATE;
- break;
- case ZCL_OTA_PD_ELEM_LEN1_STATE:
- zclOTA_ElementLen = pData[i];
- zclOTA_ClientPdState = ZCL_OTA_PD_ELEM_LEN2_STATE;
- break;
- case ZCL_OTA_PD_ELEM_LEN2_STATE:
- zclOTA_ElementLen |= ((uint32)pData[i] << 8) & 0x0000FF00;
- zclOTA_ClientPdState = ZCL_OTA_PD_ELEM_LEN3_STATE;
- break;
- case ZCL_OTA_PD_ELEM_LEN3_STATE:
- zclOTA_ElementLen |= ((uint32)pData[i] << 16) & 0x00FF0000;
- zclOTA_ClientPdState = ZCL_OTA_PD_ELEM_LEN4_STATE;
- break;
- case ZCL_OTA_PD_ELEM_LEN4_STATE:
- zclOTA_ElementLen |= ((uint32)pData[i] << 24) & 0xFF000000;
- zclOTA_ClientPdState = ZCL_OTA_PD_ELEMENT_STATE;
- // Make sure the length of the element isn't bigger than the image
- if (zclOTA_ElementLen > (zclOTA_DownloadedImageSize - zclOTA_FileOffset))
- {
- return ZCL_STATUS_INVALID_IMAGE;
- }
- #if defined OTA_MMO_SIGN
- if (zclOTA_ElementTag == OTA_ECDSA_SIGNATURE_TAG_ID)
- {
- if (zclOTA_ElementLen != OTA_SIGNATURE_LEN + Z_EXTADDR_LEN)
- {
- return ZCL_STATUS_INVALID_IMAGE;
- }
- }
- else if (zclOTA_ElementTag == OTA_ECDSA_CERT_TAG_ID)
- {
- if (zclOTA_ElementLen != OTA_CERTIFICATE_LEN)
- {
- return ZCL_STATUS_INVALID_IMAGE;
- }
- }
- #endif
- break;
- case ZCL_OTA_PD_ELEMENT_STATE:
- #if defined OTA_MMO_SIGN
- if (zclOTA_ElementTag == OTA_ECDSA_SIGNATURE_TAG_ID)
- {
- if (zclOTA_ElementPos < Z_EXTADDR_LEN)
- zclOTA_SignerIEEE[zclOTA_ElementPos] = pData[i];
- else
- zclOTA_SignatureData[zclOTA_ElementPos - Z_EXTADDR_LEN] = pData[i];
- }
- else if (zclOTA_ElementTag == OTA_ECDSA_CERT_TAG_ID)
- {
- zclOTA_Certificate[zclOTA_ElementPos] = pData[i];
- }
- #endif
- if (++zclOTA_ElementPos == zclOTA_ElementLen)
- {
- // Element is complete
- if (zclOTA_ElementTag == OTA_UPGRADE_IMAGE_TAG_ID)
- {
- // The serial flash can take up to 25 ms before it is ready for a read
- uint32 k;
- for (k=0; k<0xffff; k++)
- {
- asm("NOP");
- }
- // When the image is complete, verify CRC
- if (HalOTAChkDL(HAL_OTA_CRC_OSET) != SUCCESS)
- {
- #if (defined HAL_LCD) && (HAL_LCD == TRUE)
- HalLcdWriteString("OTA CRC Fail", HAL_LCD_LINE_3);
- #endif
- return ZCL_STATUS_INVALID_IMAGE;
- }
- }
- zclOTA_ClientPdState = ZCL_OTA_PD_ELEM_TAG1_STATE;
- }
- break;
- default:
- break;
- }
- #if defined OTA_MMO_SIGN
- // We need to skip the hash calculation on the signature element.
- // When receiving a tag, we wait to receive the entire tag before
- // adding the byte to the hash buffer because it could be the tag
- // for the signature
- if (zclOTA_ClientPdState == ZCL_OTA_PD_ELEM_TAG2_STATE)
- {
- skipHash = TRUE;
- }
- else if (zclOTA_ClientPdState == ZCL_OTA_PD_ELEM_LEN1_STATE)
- {
- if (zclOTA_ElementTag != OTA_ECDSA_SIGNATURE_TAG_ID)
- {
- // This tag is not for the signature.
- // Put the Lower byte of the tag into the hash buffer now
- // The high byte will be processed as usual below
- zclOTA_DataToHash[zclOTA_HashPos++] = LO_UINT16(zclOTA_ElementTag);
- // When the buffer reaches OTA_MMO_HASH_SIZE, update the Hash
- if (zclOTA_HashPos == OTA_MMO_HASH_SIZE)
- {
- OTA_CalculateMmoR3(&zclOTA_MmoHash, zclOTA_DataToHash, OTA_MMO_HASH_SIZE, FALSE);
- zclOTA_HashPos = 0;
- }
- skipHash = FALSE;
- }
- }
- if (!skipHash)
- {
- // Maintain a buffer of data to hash
- zclOTA_DataToHash[zclOTA_HashPos++] = pData[i];
- // When the buffer reaches OTA_MMO_HASH_SIZE, update the Hash
- if (zclOTA_HashPos == OTA_MMO_HASH_SIZE)
- {
- OTA_CalculateMmoR3(&zclOTA_MmoHash, zclOTA_DataToHash, OTA_MMO_HASH_SIZE, FALSE);
- zclOTA_HashPos = 0;
- }
- }
- #endif
- // Check if the download is complete
- if (++zclOTA_FileOffset >= zclOTA_DownloadedImageSize)
- {
- zclOTA_ImageUpgradeStatus = OTA_STATUS_COMPLETE;
- #if defined OTA_MMO_SIGN
- // Complete the hash calcualtion
- OTA_CalculateMmoR3(&zclOTA_MmoHash, zclOTA_DataToHash, zclOTA_HashPos, TRUE);
- // Validate the hash
- if (OTA_ValidateSignature(zclOTA_MmoHash.hash, zclOTA_Certificate,
- zclOTA_SignatureData, zclOTA_SignerIEEE) != ZSuccess)
- return ZCL_STATUS_INVALID_IMAGE;
- #endif
- return ZSuccess;
- }
- }
- return ZSuccess;
- }
- /******************************************************************************
- * @fn zclOTA_ProcessImageNotify
- *
- * @brief Process received Image Notify command.
- *
- * @param pInMsg - pointer to the incoming message
- *
- * @return ZStatus_t
- */
- static ZStatus_t zclOTA_ProcessImageNotify( zclIncoming_t *pInMsg )
- {
- zclOTA_ImageNotifyParams_t param;
- zclOTA_QueryNextImageReqParams_t req;
- uint8 *pData;
- // verify message length
- if ((pInMsg->pDataLen > PAYLOAD_MAX_LEN_IMAGE_NOTIFY) ||
- (pInMsg->pDataLen < PAYLOAD_MIN_LEN_IMAGE_NOTIFY))
- {
- // no further processing if invalid
- return ZCL_STATUS_MALFORMED_COMMAND;
- }
- // verify in 'normal' state
- if ((zclOTA_Permit == FALSE) ||
- (zclOTA_ImageUpgradeStatus != OTA_STATUS_NORMAL))
- {
- return ZFailure;
- }
- // parse message
- pData = pInMsg->pData;
- param.payloadType = *pData++;
- param.queryJitter = *pData++;
- param.fileId.manufacturer = BUILD_UINT16(pData[0], pData[1]);
- pData += 2;
- param.fileId.type = BUILD_UINT16(pData[0], pData[1]);
- pData += 2;
- param.fileId.version = osal_build_uint32( pData, 4 );
- // if message is broadcast
- if (pInMsg->msg->wasBroadcast)
- {
- // verify manufacturer
- if ((param.payloadType >= NOTIFY_PAYLOAD_JITTER_MFG) &&
- (param.fileId.manufacturer != zclOTA_ManufacturerId))
- {
- return ZSuccess;
- }
- // verify image type
- if ((param.payloadType >= NOTIFY_PAYLOAD_JITTER_MFG_TYPE) &&
- (param.fileId.type != zclOTA_ImageType))
- {
- return ZSuccess;
- }
- // verify version; if version matches ignore
- if ((param.payloadType >= NOTIFY_PAYLOAD_JITTER_MFG_TYPE_VERS) &&
- (param.fileId.version == zclOTA_CurrentFileVersion))
- {
- return ZSuccess;
- }
- // get random value and compare to query jitter
- if (((uint8) osal_rand() % 100) > param.queryJitter)
- {
- // if greater than query jitter ignore;
- return ZSuccess;
- }
- }
- // if unicast message, or broadcast and still made it here, send query next image
- req.fieldControl = 0;
- req.fileId.manufacturer = zclOTA_ManufacturerId;
- req.fileId.type = zclOTA_ImageType;
- req.fileId.version = zclOTA_CurrentFileVersion;
- zclOTA_SendQueryNextImageReq( &(pInMsg->msg->srcAddr), &req);
- return ZSuccess;
- }
- /******************************************************************************
- * @fn zclOTA_ProcessQueryNextImageRsp
- *
- * @brief Process received Query Next Image Response.
- *
- * @param pInMsg - pointer to the incoming message
- *
- * @return ZStatus_t
- */
- static ZStatus_t zclOTA_ProcessQueryNextImageRsp( zclIncoming_t *pInMsg )
- {
- zclOTA_QueryImageRspParams_t param;
- uint8 *pData;
- uint8 status = ZFailure;
- // verify message length
- if ((pInMsg->pDataLen != PAYLOAD_MAX_LEN_QUERY_NEXT_IMAGE_RSP) &&
- (pInMsg->pDataLen != PAYLOAD_MIN_LEN_QUERY_NEXT_IMAGE_RSP))
- {
- // no further processing if invalid
- return ZCL_STATUS_MALFORMED_COMMAND;
- }
- // ignore message if in 'download in progress' state
- if (zclOTA_ImageUpgradeStatus == OTA_STATUS_IN_PROGRESS)
- {
- return ZSuccess;
- }
- // get status
- pData = pInMsg->pData;
- param.status = *pData++;
- // if status is success
- if (param.status == ZCL_STATUS_SUCCESS)
- {
- // parse message
- param.fileId.manufacturer = BUILD_UINT16(pData[0], pData[1]);
- pData += 2;
- param.fileId.type = BUILD_UINT16(pData[0], pData[1]);
- pData += 2;
- param.fileId.version = osal_build_uint32( pData, 4 );
- pData += 4;
- param.imageSize = osal_build_uint32( pData, 4 );
- // verify manufacturer id and image type
- if ((param.fileId.type == zclOTA_ImageType) &&
- (param.fileId.manufacturer == zclOTA_ManufacturerId))
- {
- // store file version and image size
- zclOTA_DownloadedFileVersion = param.fileId.version;
- zclOTA_DownloadedImageSize = param.imageSize;
- // initialize other variables
- zclOTA_FileOffset = 0;
- zclOTA_ClientPdState = ZCL_OTA_PD_MAGIC_0_STATE;
- // set state to 'in progress'
- zclOTA_ImageUpgradeStatus = OTA_STATUS_IN_PROGRESS;
- // store server address
- zclOTA_serverAddr = pInMsg->msg->srcAddr;
- // Store the file ID
- osal_memcpy(&zclOTA_CurrentDlFileId, ¶m.fileId, sizeof(zclOTA_FileID_t));
- // send image block request
- sendImageBlockReq(&(pInMsg->msg->srcAddr));
- status = ZCL_STATUS_CMD_HAS_RSP;
- // Request the IEEE address of the server to put into the
- // ATTRID_UPGRADE_SERVER_ID attribute
- ZDP_IEEEAddrReq(pInMsg->msg->srcAddr.addr.shortAddr, ZDP_ADDR_REQTYPE_SINGLE, 0, 0);
- osal_stop_timerEx(zclOTA_TaskID, ZCL_OTA_IMAGE_QUERY_TO_EVT);
- }
- }
- if (zclOTA_AppTask != 0xFF)
- {
- // Notify the application task of the failure
- zclOTA_CallbackMsg_t *pMsg;
- pMsg = (zclOTA_CallbackMsg_t*) osal_msg_allocate(sizeof(zclOTA_CallbackMsg_t));
- if (pMsg)
- {
- pMsg->hdr.event = ZCL_OTA_CALLBACK_IND;
- pMsg->hdr.status = param.status;
- pMsg->ota_event = ZCL_OTA_START_CALLBACK;
- osal_msg_send(zclOTA_AppTask, (uint8*) pMsg);
- }
- }
- return status;
- }
- /******************************************************************************
- * @fn zclOTA_ProcessImageBlockRsp
- *
- * @brief Process received Image Block Response.
- *
- * @param pInMsg - pointer to the incoming message
- *
- * @return ZStatus_t
- */
- static ZStatus_t zclOTA_ProcessImageBlockRsp( zclIncoming_t *pInMsg )
- {
- zclOTA_ImageBlockRspParams_t param;
- zclOTA_UpgradeEndReqParams_t req;
- uint8 *pData;
- uint8 status = ZSuccess;
- // verify in 'in progress' state
- if (zclOTA_ImageUpgradeStatus != OTA_STATUS_IN_PROGRESS)
- {
- return ZSuccess;
- }
- // get status
- pData = pInMsg->pData;
- param.status = *pData++;
- // if status is success
- if (param.status == ZCL_STATUS_SUCCESS)
- {
- // verify message length
- if (pInMsg->pDataLen < PAYLOAD_MAX_LEN_IMAGE_BLOCK_RSP)
- {
- // no further processing if invalid
- return ZCL_STATUS_MALFORMED_COMMAND;
- }
- // parse message
- param.rsp.success.fileId.manufacturer = BUILD_UINT16(pData[0], pData[1]);
- pData += 2;
- param.rsp.success.fileId.type = BUILD_UINT16(pData[0], pData[1]);
- pData += 2;
- param.rsp.success.fileId.version = osal_build_uint32( pData, 4 );
- pData += 4;
- param.rsp.success.fileOffset = osal_build_uint32( pData, 4 );
- pData += 4;
- param.rsp.success.dataSize = *pData++;
- param.rsp.success.pData = pData;
- // verify manufacturer, image type, file version, file offset
- if ((param.rsp.success.fileId.type != zclOTA_ImageType) ||
- (param.rsp.success.fileId.manufacturer != zclOTA_ManufacturerId) ||
- (param.rsp.success.fileId.version != zclOTA_DownloadedFileVersion))
- {
- status = ZCL_STATUS_INVALID_IMAGE;
- }
- else
- {
- // Drop duplicate packets (retries)
- if (param.rsp.success.fileOffset != zclOTA_FileOffset)
- {
- return ZSuccess;
- }
- status = zclOTA_ProcessImageData(param.rsp.success.pData, param.rsp.success.dataSize);
- // Stop the timer and clear the retry count
- zclOTA_BlockRetry = 0;
- osal_stop_timerEx(zclOTA_TaskID, ZCL_OTA_BLOCK_RSP_TO_EVT);
- if (status == ZSuccess)
- {
- if (zclOTA_ImageUpgradeStatus == OTA_STATUS_COMPLETE)
- {
- // send upgrade end req with success status
- osal_memcpy(&req.fileId, ¶m.rsp.success.fileId, sizeof(zclOTA_FileID_t));
- req.status = ZSuccess;
- zclOTA_SendUpgradeEndReq( &(pInMsg->msg->srcAddr), &req );
- }
- else
- {
- sendImageBlockReq(&(pInMsg->msg->srcAddr));
- }
- }
- }
- }
- // else if status is 'wait for data'
- else if (param.status == ZCL_STATUS_WAIT_FOR_DATA)
- {
- // verify message length
- if (pInMsg->pDataLen != PAYLOAD_MIN_LEN_IMAGE_BLOCK_WAIT)
- {
- // no further processing if invalid
- return ZCL_STATUS_MALFORMED_COMMAND;
- }
- // parse message
- param.rsp.wait.currentTime = osal_build_uint32( pData, 4 );
- pData += 4;
- param.rsp.wait.requestTime = osal_build_uint32( pData, 4 );
- // Stop the timer and clear the retry count
- zclOTA_BlockRetry = 0;
- osal_stop_timerEx(zclOTA_TaskID, ZCL_OTA_BLOCK_RSP_TO_EVT);
- // set timer for next image block req
- zclOTA_StartTimer(ZCL_OTA_IMAGE_BLOCK_WAIT_EVT,
- (param.rsp.wait.requestTime - param.rsp.wait.currentTime));
- }
- else if (param.status == ZCL_STATUS_ABORT)
- {
- // download aborted; set state to 'normal' state
- zclOTA_ImageUpgradeStatus = OTA_STATUS_NORMAL;
- // Stop the timer and clear the retry count
- zclOTA_BlockRetry = 0;
- osal_stop_timerEx(zclOTA_TaskID, ZCL_OTA_BLOCK_RSP_TO_EVT);
- zclOTA_UpgradeComplete(ZOtaAbort);
- return ZSuccess;
- }
- else
- {
- return ZCL_STATUS_MALFORMED_COMMAND;
- }
- if (status != ZSuccess)
- {
- // download failed; set state to 'normal'
- zclOTA_ImageUpgradeStatus = OTA_STATUS_NORMAL;
- // send upgrade end req with failure status
- osal_memcpy(&req.fileId, ¶m.rsp.success.fileId, sizeof(zclOTA_FileID_t));
- req.status = status;
- zclOTA_SendUpgradeEndReq( &(pInMsg->msg->srcAddr), &req );
- }
- return ZSuccess;
- }
- /******************************************************************************
- * @fn zclOTA_ProcessUpgradeEndRsp
- *
- * @brief Process received Upgrade End Response.
- *
- * @param pInMsg - pointer to the incoming message
- *
- * @return ZStatus_t
- */
- static ZStatus_t zclOTA_ProcessUpgradeEndRsp( zclIncoming_t *pInMsg )
- {
- zclOTA_UpgradeEndRspParams_t param;
- zclOTA_FileID_t currentFileId = {zclOTA_ManufacturerId, zclOTA_ImageType, zclOTA_DownloadedFileVersion};
- uint8 *pData;
- // verify message length
- if (pInMsg->pDataLen != PAYLOAD_MAX_LEN_UPGRADE_END_RSP)
- {
- // no further processing if invalid
- return ZCL_STATUS_MALFORMED_COMMAND;
- }
- // parse message
- pData = pInMsg->pData;
- param.fileId.manufacturer = BUILD_UINT16(pData[0], pData[1]);
- pData += 2;
- param.fileId.type = BUILD_UINT16(pData[0], pData[1]);
- pData += 2;
- param.fileId.version = osal_build_uint32( pData, 4 );
- pData += 4;
- param.currentTime = osal_build_uint32( pData, 4 );
- pData += 4;
- param.upgradeTime = osal_build_uint32( pData, 4 );
- // verify in 'download complete' or 'waiting for upgrade' state
- if ((zclOTA_ImageUpgradeStatus == OTA_STATUS_COMPLETE) ||
- ((zclOTA_ImageUpgradeStatus == OTA_STATUS_UPGRADE_WAIT) && (param.upgradeTime!=OTA_UPGRADE_TIME_WAIT)))
- {
- // verify manufacturer, image type
- if (zclOTA_CmpFileId(¶m.fileId, ¤tFileId) == FALSE)
- {
- return ZSuccess;
- }
- // check upgrade time
- if (param.upgradeTime != OTA_UPGRADE_TIME_WAIT)
- {
- uint32 notifyDelay = 0;
- if (param.upgradeTime > param.currentTime)
- {
- // time to wait before notification
- notifyDelay = param.upgradeTime - param.currentTime;
- }
- // set state to 'countdown'
- zclOTA_ImageUpgradeStatus = OTA_STATUS_COUNTDOWN;
- // set timer for upgrade complete notification
- zclOTA_StartTimer(ZCL_OTA_UPGRADE_WAIT_EVT, notifyDelay);
- }
- else
- {
- // Wait for another upgrade end response
- zclOTA_ImageUpgradeStatus = OTA_STATUS_UPGRADE_WAIT;
- // Set a timer for 60 minutes to send another Upgrade End Rsp
- zclOTA_StartTimer(ZCL_OTA_UPGRADE_WAIT_EVT, 3600);
- zclOTA_UpgradeEndRetry = 0;
- }
- }
- return ZSuccess;
- }
- /******************************************************************************
- * @fn zclOTA_ProcessQuerySpecificFileRsp
- *
- * @brief Process received Query Specific File Response.
- *
- * @param pInMsg - pointer to the incoming message
- *
- * @return ZStatus_t
- */
- static ZStatus_t zclOTA_ProcessQuerySpecificFileRsp( zclIncoming_t *pInMsg )
- {
- zclOTA_QueryImageRspParams_t param;
- uint8 *pData;
- // verify message length
- if ((pInMsg->pDataLen != PAYLOAD_MAX_LEN_QUERY_SPECIFIC_FILE_RSP) &&
- (pInMsg->pDataLen != PAYLOAD_MIN_LEN_QUERY_SPECIFIC_FILE_RSP))
- {
- // no further processing if invalid
- return ZCL_STATUS_MALFORMED_COMMAND;
- }
- // ignore message if in 'download in progress' state
- if (zclOTA_ImageUpgradeStatus == OTA_STATUS_IN_PROGRESS)
- {
- return ZSuccess;
- }
- // get status
- pData = pInMsg->pData;
- param.status = *pData++;
- // if status is success
- if (param.status == ZCL_STATUS_SUCCESS)
- {
- // parse message
- param.fileId.manufacturer = BUILD_UINT16(pData[0], pData[1]);
- pData += 2;
- param.fileId.type = BUILD_UINT16(pData[0], pData[1]);
- pData += 2;
- param.fileId.version = osal_build_uint32( pData, 4 );
- pData += 4;
- param.imageSize = osal_build_uint32( pData, 4 );
- // verify manufacturer id and image type
- if ((param.fileId.type == zclOTA_ImageType) &&
- (param.fileId.manufacturer == zclOTA_ManufacturerId))
- {
- // store file version and image size
- zclOTA_DownloadedFileVersion = param.fileId.version;
- zclOTA_DownloadedImageSize = param.imageSize;
- // initialize other variables
- zclOTA_FileOffset = 0;
- // set state to 'in progress'
- zclOTA_ImageUpgradeStatus = OTA_STATUS_IN_PROGRESS;
- // send image block request
- sendImageBlockReq(&(pInMsg->msg->srcAddr));
- }
- }
- return ZSuccess;
- }
- /******************************************************************************
- * @fn zclOTA_ClientHdlIncoming
- *
- * @brief Handle incoming client commands.
- *
- * @param pInMsg - pointer to the incoming message
- *
- * @return ZStatus_t
- */
- static ZStatus_t zclOTA_ClientHdlIncoming( zclIncoming_t *pInMsg )
- {
- switch (pInMsg->hdr.commandID)
- {
- case COMMAND_IMAGE_NOTIFY:
- return zclOTA_ProcessImageNotify( pInMsg );
- case COMMAND_QUERY_NEXT_IMAGE_RSP:
- return zclOTA_ProcessQueryNextImageRsp( pInMsg );
- case COMMAND_IMAGE_BLOCK_RSP:
- return zclOTA_ProcessImageBlockRsp( pInMsg );
- case COMMAND_UPGRADE_END_RSP:
- return zclOTA_ProcessUpgradeEndRsp( pInMsg );
- case COMMAND_QUERY_SPECIFIC_FILE_RSP:
- return zclOTA_ProcessQuerySpecificFileRsp( pInMsg );
- default:
- return ZFailure;
- }
- }
- /******************************************************************************
- * @fn zclOTA_CmpFileId
- *
- * @brief Called to compare two file IDs
- *
- * @param f1, f2 - Pointers to the two file IDs to compare
- *
- * @return TRUE if the file IDs are the same, else FALSE
- */
- static uint8 zclOTA_CmpFileId(zclOTA_FileID_t *f1, zclOTA_FileID_t *f2)
- {
- if ((f1->manufacturer == 0xFFFF) ||
- (f2->manufacturer == 0xFFFF) ||
- (f1->manufacturer == f2->manufacturer))
- {
- if ((f1->type == 0xFFFF) ||
- (f2->type == 0xFFFF) ||
- (f1->type == f2->type))
- {
- if ((f1->version == 0xFFFFFFFF) ||
- (f2->version == 0xFFFFFFFF) ||
- (f1->version == f2->version))
- {
- return TRUE;
- }
- }
- }
- return FALSE;
- }
- /******************************************************************************
- * @fn zclOTA_ImageBlockWaitExpired
- *
- * @brief Perform action on image block wait timer expiration.
- *
- * @param none
- *
- * @return none
- */
- static void zclOTA_ImageBlockWaitExpired(void)
- {
- // verify in 'in progress' state
- if (zclOTA_ImageUpgradeStatus == OTA_STATUS_IN_PROGRESS)
- {
- // request next block
- sendImageBlockReq(&zclOTA_serverAddr);
- }
- }
- /******************************************************************************
- * @fn zclOTA_UpgradeComplete
- *
- * @brief Notify the application task that an upgrade has completed.
- *
- * @param status - The status of the upgrade
- *
- * @return none
- */
- static void zclOTA_UpgradeComplete(uint8 status)
- {
- // Go back to the normal state
- zclOTA_ImageUpgradeStatus = OTA_STATUS_NORMAL;
- if ((zclOTA_DownloadedImageSize == OTA_HEADER_LEN_MIN_ECDSA) ||
- (zclOTA_DownloadedImageSize == OTA_HEADER_LEN_MIN))
- {
- status = ZFailure;
- }
- if (zclOTA_AppTask != 0xFF)
- {
- // Notify the application task the upgrade stopped
- zclOTA_CallbackMsg_t *pMsg;
- pMsg = (zclOTA_CallbackMsg_t*) osal_msg_allocate(sizeof(zclOTA_CallbackMsg_t));
- if (pMsg)
- {
- pMsg->hdr.event = ZCL_OTA_CALLBACK_IND;
- pMsg->hdr.status = status;
- pMsg->ota_event = ZCL_OTA_DL_COMPLETE_CALLBACK;
- osal_msg_send(zclOTA_AppTask, (uint8*) pMsg);
- }
- }
- }
- /******************************************************************************
- * @fn zclOTA_ProcessZDOMsgs
- *
- * @brief Process callbacks from the ZDO.
- *
- * @param pMsg - a Pointer to the message from the ZDO
- *
- * @return none
- */
- static void zclOTA_ProcessZDOMsgs( zdoIncomingMsg_t *pMsg )
- {
- if (pMsg->clusterID == IEEE_addr_rsp)
- {
- ZDO_NwkIEEEAddrResp_t *pNwkAddrRsp = ZDO_ParseAddrRsp( pMsg );
- // If this is from the OTA server, record the server's IEEE address
- if (pNwkAddrRsp != NULL)
- {
- if (pNwkAddrRsp->nwkAddr == zclOTA_serverAddr.addr.shortAddr)
- {
- osal_memcpy(&zclOTA_UpgradeServerID, pNwkAddrRsp->extAddr, Z_EXTADDR_LEN);
- }
- osal_mem_free( pNwkAddrRsp );
- }
- }
- }
- #endif // OTA_CLIENT
- #if defined (OTA_SERVER) && (OTA_SERVER == TRUE)
- /******************************************************************************
- * @fn zclOTA_ProcessNextImgRsp
- *
- * @brief Handles a response to a MT_OTA_NEXT_IMG_RSP.
- *
- * @param pMsg - The data from the server.
- * pFileId - The ID of the OTA File.
- * pAddr - The source of the message.
- *
- * @return none
- */
- void zclOTA_ProcessNextImgRsp(uint8* pMsg, zclOTA_FileID_t *pFileId,
- afAddrType_t *pAddr)
- {
- zclOTA_QueryImageRspParams_t queryRsp;
- uint8 options;
- uint8 status;
- // Get the status of the operation
- status = *pMsg++;
- // Get the options
- options = *pMsg++;
- // Copy the file ID
- osal_memcpy(&queryRsp.fileId, pFileId, sizeof(zclOTA_FileID_t));
- // Set the image size
- if (status == ZSuccess)
- {
- queryRsp.status = ZSuccess;
- queryRsp.imageSize = BUILD_UINT32(pMsg[0], pMsg[1], pMsg[2], pMsg[3]);
- }
- else
- {
- queryRsp.status = ZOtaNoImageAvailable;
- queryRsp.imageSize = 0;
- }
- queryResponse = queryRsp; // save global variable for query image response. Used later in image block request check
- // Send a response to the client
- if (options & MT_OTA_QUERY_SPECIFIC_OPTION)
- {
- zclOTA_SendQuerySpecificFileRsp(pAddr, &queryRsp);
- }
- else
- {
- zclOTA_SendQueryNextImageRsp(pAddr, &queryRsp);
- }
- }
- /******************************************************************************
- * @fn zclOTA_ProcessFileReadRsp
- *
- * @brief Handles a response to a MT_OTA_FILE_READ_RSP.
- *
- * @param pMsg - The data from the server.
- * pFileId - The ID of the OTA File.
- * pAddr - The source of the message.
- *
- * @return none
- */
- void zclOTA_ProcessFileReadRsp(uint8* pMsg, zclOTA_FileID_t *pFileId,
- afAddrType_t *pAddr)
- {
- zclOTA_ImageBlockRspParams_t blockRsp;
- // Set the status
- blockRsp.status = *pMsg++;
- // Check the status of the file read
- if (blockRsp.status == ZSuccess)
- {
- // Fill in the response parameters
- osal_memcpy(&blockRsp.rsp.success.fileId, pFileId, sizeof(zclOTA_FileID_t));
- blockRsp.rsp.success.fileOffset = BUILD_UINT32(pMsg[0], pMsg[1], pMsg[2], pMsg[3]);
- pMsg += 4;
- blockRsp.rsp.success.dataSize = *pMsg++;
- blockRsp.rsp.success.pData = pMsg;
- }
- else
- {
- blockRsp.status = ZOtaAbort;
- }
- // Send the block response to the peer
- zclOTA_SendImageBlockRsp(pAddr, &blockRsp);
- }
- /******************************************************************************
- * @fn OTA_HandleFileSysCb
- *
- * @brief Handles File Server Callbacks.
- *
- * @param pMSGpkt - The data from the server.
- *
- * @return none
- */
- void zclOTA_ServerHandleFileSysCb(OTA_MtMsg_t* pMSGpkt)
- {
- zclOTA_FileID_t pFileId;
- afAddrType_t pAddr;
- uint8 *pMsg;
- if (pMSGpkt != NULL)
- {
- // Get the File ID and AF Address
- pMsg = pMSGpkt->data;
- pMsg = OTA_StreamToFileId(&pFileId, pMsg);
- pMsg = OTA_StreamToAfAddr(&pAddr, pMsg);
- switch(pMSGpkt->cmd)
- {
- case MT_OTA_NEXT_IMG_RSP:
- zclOTA_ProcessNextImgRsp(pMsg, &pFileId, &pAddr);
- break;
- case MT_OTA_FILE_READ_RSP:
- zclOTA_ProcessFileReadRsp(pMsg, &pFileId, &pAddr);
- break;
- default:
- break;
- }
- }
- }
- /******************************************************************************
- * @fn zclOTA_Srv_QueryNextImageReq
- *
- * @brief Handle a Query Next Image Request.
- *
- * @param pSrcAddr - The source of the message
- * pParam - message parameters
- *
- * @return ZStatus_t
- *
- * @note On a query next image, we must request a file listing
- * from the File Server. Then open a file if
- */
- ZStatus_t zclOTA_Srv_QueryNextImageReq(afAddrType_t *pSrcAddr, zclOTA_QueryNextImageReqParams_t *pParam)
- {
- uint8 options = 0;
- uint8 status;
- if (zclOTA_Permit)
- {
- if (pParam->fieldControl)
- {
- options |= MT_OTA_HW_VER_PRESENT_OPTION;
- }
- // Request the next image for this device from the console via the MT File System
- status = MT_OtaGetImage(pSrcAddr, &pParam->fileId, pParam->hardwareVersion, NULL, options);
- }
- else
- {
- status = ZOtaNoImageAvailable;
- }
- if (status != ZSuccess)
- {
- zclOTA_QueryImageRspParams_t queryRsp;
- // Fill in the response parameters
- osal_memcpy(&queryRsp.fileId, &pParam->fileId, sizeof(zclOTA_FileID_t));
- queryRsp.status = ZOtaNoImageAvailable;
- queryRsp.imageSize = 0;
- // Send a failure response to the client
- zclOTA_SendQueryNextImageRsp(pSrcAddr, &queryRsp);
- }
- return ZCL_STATUS_CMD_HAS_RSP;
- }
- /******************************************************************************
- * @fn zclOTA_Srv_ImageBlockReq
- *
- * @brief Handle an Image Block Request.
- *
- * @param pSrcAddr - The source of the message
- * pParam - message parameters
- *
- * @return ZStatus_t
- */
- ZStatus_t zclOTA_Srv_ImageBlockReq(afAddrType_t *pSrcAddr, zclOTA_ImageBlockReqParams_t *pParam)
- {
- uint8 status = ZFailure;
- if (pParam->fileId.version != queryResponse.fileId.version)
- {
- status = ZCL_STATUS_NO_IMAGE_AVAILABLE;
- }
- else
- {
- if (zclOTA_Permit && (pParam != NULL))
- {
- uint8 len = pParam->maxDataSize;
- if (len > OTA_MAX_MTU)
- {
- len = OTA_MAX_MTU;
- }
- // Read the data from the OTA Console
- status = MT_OtaFileReadReq(pSrcAddr, &pParam->fileId, len, pParam->fileOffset);
- // Send a wait response to the client
- if (status != ZSuccess)
- {
- zclOTA_ImageBlockRspParams_t blockRsp;
- // Fill in the response parameters
- blockRsp.status = ZOtaWaitForData;
- osal_memcpy(&blockRsp.rsp.success.fileId, &pParam->fileId, sizeof(zclOTA_FileID_t));
- blockRsp.rsp.wait.currentTime = 0;
- blockRsp.rsp.wait.requestTime = OTA_SEND_BLOCK_WAIT;
- // Send the block to the peer
- zclOTA_SendImageBlockRsp(pSrcAddr, &blockRsp);
- }
- status = ZCL_STATUS_CMD_HAS_RSP;
- }
- }
- return status;
- }
- /******************************************************************************
- * @fn zclOTA_Srv_ImagePageReq
- *
- * @brief Handle an Image Page Request. Note: Not currently supported.
- *
- * @param pSrcAddr - The source of the message
- * pParam - message parameters
- *
- * @return ZStatus_t
- */
- ZStatus_t zclOTA_Srv_ImagePageReq(afAddrType_t *pSrcAddr, zclOTA_ImagePageReqParams_t *pParam)
- {
- // Send not supported resposne
- return ZUnsupClusterCmd;
- }
- /******************************************************************************
- * @fn zclOTA_Srv_UpgradeEndReq
- *
- * @brief Handle an Upgrade End Request.
- *
- * @param pSrcAddr - The source of the message
- * pParam - message parameters
- *
- * @return ZStatus_t
- */
- ZStatus_t zclOTA_Srv_UpgradeEndReq(afAddrType_t *pSrcAddr, zclOTA_UpgradeEndReqParams_t *pParam)
- {
- uint8 status = ZFailure;
- if (zclOTA_Permit && (pParam != NULL))
- {
- zclOTA_UpgradeEndRspParams_t rspParms;
- if (pParam->status == ZSuccess)
- {
- osal_memcpy(&rspParms.fileId, &pParam->fileId, sizeof(zclOTA_FileID_t));
- rspParms.currentTime = osal_GetSystemClock();
- rspParms.upgradeTime = rspParms.currentTime + OTA_UPGRADE_DELAY;
- // Send the response to the peer
- zclOTA_SendUpgradeEndRsp(pSrcAddr, &rspParms);
- }
- // Notify the Console Tool
- MT_OtaSendStatus(pSrcAddr->addr.shortAddr, MT_OTA_DL_COMPLETE, pParam->status, 0);
- status = ZCL_STATUS_CMD_HAS_RSP;
- }
- return status;
- }
- /******************************************************************************
- * @fn zclOTA_Srv_QuerySpecificFileReq
- *
- * @brief Handles a Query Specific File Request.
- *
- * @param pSrcAddr - The source of the message
- * pParam - message parameters
- *
- * @return ZStatus_t
- */
- ZStatus_t zclOTA_Srv_QuerySpecificFileReq(afAddrType_t *pSrcAddr, zclOTA_QuerySpecificFileReqParams_t *pParam)
- {
- uint8 status;
- // Request the image from the console
- if (zclOTA_Permit)
- {
- status = MT_OtaGetImage(pSrcAddr, &pParam->fileId, 0, pParam->nodeAddr, MT_OTA_QUERY_SPECIFIC_OPTION);
- }
- else
- {
- status = ZOtaNoImageAvailable;
- }
- if (status != ZSuccess)
- {
- zclOTA_QueryImageRspParams_t queryRsp;
- // Fill in the response parameters
- osal_memcpy(&queryRsp.fileId, &pParam->fileId, sizeof(zclOTA_FileID_t));
- queryRsp.status = ZOtaNoImageAvailable;
- queryRsp.imageSize = 0;
- // Send a failure response to the client
- zclOTA_SendQuerySpecificFileRsp(pSrcAddr, &queryRsp);
- }
- return ZCL_STATUS_CMD_HAS_RSP;
- }
- /******************************************************************************
- * @fn zclOTA_ProcessQueryNextImageReq
- *
- * @brief Process received Query Next Image Request.
- *
- * @param pInMsg - pointer to the incoming message
- *
- * @return ZStatus_t
- */
- static ZStatus_t zclOTA_ProcessQueryNextImageReq( zclIncoming_t *pInMsg )
- {
- zclOTA_QueryNextImageReqParams_t param;
- uint8 *pData;
- /* verify message length */
- if ((pInMsg->pDataLen != PAYLOAD_MAX_LEN_QUERY_NEXT_IMAGE_REQ) &&
- (pInMsg->pDataLen != PAYLOAD_MIN_LEN_QUERY_NEXT_IMAGE_REQ))
- {
- /* no further processing if invalid */
- return ZCL_STATUS_MALFORMED_COMMAND;
- }
- /* parse message parameters */
- pData = pInMsg->pData;
- param.fieldControl = *pData++;
- param.fileId.manufacturer = BUILD_UINT16(pData[0], pData[1]);
- pData += 2;
- param.fileId.type = BUILD_UINT16(pData[0], pData[1]);
- pData += 2;
- param.fileId.version = osal_build_uint32( pData, 4 );
- pData += 4;
- if ((param.fieldControl & 0x01) != 0)
- {
- param.hardwareVersion = BUILD_UINT16(pData[0], pData[1]);
- }
- /* call callback */
- return zclOTA_Srv_QueryNextImageReq(&pInMsg->msg->srcAddr, ¶m);
- }
- /******************************************************************************
- * @fn zclOTA_ProcessImageBlockReq
- *
- * @brief Process received Image Block Request.
- *
- * @param pInMsg - pointer to the incoming message
- *
- * @return ZStatus_t
- */
- static ZStatus_t zclOTA_ProcessImageBlockReq( zclIncoming_t *pInMsg )
- {
- zclOTA_ImageBlockReqParams_t param;
- uint8 *pData;
- /* verify message length */
- if ((pInMsg->pDataLen != PAYLOAD_MAX_LEN_IMAGE_BLOCK_REQ) &&
- (pInMsg->pDataLen != PAYLOAD_MIN_LEN_IMAGE_BLOCK_REQ))
- {
- /* no further processing if invalid */
- return ZCL_STATUS_MALFORMED_COMMAND;
- }
- /* parse message parameters */
- pData = pInMsg->pData;
- param.fieldControl = *pData++;
- param.fileId.manufacturer = BUILD_UINT16(pData[0], pData[1]);
- pData += 2;
- param.fileId.type = BUILD_UINT16(pData[0], pData[1]);
- pData += 2;
- param.fileId.version = osal_build_uint32( pData, 4 );
- pData += 4;
- param.fileOffset = osal_build_uint32( pData, 4 );
- pData += 4;
- param.maxDataSize = *pData++;
- if ((param.fieldControl & 0x01) != 0)
- {
- osal_cpyExtAddr(param.nodeAddr, pData);
- }
- /* call callback */
- return zclOTA_Srv_ImageBlockReq(&pInMsg->msg->srcAddr, ¶m);
- }
- /******************************************************************************
- * @fn zclOTA_ProcessImagePageReq
- *
- * @brief Process received Image Page Request.
- *
- * @param pInMsg - pointer to the incoming message
- *
- * @return ZStatus_t
- */
- static ZStatus_t zclOTA_ProcessImagePageReq( zclIncoming_t *pInMsg )
- {
- zclOTA_ImagePageReqParams_t param;
- uint8 *pData;
- /* verify message length */
- if ((pInMsg->pDataLen != PAYLOAD_MAX_LEN_IMAGE_PAGE_REQ) &&
- (pInMsg->pDataLen != PAYLOAD_MIN_LEN_IMAGE_PAGE_REQ))
- {
- /* no further processing if invalid */
- return ZCL_STATUS_MALFORMED_COMMAND;
- }
- /* parse message parameters */
- pData = pInMsg->pData;
- param.fieldControl = *pData++;
- param.fileId.manufacturer = BUILD_UINT16(pData[0], pData[1]);
- pData += 2;
- param.fileId.type = BUILD_UINT16(pData[0], pData[1]);
- pData += 2;
- param.fileId.version = osal_build_uint32( pData, 4 );
- pData += 4;
- param.fileOffset = osal_build_uint32( pData, 4 );
- pData += 4;
- param.maxDataSize = *pData++;
- param.pageSize = BUILD_UINT16(pData[0], pData[1]);
- pData += 2;
- param.responseSpacing = BUILD_UINT16(pData[0], pData[1]);
- pData += 2;
- if ((param.fieldControl & 0x01) != 0)
- {
- osal_cpyExtAddr(param.nodeAddr, pData);
- }
- /* call callback */
- return zclOTA_Srv_ImagePageReq(&pInMsg->msg->srcAddr, ¶m);
- }
- /******************************************************************************
- * @fn zclOTA_ProcessUpgradeEndReq
- *
- * @brief Process received Upgrade End Request.
- *
- * @param pInMsg - pointer to the incoming message
- *
- * @return ZStatus_t
- */
- static ZStatus_t zclOTA_ProcessUpgradeEndReq( zclIncoming_t *pInMsg )
- {
- zclOTA_UpgradeEndReqParams_t param;
- uint8 *pData;
- /* verify message length */
- if ((pInMsg->pDataLen != PAYLOAD_MAX_LEN_UPGRADE_END_REQ) &&
- (pInMsg->pDataLen != PAYLOAD_MIN_LEN_UPGRADE_END_REQ))
- {
- /* no further processing if invalid */
- return ZCL_STATUS_MALFORMED_COMMAND;
- }
- /* parse message parameters */
- pData = pInMsg->pData;
- param.status = *pData++;
- if (param.status == ZCL_STATUS_SUCCESS)
- {
- param.fileId.manufacturer = BUILD_UINT16(pData[0], pData[1]);
- pData += 2;
- param.fileId.type = BUILD_UINT16(pData[0], pData[1]);
- pData += 2;
- param.fileId.version = osal_build_uint32( pData, 4 );
- }
- /* call callback */
- return zclOTA_Srv_UpgradeEndReq(&pInMsg->msg->srcAddr, ¶m);
- }
- /******************************************************************************
- * @fn zclOTA_ProcessQuerySpecificFileReq
- *
- * @brief Process received Image Page Request.
- *
- * @param pInMsg - pointer to the incoming message
- *
- * @return ZStatus_t
- */
- static ZStatus_t zclOTA_ProcessQuerySpecificFileReq( zclIncoming_t *pInMsg )
- {
- zclOTA_QuerySpecificFileReqParams_t param;
- uint8 *pData;
- /* verify message length */
- if (pInMsg->pDataLen != PAYLOAD_MAX_LEN_QUERY_SPECIFIC_FILE_REQ)
- {
- /* no further processing if invalid */
- return ZCL_STATUS_MALFORMED_COMMAND;
- }
- /* parse message parameters */
- pData = pInMsg->pData;
- osal_cpyExtAddr(param.nodeAddr, pData);
- pData += Z_EXTADDR_LEN;
- param.fileId.manufacturer = BUILD_UINT16(pData[0], pData[1]);
- pData += 2;
- param.fileId.type = BUILD_UINT16(pData[0], pData[1]);
- pData += 2;
- param.fileId.version = osal_build_uint32( pData, 4 );
- pData += 4;
- param.stackVersion = BUILD_UINT16(pData[0], pData[1]);
- /* call callback */
- return zclOTA_Srv_QuerySpecificFileReq(&pInMsg->msg->srcAddr, ¶m);
- }
- /******************************************************************************
- * @fn zclOTA_ServerHdlIncoming
- *
- * @brief Handle incoming server commands.
- *
- * @param pInMsg - pointer to the incoming message
- *
- * @return ZStatus_t
- */
- static ZStatus_t zclOTA_ServerHdlIncoming( zclIncoming_t *pInMsg )
- {
- switch (pInMsg->hdr.commandID)
- {
- case COMMAND_QUERY_NEXT_IMAGE_REQ:
- return zclOTA_ProcessQueryNextImageReq( pInMsg );
- case COMMAND_IMAGE_BLOCK_REQ:
- return zclOTA_ProcessImageBlockReq( pInMsg );
- case COMMAND_IMAGE_PAGE_REQ:
- return zclOTA_ProcessImagePageReq( pInMsg );
- case COMMAND_UPGRADE_END_REQ:
- return zclOTA_ProcessUpgradeEndReq( pInMsg );
- case COMMAND_QUERY_SPECIFIC_FILE_REQ:
- return zclOTA_ProcessQuerySpecificFileReq( pInMsg );
- default:
- return ZFailure;
- }
- }
- #endif // OTA_SERVER
|