From b24866225a6301d3a663f874725e83c012dc25d3 Mon Sep 17 00:00:00 2001 From: Florent Duchon Date: Wed, 26 Dec 2012 17:36:00 +0100 Subject: digital/beacon: add bitcloud stack into common directory digital/zigbit --- .../HAL/drivers/ISD/src/isdImageStorage.c | 626 +++++++++++++++++++++ 1 file changed, 626 insertions(+) create mode 100644 digital/zigbit/bitcloud/stack/Components/HAL/drivers/ISD/src/isdImageStorage.c (limited to 'digital/zigbit/bitcloud/stack/Components/HAL/drivers/ISD/src/isdImageStorage.c') diff --git a/digital/zigbit/bitcloud/stack/Components/HAL/drivers/ISD/src/isdImageStorage.c b/digital/zigbit/bitcloud/stack/Components/HAL/drivers/ISD/src/isdImageStorage.c new file mode 100644 index 00000000..a173da69 --- /dev/null +++ b/digital/zigbit/bitcloud/stack/Components/HAL/drivers/ISD/src/isdImageStorage.c @@ -0,0 +1,626 @@ +/**************************************************************************//** +\file isdImageStorage.c + +\brief Implementation of image storage driver. + +\author + Atmel Corporation: http://www.atmel.com \n + Support email: avr@atmel.com + + Copyright (c) 2008-2011, Atmel Corporation. All rights reserved. + Licensed under Atmel's Limited License Agreement (BitCloudTM). + +\internal + History: + 25.05.11 A. Khromykh - Created +*******************************************************************************/ +/****************************************************************************** + * WARNING: CHANGING THIS FILE MAY AFFECT CORE FUNCTIONALITY OF THE STACK. * + * EXPERT USERS SHOULD PROCEED WITH CAUTION. * + ******************************************************************************/ + +#ifdef _OTAU_ +#if (APP_USE_OTAU == 1) + +/****************************************************************************** + Includes section +******************************************************************************/ +#include +#include +#include +#include +#include +#include +#include + +/****************************************************************************** + Defines section +******************************************************************************/ +// Size of length field in frame +#define LEN_SIZE (sizeof(((IsdCommandFrame_t*)NULL)->length)) +// Start of frame market +#define SOF 0x2A +// 500 ms interbyte timeout should be enough for everyone +#define INTERBYTE_TIMEOUT 500 +// 5000 ms timeout between request to storage system and response from it. +#define INTERMESSAGE_TIMEOUT 5000 +#define USART_RX_BUFFER_LENGTH 104 + +#ifndef APP_MAX_COMMAND_PAYLOAD_SIZE + #define APP_MAX_COMMAND_PAYLOAD_SIZE 100 +#endif + +// code from runner +#define ISD_ZCL_COMMAND_INDICATION 0x0046 +#define ISD_ZCL_COMMAND_REQUEST 0x0044 +#define ISD_DRIVER_INIT_REQUEST 0x0100 +#define ISD_DRIVER_INIT_RESPONSE 0x0101 +#define ISD_COMMAND_ID_SIZE (sizeof(uint16_t)) +#define ISD_INIT_MARKER 0x55 +/****************************************************************************** + Types section +******************************************************************************/ +// States of tx FSM +typedef enum _TxState_t +{ + TX_ERR_OR_OFF, + TX_IDLE, + TX_SENDING_SOF, + TX_SENDING_DATA, +} TxState_t; + +// States of rx FSM +typedef enum _RxState_t +{ + RX_ERR_OR_OFF, + RX_WAITING_START, // AKA IDLE + RX_WAITING_LEN, + RX_WAITING_DATA, +} RxState_t; + +BEGIN_PACK +typedef struct PACK _IsdCommandFrame_t +{ + uint16_t length; + uint16_t commandId; + uint8_t payload[APP_MAX_COMMAND_PAYLOAD_SIZE]; +} IsdCommandFrame_t; + +typedef struct PACK +{ + uint8_t srcAddrMode; + ShortAddr_t srcShortAddress; + ExtAddr_t srcExtAddress; + ProfileId_t srcProfileId; + Endpoint_t srcEndpointId; + ClusterId_t srcClusterId; + + ClusterId_t clusterId; + uint8_t direction; + uint8_t commandId; + uint8_t payload[1]; +} IsdCommandIndication_t; + +typedef struct PACK +{ + LITTLE_ENDIAN_OCTET(3,( + uint8_t direction : 1, + uint8_t generalCommand : 1, + uint8_t reserved : 6 + )) +} IsdCommandOptions_t; + +typedef struct PACK +{ + uint8_t addrMode; + ShortAddr_t shortAddress; + ExtAddr_t extAddress; + ProfileId_t profileId; + uint8_t endpoint; + uint8_t dstEndpoint; + ClusterId_t clusterId; + uint8_t defaultResponse; + IsdCommandOptions_t commandOptions; + uint8_t commandId; + uint8_t recordsCount; + uint8_t request[1]; +} IsdCommandRequest_t; +END_PACK + +/****************************************************************************** + Static Function Prototypes section +******************************************************************************/ +static void isdUsartReceivedHandler(uint16_t bytesAmount); +static void isdSendCommandFrame(void); +static void isdUsartTransmittedHandler(void); +static void isdInterbyteTimeoutExpired(void); +static void isdIntermessageTimeoutExpired(void); +static void isdInitReq(void); +static void isdInitResp(void); +static void isdSerialNotify(void); +static void isdSetState(ISD_Status_t state); + +/****************************************************************************** + Static variables section +******************************************************************************/ +static HAL_UsartDescriptor_t usartDescriptor; +static RxState_t rxState = RX_ERR_OR_OFF; +static TxState_t txState = TX_ERR_OR_OFF; +static uint8_t usartDescriptorRxBuffer[USART_RX_BUFFER_LENGTH]; +static IsdCommandFrame_t isdBuffer; + +static HAL_AppTimer_t interbyteTimer = +{ + .interval = INTERBYTE_TIMEOUT, + .mode = TIMER_ONE_SHOT_MODE, + .callback = isdInterbyteTimeoutExpired, +}; + +static HAL_AppTimer_t intermessageTimer = +{ + .interval = INTERMESSAGE_TIMEOUT, + .mode = TIMER_ONE_SHOT_MODE, + .callback = isdIntermessageTimeoutExpired, +}; + +static IsdOpenCb_t generalCb; +static IsdUpgradeEndCb_t upgradeEndCb; +static IsdQueryNextImageCb_t queryNextImageCb; +static IsdImageBlockCb_t imageBlockCb; + +static ISD_Status_t isdState; + +/****************************************************************************** + Implementations section +******************************************************************************/ +/**************************************************************************//** +\brief Open image storage driver + +\param[in] cb - callback about driver actions +******************************************************************************/ +void ISD_Open(IsdOpenCb_t cb) +{ + // Implementation depends on 'length' field in IsdCommandFrame_t being one byte + // In case of change, several modifications would be required + assert_static(2 == LEN_SIZE); + // Also depends on 'length' field being first field of command frame + assert_static(0 == offsetof(IsdCommandFrame_t, length)); + +#ifdef BSP_ENABLE_RS232_CONTROL + BSP_EnableRs232(); +#endif /* BSP_ENABLE_RS232_CONTROL */ + + usartDescriptor.tty = APP_USART_CHANNEL; + usartDescriptor.mode = USART_MODE_ASYNC; + usartDescriptor.flowControl = USART_FLOW_CONTROL_NONE; + usartDescriptor.baudrate = USART_BAUDRATE_38400; + usartDescriptor.dataLength = USART_DATA8; + usartDescriptor.parity = USART_PARITY_NONE; + usartDescriptor.stopbits = USART_STOPBIT_1; + usartDescriptor.rxBuffer = usartDescriptorRxBuffer; + usartDescriptor.rxBufferLength = USART_RX_BUFFER_LENGTH; //BULK_SIZE + usartDescriptor.txBuffer = NULL; + usartDescriptor.txBufferLength = 0; + usartDescriptor.rxCallback = isdUsartReceivedHandler; + usartDescriptor.txCallback = isdUsartTransmittedHandler; + + generalCb = cb; + + if (-1 != HAL_OpenUsart(&usartDescriptor)) + { + rxState = RX_WAITING_START; + txState = TX_IDLE; + isdInitReq(); + } + else + { + rxState = RX_ERR_OR_OFF; + txState = TX_ERR_OR_OFF; + isdSetState(ISD_HARDWARE_FAULT); + } +} + +/**************************************************************************//** +\brief Request to storage system about communication. +******************************************************************************/ +static void isdInitReq(void) +{ + isdBuffer.commandId = ISD_DRIVER_INIT_REQUEST; + isdBuffer.length = ISD_COMMAND_ID_SIZE + sizeof(uint8_t); + isdBuffer.payload[0] = ISD_INIT_MARKER; + + HAL_StartAppTimer(&intermessageTimer); + isdSendCommandFrame(); +} + +/**************************************************************************//** +\brief Response from storage system about communication. +******************************************************************************/ +static void isdInitResp(void) +{ + HAL_StopAppTimer(&intermessageTimer); + + if (ISD_INIT_MARKER != isdBuffer.payload[0]) + isdSetState(ISD_COMMUNICATION_LOST); + else + isdSetState(ISD_SUCCESS); +} + +/**************************************************************************//** +\brief Close image storage driver +******************************************************************************/ +void ISD_Close(void) +{ + rxState = RX_ERR_OR_OFF; + txState = TX_ERR_OR_OFF; + HAL_CloseUsart(&usartDescriptor); +} + +/**************************************************************************//** +\brief Reset rx FSM on expiration of interbyte timeout +******************************************************************************/ +static void isdInterbyteTimeoutExpired(void) +{ + if (RX_ERR_OR_OFF != rxState) + rxState = RX_WAITING_START; +} + +/**************************************************************************//** +\brief Callback about timout expiration between request and response +******************************************************************************/ +static void isdIntermessageTimeoutExpired(void) +{ + isdSetState(ISD_COMMUNICATION_LOST); + isdInitReq(); +} + +/**************************************************************************//** +\brief Callback on reception of serial byte(s) + +\param[in] bytesAmount number of received bytes +******************************************************************************/ +static void isdUsartReceivedHandler(uint16_t bytesAmount) +{ + static uint16_t rxCnt = 0; + while (bytesAmount) + { + switch (rxState) + { + case RX_WAITING_START: + { + uint8_t data; + if (HAL_ReadUsart(&usartDescriptor, &data, sizeof(uint8_t)) <= 0) + { + rxState = RX_ERR_OR_OFF; + isdSetState(ISD_HARDWARE_FAULT); + return; + } + if (SOF == data) + rxState = RX_WAITING_LEN; + + bytesAmount--; + } + break; + + case RX_WAITING_LEN: + { + if (bytesAmount >= sizeof(uint16_t)) + { + if (HAL_ReadUsart(&usartDescriptor, (uint8_t *)&isdBuffer.length, sizeof(uint16_t)) <= 0) + { + rxState = RX_ERR_OR_OFF; + isdSetState(ISD_HARDWARE_FAULT); + return; + } + + // Limit length to avoid possible buffer overflow + isdBuffer.length = MIN(isdBuffer.length, sizeof(IsdCommandFrame_t) - LEN_SIZE); + + if (isdBuffer.length > 0) + rxState = RX_WAITING_DATA; + else + rxState = RX_WAITING_START; // Do not allow zero len + + bytesAmount -= sizeof(uint16_t); + rxCnt = 0; + } + else + return; + } + break; + + case RX_WAITING_DATA: + { + int readCnt; + uint8_t *readPtr = (uint8_t *)&isdBuffer; + + readPtr += offsetof(IsdCommandFrame_t, commandId) + rxCnt; + readCnt = HAL_ReadUsart(&usartDescriptor, readPtr, MIN(bytesAmount, (uint16_t) (isdBuffer.length - rxCnt))); + + if (readCnt <= 0) + { + rxState = RX_ERR_OR_OFF; + isdSetState(ISD_HARDWARE_FAULT); + return; + } + + bytesAmount -= readCnt; + rxCnt += readCnt; + if (rxCnt >= isdBuffer.length) + { + // Full packet is received + rxState = RX_WAITING_START; + isdSerialNotify(); + } + } + break; + + case RX_ERR_OR_OFF: + default: + return; + } + } + + HAL_StopAppTimer(&interbyteTimer); + + if (RX_WAITING_DATA == rxState || RX_WAITING_LEN == rxState) + HAL_StartAppTimer(&interbyteTimer); +} + +/**************************************************************************//** +\brief Sends new command frame + +\return result code +******************************************************************************/ +static void isdSendCommandFrame(void) +{ + static uint8_t sof = SOF; + + if (HAL_WriteUsart(&usartDescriptor, &sof, sizeof(sof)) > 0) + { + txState = TX_SENDING_SOF; + } + else + { + txState = TX_ERR_OR_OFF; + isdSetState(ISD_HARDWARE_FAULT); + } +} + +/**************************************************************************//** +\brief Callback on completion of single serial transmit +******************************************************************************/ +static void isdUsartTransmittedHandler(void) +{ + switch (txState) + { + case TX_SENDING_SOF: + { + uint8_t *writePtr = (uint8_t *)&isdBuffer; + + writePtr += offsetof(IsdCommandFrame_t, length); + if (HAL_WriteUsart(&usartDescriptor, writePtr, isdBuffer.length + LEN_SIZE) <= 0) + { + txState = TX_ERR_OR_OFF; + isdSetState(ISD_HARDWARE_FAULT); + } + else + txState = TX_SENDING_DATA; + } + break; + + case TX_SENDING_DATA: + txState = TX_IDLE; + break; + + case TX_IDLE: + case TX_ERR_OR_OFF: + default: + break; + } +} + +/**************************************************************************//** +\brief Send query next image request to storage system + +\param[in] addressing - pointer to structure that include client network information; \n +\param[in] data - data payload; \n +\param[in] cd - callback about response receiving from storage system. +******************************************************************************/ +void ISD_QueryNextImageReq(ZCL_Addressing_t *addressing, ZCL_OtauQueryNextImageReq_t *data, IsdQueryNextImageCb_t cb) +{ + IsdCommandIndication_t *serialData = (IsdCommandIndication_t *)isdBuffer.payload; + + if (ISD_SUCCESS != isdState) + return; + + serialData->clusterId = addressing->clusterId; + serialData->commandId = QUERY_NEXT_IMAGE_REQUEST_ID; + serialData->srcAddrMode = addressing->addrMode; + serialData->srcShortAddress = addressing->addr.shortAddress; + serialData->srcExtAddress = addressing->addr.extAddress; + serialData->srcProfileId = addressing->profileId; + serialData->srcEndpointId = addressing->endpointId; + serialData->srcClusterId = addressing->clusterId; + serialData->direction = addressing->clusterSide; + + memcpy(serialData->payload, data, sizeof(ZCL_OtauQueryNextImageReq_t)); + + isdBuffer.commandId = ISD_ZCL_COMMAND_INDICATION; + isdBuffer.length = ISD_COMMAND_ID_SIZE + sizeof(IsdCommandIndication_t) + + sizeof(ZCL_OtauQueryNextImageReq_t) - sizeof(uint8_t); + + queryNextImageCb = cb; + + HAL_StartAppTimer(&intermessageTimer); + isdSendCommandFrame(); +} + +/**************************************************************************//** +\brief Send image block request to storage system + +\param[in] addressing - pointer to structure that include client network information; \n +\param[in] data - data payload; \n +\param[in] cd - callback about response receiving from storage system. +******************************************************************************/ +void ISD_ImageBlockReq(ZCL_Addressing_t *addressing, ZCL_OtauImageBlockReq_t *data, IsdImageBlockCb_t cb) +{ + IsdCommandIndication_t *serialData = (IsdCommandIndication_t *)isdBuffer.payload; + + if (ISD_SUCCESS != isdState) + return; + + serialData->clusterId = addressing->clusterId; + serialData->commandId = IMAGE_BLOCK_REQUEST_ID; + serialData->srcAddrMode = addressing->addrMode; + serialData->srcShortAddress = addressing->addr.shortAddress; + serialData->srcExtAddress = addressing->addr.extAddress; + serialData->srcProfileId = addressing->profileId; + serialData->srcEndpointId = addressing->endpointId; + serialData->srcClusterId = addressing->clusterId; + serialData->direction = addressing->clusterSide; + + memcpy(serialData->payload, data, sizeof(ZCL_OtauImageBlockReq_t)); + + isdBuffer.commandId = ISD_ZCL_COMMAND_INDICATION; + isdBuffer.length = ISD_COMMAND_ID_SIZE + sizeof(IsdCommandIndication_t) + + sizeof(ZCL_OtauImageBlockReq_t) - sizeof(uint8_t); + + imageBlockCb = cb; + + HAL_StartAppTimer(&intermessageTimer); + isdSendCommandFrame(); +} + +/**************************************************************************//** +\brief Send upgrade end request to storage system + +\param[in] addressing - pointer to structure that include client network information; \n +\param[in] data - data payload; \n +\param[in] cd - callback about response receiving from storage system. +******************************************************************************/ +void ISD_UpgradeEndReq(ZCL_Addressing_t *addressing, ZCL_OtauUpgradeEndReq_t *data, IsdUpgradeEndCb_t cb) +{ + IsdCommandIndication_t *serialData = (IsdCommandIndication_t *)isdBuffer.payload; + + if (ISD_SUCCESS != isdState) + return; + + serialData->clusterId = addressing->clusterId; + serialData->commandId = UPGRADE_END_REQUEST_ID; + serialData->srcAddrMode = addressing->addrMode; + serialData->srcShortAddress = addressing->addr.shortAddress; + serialData->srcExtAddress = addressing->addr.extAddress; + serialData->srcProfileId = addressing->profileId; + serialData->srcEndpointId = addressing->endpointId; + serialData->srcClusterId = addressing->clusterId; + serialData->direction = addressing->clusterSide; + + memcpy(serialData->payload, data, sizeof(ZCL_OtauUpgradeEndReq_t)); + + isdBuffer.commandId = ISD_ZCL_COMMAND_INDICATION; + isdBuffer.length = ISD_COMMAND_ID_SIZE + sizeof(IsdCommandIndication_t) + + sizeof(ZCL_OtauUpgradeEndReq_t) - sizeof(uint8_t); + + upgradeEndCb = cb; + + HAL_StartAppTimer(&intermessageTimer); + isdSendCommandFrame(); +} + +/**************************************************************************//** +\brief Receive any messages from storage system +******************************************************************************/ +static void isdSerialNotify(void) +{ + IsdCommandRequest_t *req = (IsdCommandRequest_t *)isdBuffer.payload; + + if (ISD_DRIVER_INIT_RESPONSE == isdBuffer.commandId) + { + isdInitResp(); + return; + } + + if (ISD_ZCL_COMMAND_REQUEST != isdBuffer.commandId) + return; + + if (OTAU_CLUSTER_ID != req->clusterId) + return; + + switch (req->commandId) + { + case QUERY_NEXT_IMAGE_RESPONSE_ID: + { + ZCL_OtauQueryNextImageResp_t *resp = (ZCL_OtauQueryNextImageResp_t *)req->request; + + HAL_StopAppTimer(&intermessageTimer); + if (queryNextImageCb) + { + queryNextImageCb(resp); + queryNextImageCb = NULL; + } + } + break; + case IMAGE_BLOCK_RESPONSE_ID: + { + ZCL_OtauImageBlockResp_t *resp = (ZCL_OtauImageBlockResp_t *)req->request; + + HAL_StopAppTimer(&intermessageTimer); + if (imageBlockCb) + { + imageBlockCb(resp); + imageBlockCb = NULL; + } + } + break; + case UPGRADE_END_RESPONSE_ID: + { + ZCL_OtauUpgradeEndResp_t *resp = (ZCL_OtauUpgradeEndResp_t *)req->request; + + HAL_StopAppTimer(&intermessageTimer); + if (upgradeEndCb) + { + upgradeEndCb(resp); + upgradeEndCb = NULL; + } + else + { + ZCL_Addressing_t addr = + { + .addrMode = req->addrMode, + .profileId = req->profileId, + .endpointId = req->dstEndpoint, + .clusterId = req->clusterId, + .clusterSide = ZCL_CLIENT_CLUSTER_TYPE, + .manufacturerSpecCode = 0, + }; + + if (APS_EXT_ADDRESS == addr.addrMode) + addr.addr.extAddress = req->extAddress; + else + addr.addr.shortAddress = req->shortAddress; + + ZCL_UnsolicitedUpgradeEndResp(&addr, resp); + } + } + break; + } +} + +/**************************************************************************//** +\brief Set actual driver state and report to high layer about that. + +\param[in] state - actual driver state +******************************************************************************/ +static void isdSetState(ISD_Status_t state) +{ + isdState = state; + + if (generalCb) + generalCb(state); +} + +#endif // (APP_USE_OTAU == 1) +#endif // _OTAU_ + +// eof isdImageStorage.c -- cgit v1.2.3