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 --- .../drivers/USBClasses/MSD/src/massStorageDevice.c | 327 +++++++++++++++++++++ 1 file changed, 327 insertions(+) create mode 100644 digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/massStorageDevice.c (limited to 'digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/massStorageDevice.c') diff --git a/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/massStorageDevice.c b/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/massStorageDevice.c new file mode 100644 index 00000000..94c36c42 --- /dev/null +++ b/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/massStorageDevice.c @@ -0,0 +1,327 @@ +/****************************************************************************//** + \file massStorageDevice.c + + \brief Implementation of mass storage API. + + \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: + 29/08/11 N. Fomin - Created +*******************************************************************************/ +/****************************************************************************** + Includes section +******************************************************************************/ +#include +#include +#include +#include +#include +#include +#include + +/****************************************************************************** + Defines section +******************************************************************************/ +#define CBW_SIZE 31 +#define CBW_SIGNATURE 0x43425355 + +#define CSW_SIZE 13 +#define CSW_COMMAND_FAILED_STATUS 1 +#define CSW_COMMAND_SUCCESS_STATUS 0 + +/****************************************************************************** + Types section +******************************************************************************/ +typedef enum +{ + MSD_COMMAND_TRANSPORT, + MSD_SCSI_ANSWER, + MSD_DATA_INOUT, + MSD_STATUS_TRANSPORT +} MsdState_t; + +typedef struct +{ + uint32_t bufferOffset; + uint16_t buffersToTransfer; + uint32_t blockAddress; +} MsdReadWriteControl_t; + +/****************************************************************************** + Prototypes section +******************************************************************************/ +static void msdBufferReadCallback(MemoryStatus_t status); +static void msdBufferWriteCallback(MemoryStatus_t status); + +/****************************************************************************** + External global variables section +******************************************************************************/ +static UsbMscRequest_t request; + +/****************************************************************************** + Global variables section +******************************************************************************/ +// pointer to application hsmci descriptor +static HAL_HsmciDescriptor_t msdDescr; +HAL_HsmciDescriptor_t *msdPointDescr; +static HAL_HsmciCommandDescriptor_t commandDescr; +static HAL_HsmciDataTransferDescriptor_t dataTransferDescr; +static MsdReadWriteControl_t rwControl; +static MscCSW_t csw; +static MsdState_t msdState; +static MSD_Callback_t msdCallback = NULL; + +void msdRcvCallback(void *pArg, uint8_t status, uint16_t transferred, uint16_t remaining); + +/****************************************************************************** + Implementations section +******************************************************************************/ +/**************************************************************************//** +\brief Transmitting callback of usb. +\param[in] + pArg - pointer to some data; + status - result of the USB transfer.; + transferred - how much data are transferred; + remaining - how much data are not transferred. +******************************************************************************/ +void msdTmtCallback(void *pArg, uint8_t status, uint16_t transferred, uint16_t remaining) +{ + (void)pArg; + (void)status; + (void)remaining; + (void)transferred; + + if (MSD_DATA_INOUT == msdState) + { + rwControl.buffersToTransfer--; + rwControl.blockAddress += msdDescr.dataTransferDescriptor->length / STANDARD_BLOCK_LENGTH; + if (0 == rwControl.buffersToTransfer) + { + csw.bCSWStatus = CSW_COMMAND_SUCCESS_STATUS; + msdState = MSD_STATUS_TRANSPORT; + memcpy(msdDescr.dataTransferDescriptor->buffer, (uint8_t*)&csw, CSW_SIZE); + HAL_UsbWrite(MSD_TRANSMIT_PIPE, msdDescr.dataTransferDescriptor->buffer, CSW_SIZE, msdTmtCallback, NULL); + return; + } + else + if (memorySuccessStatus != absMemRead(&msdDescr, rwControl.blockAddress, msdBufferReadCallback)) + msdCallback(MSD_READ_ERROR); + + } + if (MSD_SCSI_ANSWER == msdState) + { + csw.bCSWStatus = CSW_COMMAND_SUCCESS_STATUS; + msdState = MSD_STATUS_TRANSPORT; + memcpy(msdDescr.dataTransferDescriptor->buffer, (uint8_t*)&csw, CSW_SIZE); + HAL_UsbWrite(MSD_TRANSMIT_PIPE, msdDescr.dataTransferDescriptor->buffer, CSW_SIZE, msdTmtCallback, NULL); + return; + } + if (MSD_STATUS_TRANSPORT == msdState) + { + if (msdCallback) + msdCallback(MSD_STATUS_SUCCESS); + msdState = MSD_COMMAND_TRANSPORT; + HAL_UsbRead(MSD_RECEIVE_PIPE, msdDescr.dataTransferDescriptor->buffer, CBW_SIZE, msdRcvCallback, NULL); + return; + } +} + +/**************************************************************************//** +\brief Receiving callback of usb. +\param[in] + pArg - pointer to some data; + status - result of the USB transfer.; + transferred - how much data are transferred; + remaining - how much data are not transferred. +******************************************************************************/ +void msdRcvCallback(void *pArg, uint8_t status, uint16_t transferred, uint16_t remaining) +{ + bool validAndMeaningful = true; + MscCBW_t *cbw = (MscCBW_t *)(msdDescr.dataTransferDescriptor->buffer); + uint8_t length; + + (void)pArg; + (void)status; + (void)remaining; + + if (MSD_COMMAND_TRANSPORT == msdState) + { + /* check that CBW is valid */ + if ((CBW_SIZE != transferred) || (CBW_SIGNATURE != cbw->dCBWSignature)) + validAndMeaningful = false; + if (!validAndMeaningful) + { + HAL_Stall(ADDRESS_MSC_BULKIN_PIPE & 0x03); + return; + } + /* check that CBW is meaningful */ + if ((cbw->bCBWLUN > 0x0F) || (cbw->bCBWCBLength == 0) || (cbw->bCBWCBLength > 0x10) || (cbw->bmCBWFlags & 0x7F)) + validAndMeaningful = false; + if (!validAndMeaningful) + return; + /* fill csw with parameters from cbw */ + csw.cDSWTag = cbw->cDBWTag; + csw.dCSWSignature = CBW_SIGNATURE; + /* check that command is valid */ + if (!scsiIsValidCommand(cbw->CBWCB)) + { + csw.bCSWStatus = CSW_COMMAND_FAILED_STATUS; + msdState = MSD_STATUS_TRANSPORT; + memcpy(msdDescr.dataTransferDescriptor->buffer, (uint8_t*)&csw, CSW_SIZE); + HAL_UsbWrite(MSD_TRANSMIT_PIPE, msdDescr.dataTransferDescriptor->buffer, CSW_SIZE, msdTmtCallback, NULL); + return; + } + /* check that no data in-out phase is needed */ + if (!scsiIsDataInOutPhaseNeeded(cbw->CBWCB)) + { + csw.bCSWStatus = CSW_COMMAND_SUCCESS_STATUS; + msdState = MSD_STATUS_TRANSPORT; + memcpy(msdDescr.dataTransferDescriptor->buffer, (uint8_t*)&csw, CSW_SIZE); + HAL_UsbWrite(MSD_TRANSMIT_PIPE, msdDescr.dataTransferDescriptor->buffer, CSW_SIZE, msdTmtCallback, NULL); + return; + } + /* check that command is no read-write command */ + if (!scsiIsReadWriteCommand(cbw->CBWCB)) + { + csw.bCSWStatus = CSW_COMMAND_SUCCESS_STATUS; + msdState = MSD_SCSI_ANSWER; + length = scsiGetCommandResponse(cbw->CBWCB, msdDescr.dataTransferDescriptor->buffer); + HAL_UsbWrite(MSD_TRANSMIT_PIPE, msdDescr.dataTransferDescriptor->buffer, length, msdTmtCallback, NULL); + return; + } + /* check that command is read command */ + rwControl.buffersToTransfer = scsiBlocksAmount(cbw->CBWCB) * (msdDescr.dataTransferDescriptor->length / STANDARD_BLOCK_LENGTH); + rwControl.blockAddress = scsiGetBlockAddress(cbw->CBWCB); + if (scsiIsReadCommand(cbw->CBWCB)) + { + if (memorySuccessStatus != absMemRead(&msdDescr, rwControl.blockAddress, msdBufferReadCallback)) + msdCallback(MSD_READ_ERROR); + } + else + HAL_UsbRead(MSD_RECEIVE_PIPE, msdDescr.dataTransferDescriptor->buffer, + BULK_SIZE, msdRcvCallback, NULL); + msdState = MSD_DATA_INOUT; + return; + } + if (MSD_DATA_INOUT == msdState) + { + /* increase internal write buffer offset*/ + rwControl.bufferOffset += transferred; + /* if buffer is full perform write to flash */ + if (rwControl.bufferOffset == msdDescr.dataTransferDescriptor->length) + { + if (memorySuccessStatus != absMemWrite(&msdDescr, rwControl.blockAddress, msdBufferWriteCallback)) + msdCallback(MSD_WRITE_ERROR); + /* wait for hsmci bus becomes free */ + rwControl.bufferOffset = 0; + rwControl.buffersToTransfer--; + rwControl.blockAddress += msdDescr.dataTransferDescriptor->length / STANDARD_BLOCK_LENGTH; + return; + } + if (0 != rwControl.buffersToTransfer) + HAL_UsbRead(MSD_RECEIVE_PIPE, msdDescr.dataTransferDescriptor->buffer + rwControl.bufferOffset, + BULK_SIZE, msdRcvCallback, NULL); + + } +} + +/**************************************************************************//** +\brief Opens mass storage device. +\param[in] + callback - pointer to function to notify about MSD errors and transactions; + responseBuffer - pointer to hsmci command response buffer; it should have + a size of four; + buffer - pointer to buffer for hsmci data transfer; it should be + a multiplier of 512; + length - length of buffer for data transfer. +******************************************************************************/ +void MSD_Open(MSD_Callback_t callback, uint32_t *responseBuffer, uint8_t *buffer, uint32_t length) +{ + uint32_t lastBlock; + + msdCallback = callback; + + msdDescr.dataTransferDescriptor = &dataTransferDescr; + msdDescr.commandDescriptor = &commandDescr; + msdDescr.dataTransferDescriptor->buffer = buffer; + msdDescr.dataTransferDescriptor->length = length; + msdDescr.commandDescriptor->responseBuffer = responseBuffer; + msdDescr.dataTransferDescriptor->commandDescr = &commandDescr; + + msdPointDescr = & msdDescr; + + if (-1 == HAL_OpenHsmci(&msdDescr)) + if (msdCallback) + msdCallback(MSD_INTERFACE_BUSY); + + if (memorySuccessStatus != absMemInit(&msdDescr)) + if (msdCallback) + msdCallback(MSD_MEMORY_INIT_ERROR); + + if (memorySuccessStatus != absMemCapacity(&msdDescr, &lastBlock)) + if (msdCallback) + msdCallback(MSD_READ_CAPACITY_ERROR); + + scsiSetCapacity(lastBlock); + + rwControl.bufferOffset = 0; + rwControl.buffersToTransfer = 0; + msdState = MSD_COMMAND_TRANSPORT; + csw.dCSWDataResidue = 0; + + HAL_RegisterEndOfBusResetHandler(usbBusResetAction); + if (DEVICE_POWERED != HAL_GetState()) + HAL_UsbInit((uint8_t *)&request); +} + +/**************************************************************************//** +\brief Closes mass storage device. +******************************************************************************/ +void MSD_Close(void) +{ + if (-1 == HAL_CloseHsmci(&msdDescr)) + if (msdCallback) + msdCallback(MSD_INTERFACE_BUSY); +} + +/**************************************************************************//** +\brief Memory read callback function. +\param[in] + status - status of memory read procedure. +******************************************************************************/ +static void msdBufferReadCallback(MemoryStatus_t status) +{ + if (memorySuccessStatus != status) + msdCallback(MSD_READ_ERROR); + HAL_UsbWrite(MSD_TRANSMIT_PIPE, msdDescr.dataTransferDescriptor->buffer, + msdDescr.dataTransferDescriptor->length, msdTmtCallback, NULL); +} + +/**************************************************************************//** +\brief Memory write callback function. +\param[in] + status - status of memory write procedure. +******************************************************************************/ +static void msdBufferWriteCallback(MemoryStatus_t status) +{ + if (memorySuccessStatus != status) + msdCallback(MSD_WRITE_ERROR); + if (0 == rwControl.buffersToTransfer) + { + csw.bCSWStatus = CSW_COMMAND_SUCCESS_STATUS; + msdState = MSD_STATUS_TRANSPORT; + memcpy(msdDescr.dataTransferDescriptor->buffer, (uint8_t*)&csw, CSW_SIZE); + HAL_UsbWrite(MSD_TRANSMIT_PIPE, msdDescr.dataTransferDescriptor->buffer, CSW_SIZE, msdTmtCallback, NULL); + } + else + HAL_UsbRead(MSD_RECEIVE_PIPE, msdDescr.dataTransferDescriptor->buffer, + BULK_SIZE, msdRcvCallback, NULL); +} + +// eof massStorageDevice.c -- cgit v1.2.3