summaryrefslogtreecommitdiffhomepage
path: root/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD
diff options
context:
space:
mode:
Diffstat (limited to 'digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD')
-rw-r--r--digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/include/abstractMemory.h83
-rw-r--r--digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/include/mem.h106
-rw-r--r--digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/include/mscProtocol.h79
-rw-r--r--digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/include/scsiProtocol.h114
-rw-r--r--digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/abstractMemory.c225
-rw-r--r--digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/massStorageDevice.c327
-rw-r--r--digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/mmc.c618
-rw-r--r--digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/mscProtocol.c53
-rw-r--r--digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/scsiProtocol.c398
9 files changed, 2003 insertions, 0 deletions
diff --git a/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/include/abstractMemory.h b/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/include/abstractMemory.h
new file mode 100644
index 00000000..2eab5f00
--- /dev/null
+++ b/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/include/abstractMemory.h
@@ -0,0 +1,83 @@
+/****************************************************************************//**
+ \file abstactMemory.h
+
+ \brief Declaration of abstract memory commands.
+
+ \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
+*******************************************************************************/
+#ifndef _ABSTRACT_MEMORY_H
+#define _ABSTRACT_MEMORY_H
+
+/******************************************************************************
+ Includes section
+******************************************************************************/
+#include <types.h>
+#include <hsmci.h>
+
+/******************************************************************************
+ Types section
+******************************************************************************/
+typedef enum
+{
+ memorySuccessStatus,
+ memoryErrorStatus
+} MemoryStatus_t;
+
+/******************************************************************************
+ Prototypes section
+******************************************************************************/
+/**************************************************************************//**
+\brief Writes data to memory at "address".
+\param[in]
+ descriptor - pointer to hsmci descriptor;
+ address - address of blocks to write.
+ callback - pointer to function to nofity upper layer about end of write
+ procedure.
+\return
+ status of write procedure.
+******************************************************************************/
+MemoryStatus_t absMemWrite(HAL_HsmciDescriptor_t *descriptor, uint32_t address, void (*callback)(MemoryStatus_t));
+
+/**************************************************************************//**
+\brief Reads data from memory at "address".
+\param[in]
+ descriptor - pointer to hsmci descriptor;
+ address - address of blocks to read.
+ callback - pointer to function to nofity upper layer about end of read
+ procedure.
+\return
+ status of read procedure.
+******************************************************************************/
+MemoryStatus_t absMemRead(HAL_HsmciDescriptor_t *descriptor, uint32_t address, void (*callback)(MemoryStatus_t));
+
+/**************************************************************************//**
+\brief Performs memory initialization.
+\param[in]
+ descriptor - pointer to hsmci descriptor.
+\return
+ status of initialization procedure.
+******************************************************************************/
+MemoryStatus_t absMemInit(HAL_HsmciDescriptor_t *descriptor);
+
+/**************************************************************************//**
+\brief Reads memory capacity.
+\param[in]
+ descriptor - pointer to hsmci descriptor.
+\param[out]
+ lastBlockNumber - number of last accessible block of memory.
+\return
+ status of read capacity procedure.
+******************************************************************************/
+MemoryStatus_t absMemCapacity(HAL_HsmciDescriptor_t *descriptor, uint32_t *lastBlockNumber);
+
+#endif /* _ABSTRACT_MEMORY_H */
+// eof abstactMemory.h
diff --git a/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/include/mem.h b/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/include/mem.h
new file mode 100644
index 00000000..0197f13a
--- /dev/null
+++ b/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/include/mem.h
@@ -0,0 +1,106 @@
+/****************************************************************************//**
+ \file mem.h
+
+ \brief Declaration of memory commands.
+
+ \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
+*******************************************************************************/
+#ifndef _MEM_H
+#define _MEM_H
+
+/******************************************************************************
+ Includes section
+******************************************************************************/
+#include <types.h>
+#include <hsmci.h>
+
+/******************************************************************************
+ Define(s) section
+******************************************************************************/
+// block length
+#define STANDARD_BLOCK_LENGTH 512
+
+/******************************************************************************
+ Types section
+******************************************************************************/
+typedef enum
+{
+ memSuccess,
+ hsmciError,
+ voltageError,
+ commandError,
+ initTimeoutError,
+ stateError,
+ hsmciReadError,
+ hsmciWriteError,
+ setMaxFreqError
+} MemStatus_t;
+
+typedef struct
+{
+ uint32_t lastLogicalBlock;
+ uint32_t logicalBlockLength;
+} MemCapacityInfo_t;
+
+/******************************************************************************
+ Prototypes section
+******************************************************************************/
+/**************************************************************************//**
+\brief Writes one data block to memory at "address".
+\param[in]
+ descriptor - pointer to hsmci descriptor;
+ address - address of block to write.
+\return
+ status of write procedure.
+******************************************************************************/
+MemStatus_t memWriteBlock(HAL_HsmciDescriptor_t *descriptor, uint32_t address, void (*callback)(MemStatus_t));
+
+/**************************************************************************//**
+\brief Reads one data block from memory at "address".
+\param[in]
+ descriptor - pointer to hsmci descriptor;
+ address - address of block to read.
+\return
+ status of read procedure.
+******************************************************************************/
+MemStatus_t memReadBlock(HAL_HsmciDescriptor_t *descriptor, uint32_t address, void (*callback)(MemStatus_t));
+
+/**************************************************************************//**
+\brief Performs memory initialization.
+\param[in]
+ commandDescr - pointer to hsmci command descriptor.
+\return
+ status of initialization procedure.
+******************************************************************************/
+MemStatus_t memInit(HAL_HsmciDescriptor_t *commandDescr);
+
+/**************************************************************************//**
+\brief Reads memory capacity.
+\param[in]
+ descriptor - pointer to hsmci descriptor.
+\param[out]
+ capInfo - pointer to memory capacity structure.
+\return
+ status of read capacity procedure.
+******************************************************************************/
+MemStatus_t memGetCapacityInfo(HAL_HsmciDescriptor_t *descriptor, MemCapacityInfo_t *capInfo);
+
+/**************************************************************************//**
+\brief Checks if memory is ready for any data transfer.
+\return
+ false - memory is busy;
+ true - memory is ready.
+******************************************************************************/
+bool memIsBusy(void);
+
+#endif /* _MEM_H */
+// eof mem.h
diff --git a/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/include/mscProtocol.h b/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/include/mscProtocol.h
new file mode 100644
index 00000000..aa5964ad
--- /dev/null
+++ b/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/include/mscProtocol.h
@@ -0,0 +1,79 @@
+/****************************************************************************//**
+ \file mscProtocol.h
+
+ \brief Declaration of mass storage device protocol command.
+
+ \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
+*******************************************************************************/
+#ifndef _MSCPROTOCOL_H
+#define _MSCPROTOCOL_H
+
+/******************************************************************************
+ Includes section
+******************************************************************************/
+#include <types.h>
+#include <usbSetupProcess.h>
+
+/******************************************************************************
+ Define(s) section
+******************************************************************************/
+// data size in request structure
+#define MSC_REQUEST_DATA_SIZE 1
+
+// request codes for mass storage class
+#define BULK_ONLY_MASS_STORAGE_RESET 0xFF
+#define GET_MAX_LUN 0xFE
+// maximum size of CBW data
+#define CBW_DATA_SIZE 16
+
+/******************************************************************************
+ Types section
+******************************************************************************/
+BEGIN_PACK
+typedef struct PACK
+{
+ UsbRequest_t request;
+ uint8_t bData[MSC_REQUEST_DATA_SIZE];
+} UsbMscRequest_t;
+// MSC command block wrapper (CBW)
+typedef struct PACK
+{
+ uint32_t dCBWSignature;
+ uint32_t cDBWTag;
+ uint32_t dCBWDataTransferLength;
+ uint8_t bmCBWFlags;
+ uint8_t bCBWLUN;
+ uint8_t bCBWCBLength;
+ uint8_t CBWCB[CBW_DATA_SIZE];
+} MscCBW_t;
+// MSC command status wrapper (CSW)
+typedef struct PACK
+{
+ uint32_t dCSWSignature;
+ uint32_t cDSWTag;
+ uint32_t dCSWDataResidue;
+ uint8_t bCSWStatus;
+} MscCSW_t;
+END_PACK
+
+/******************************************************************************
+ Prototypes section
+******************************************************************************/
+/**************************************************************************//**
+\brief Mass storage device request handler.
+\param[in]
+ data - pointer to host's request.
+******************************************************************************/
+void msdRequestHandler(uint8_t *data);
+
+#endif /* _MSCPROTOCOL_H */
+// eof msdProtocol.h \ No newline at end of file
diff --git a/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/include/scsiProtocol.h b/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/include/scsiProtocol.h
new file mode 100644
index 00000000..6a10b4dc
--- /dev/null
+++ b/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/include/scsiProtocol.h
@@ -0,0 +1,114 @@
+/****************************************************************************//**
+ \file scsiProtocol.h
+
+ \brief Declaration of scsi protocol commands.
+
+ \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
+*******************************************************************************/
+#ifndef _SCSIPROTOCOL_H
+#define _SCSIPROTOCOL_H
+
+/******************************************************************************
+ Includes section
+******************************************************************************/
+#include <types.h>
+
+/******************************************************************************
+ Define(s) section
+******************************************************************************/
+// Maximum response length for scsi command
+#define MAX_COMMAND_RESPONSE_LENGTH 36
+
+/******************************************************************************
+ Prototypes section
+******************************************************************************/
+/**************************************************************************//**
+\brief Checks if received scsi command is supported.
+\param[in]
+ data - pointer to received command with parameters.
+\return
+ false - command is not supported;
+ true - command is supported.
+******************************************************************************/
+bool scsiIsValidCommand(uint8_t *data);
+
+/**************************************************************************//**
+\brief Checks if any response or data transfer needed for received
+ scsi command.
+\param[in]
+ command - received command.
+\return
+ false - response is not needed;
+ true - response is needed.
+******************************************************************************/
+bool scsiIsDataInOutPhaseNeeded(uint8_t *data);
+
+/**************************************************************************//**
+\brief Checks if command is read or write command.
+\param[in]
+ command - received command.
+\return
+ false - command is not read/write command;
+ true - command is read/write command.
+******************************************************************************/
+bool scsiIsReadWriteCommand(uint8_t *data);
+
+/**************************************************************************//**
+\brief Checks if command is read command.
+\param[in]
+ command - received command.
+\return
+ false - command is not read command;
+ true - command is read command.
+******************************************************************************/
+bool scsiIsReadCommand(uint8_t *data);
+
+/**************************************************************************//**
+\brief Blocks for read/write command.
+\param[in]
+ data - pointer to received command with parameters.
+\return
+ number of blocks to read or write from memory.
+******************************************************************************/
+uint16_t scsiBlocksAmount(uint8_t *data);
+
+/**************************************************************************//**
+\brief Response for scsi command.
+\param[in]
+ command - received command.
+\param[out]
+ buffer - buffer with scsi command response.
+\return
+ length of response
+******************************************************************************/
+uint8_t scsiGetCommandResponse(uint8_t *data, uint8_t *buffer);
+
+/**************************************************************************//**
+\brief Sets number of last available memory block for scsi response.
+\param[in]
+ lastBlock - received command.
+\param[out]
+ buffer - number of last available memory block
+******************************************************************************/
+void scsiSetCapacity(uint32_t lastBlock);
+
+/**************************************************************************//**
+\brief Block address for read/write command.
+\param[in]
+ data - pointer to received command with parameters.
+\return
+ block address for read or write from memory.
+******************************************************************************/
+uint32_t scsiGetBlockAddress(uint8_t *data);
+
+#endif /* _SCSIPROTOCOL_H */
+// eof scsiProtocol.h
diff --git a/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/abstractMemory.c b/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/abstractMemory.c
new file mode 100644
index 00000000..dc11be63
--- /dev/null
+++ b/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/abstractMemory.c
@@ -0,0 +1,225 @@
+/****************************************************************************//**
+ \files abstractMemory.c
+
+ \brief Implementation of amstract memory commands.
+
+ \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:
+ 30/08/11 N. Fomin - Created
+*******************************************************************************/
+/******************************************************************************
+ Includes section
+******************************************************************************/
+#include <mem.h>
+#include <abstractMemory.h>
+
+/******************************************************************************
+ Define(s) section
+******************************************************************************/
+#define RETRY_COUNT 5
+
+/******************************************************************************
+ External global variables section
+******************************************************************************/
+/******************************************************************************
+ Types section
+******************************************************************************/
+typedef struct
+{
+ uint16_t transferLength;
+ uint16_t blocksToTransfer;
+ uint32_t logicalBlockAddress;
+ HAL_HsmciDescriptor_t *hsmciDescriptor;
+ uint8_t *dataBuffer;
+} AbsMemInternal_t;
+
+/******************************************************************************
+ Global variables section
+******************************************************************************/
+static void (*absMemCallback)(MemoryStatus_t status);
+static AbsMemInternal_t apsMemInternal;
+
+/******************************************************************************
+ Implementations section
+******************************************************************************/
+/**************************************************************************//**
+\brief Current memory read callback.
+\param[in]
+ status - status of read operation.
+******************************************************************************/
+void absMemReadBlockCallback(MemStatus_t status)
+{
+ uint8_t i = RETRY_COUNT;
+ apsMemInternal.blocksToTransfer--;
+ uint16_t blocksRemaining = apsMemInternal.transferLength - apsMemInternal.blocksToTransfer;
+ HAL_HsmciDescriptor_t *descriptor = apsMemInternal.hsmciDescriptor;
+
+ if (memSuccess != status)
+ absMemCallback(memoryErrorStatus);
+ if (0 == apsMemInternal.blocksToTransfer)
+ {
+ descriptor->dataTransferDescriptor->buffer = apsMemInternal.dataBuffer;
+ absMemCallback(memorySuccessStatus);
+ return;
+ }
+
+ descriptor->dataTransferDescriptor->buffer += blocksRemaining * STANDARD_BLOCK_LENGTH;
+
+ while(i--)
+ {
+ if (memSuccess == memReadBlock(descriptor, apsMemInternal.logicalBlockAddress + blocksRemaining, absMemReadBlockCallback))
+ break;
+ }
+ if (0 == i)
+ absMemCallback(memoryErrorStatus);
+}
+
+/**************************************************************************//**
+\brief Current memory write callback.
+\param[in]
+ status - status of write operation.
+******************************************************************************/
+void absMemWriteBlockCallback(MemStatus_t status)
+{
+ uint8_t i = RETRY_COUNT;
+ apsMemInternal.blocksToTransfer--;
+ uint16_t blocksRemaining = apsMemInternal.transferLength - apsMemInternal.blocksToTransfer;
+ HAL_HsmciDescriptor_t *descriptor = apsMemInternal.hsmciDescriptor;
+
+ if (memSuccess != status)
+ absMemCallback(memoryErrorStatus);
+ if (0 == apsMemInternal.blocksToTransfer)
+ {
+ descriptor->dataTransferDescriptor->buffer = apsMemInternal.dataBuffer;
+ absMemCallback(memorySuccessStatus);
+ return;
+ }
+
+ descriptor->dataTransferDescriptor->buffer += blocksRemaining * STANDARD_BLOCK_LENGTH;
+
+ while(i--)
+ {
+ if (memSuccess == memWriteBlock(descriptor, apsMemInternal.logicalBlockAddress + blocksRemaining, absMemWriteBlockCallback))
+ break;
+ }
+ if (0 == i)
+ absMemCallback(memoryErrorStatus);
+}
+
+/**************************************************************************//**
+\brief Performs memory initialization.
+\param[in]
+ descriptor - pointer to hsmci descriptor.
+\return
+ status of initialization procedure.
+******************************************************************************/
+MemoryStatus_t absMemInit(HAL_HsmciDescriptor_t *descriptor)
+{
+ if (memSuccess != memInit(descriptor))
+ return memoryErrorStatus;
+
+ return memorySuccessStatus;
+}
+
+/**************************************************************************//**
+\brief Reads memory capacity.
+\param[in]
+ descriptor - pointer to hsmci descriptor.
+\param[out]
+ lastBlockNumber - number of last accessible block of memory.
+\return
+ status of read capacity procedure.
+******************************************************************************/
+MemoryStatus_t absMemCapacity(HAL_HsmciDescriptor_t *descriptor, uint32_t *lastBlockNumber)
+{
+ MemCapacityInfo_t capInfo;
+ uint8_t i = RETRY_COUNT;
+ MemStatus_t status;
+
+ while(i--)
+ {
+ status = memGetCapacityInfo(descriptor, &capInfo);
+ if (memSuccess == status)
+ {
+ *lastBlockNumber = capInfo.lastLogicalBlock;
+ return memorySuccessStatus;
+ }
+ }
+
+ return memoryErrorStatus;
+}
+
+/**************************************************************************//**
+\brief Writes data to memory at "address".
+\param[in]
+ descriptor - pointer to hsmci descriptor;
+ address - address of blocks to write.
+ callback - pointer to function to nofity upper layer about end of write
+ procedure.
+\return
+ status of write procedure.
+******************************************************************************/
+MemoryStatus_t absMemWrite(HAL_HsmciDescriptor_t *descriptor, uint32_t address, void (*callback)(MemoryStatus_t))
+{
+ HAL_HsmciDataTransferDescriptor_t *dataDescr = descriptor->dataTransferDescriptor;
+ uint8_t i;
+ absMemCallback = callback;
+
+ apsMemInternal.logicalBlockAddress = address;
+ apsMemInternal.transferLength = dataDescr->length / STANDARD_BLOCK_LENGTH;
+ apsMemInternal.blocksToTransfer = apsMemInternal.transferLength;
+ apsMemInternal.dataBuffer = descriptor->dataTransferDescriptor->buffer;
+
+ dataDescr->length = STANDARD_BLOCK_LENGTH;
+
+ i = RETRY_COUNT;
+ while(i--)
+ {
+ if (memSuccess == memWriteBlock(descriptor, address, absMemWriteBlockCallback))
+ return memorySuccessStatus;
+ }
+
+ return memoryErrorStatus;
+}
+
+/**************************************************************************//**
+\brief Reads data from memory at "address".
+\param[in]
+ descriptor - pointer to hsmci descriptor;
+ address - address of blocks to read.
+ callback - pointer to function to nofity upper layer about end of read
+ procedure.
+\return
+ status of read procedure.
+******************************************************************************/
+MemoryStatus_t absMemRead(HAL_HsmciDescriptor_t *descriptor, uint32_t address, void (*callback)(MemoryStatus_t))
+{
+ HAL_HsmciDataTransferDescriptor_t *dataDescr = descriptor->dataTransferDescriptor;
+ uint8_t i;
+ absMemCallback = callback;
+
+ apsMemInternal.logicalBlockAddress = address;
+ apsMemInternal.transferLength = dataDescr->length / STANDARD_BLOCK_LENGTH;
+ apsMemInternal.blocksToTransfer = apsMemInternal.transferLength;
+ apsMemInternal.dataBuffer = descriptor->dataTransferDescriptor->buffer;
+
+ dataDescr->length = STANDARD_BLOCK_LENGTH;
+
+ i = RETRY_COUNT;
+ while(i--)
+ {
+ if (memSuccess == memReadBlock(descriptor, address, absMemReadBlockCallback))
+ return memorySuccessStatus;
+ }
+
+ return memoryErrorStatus;
+}
+
+//eof abstractMemory.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 <mscProtocol.h>
+#include <usbEnumeration.h>
+#include <massStorageDevice.h>
+#include <scsiProtocol.h>
+#include <abstractMemory.h>
+#include <usbDescriptors.h>
+#include <mem.h>
+
+/******************************************************************************
+ 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
diff --git a/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/mmc.c b/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/mmc.c
new file mode 100644
index 00000000..b512bd04
--- /dev/null
+++ b/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/mmc.c
@@ -0,0 +1,618 @@
+/****************************************************************************//**
+ \files mmc.c
+
+ \brief Implementation of mmc protocol.
+
+ \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:
+ 30/08/11 N. Fomin - Created
+*******************************************************************************/
+/******************************************************************************
+ Includes section
+******************************************************************************/
+#include <mem.h>
+
+/******************************************************************************
+ Define(s) section
+******************************************************************************/
+// card voltage ranges
+#define OCR_VDD_16_17 (1 << 4)
+#define OCR_VDD_17_18 (1 << 5)
+#define OCR_VDD_18_19 (1 << 6)
+#define OCR_VDD_19_20 (1 << 7)
+#define OCR_VDD_20_21 (1 << 8)
+#define OCR_VDD_21_22 (1 << 9)
+#define OCR_VDD_22_23 (1 << 10)
+#define OCR_VDD_23_24 (1 << 11)
+#define OCR_VDD_24_25 (1 << 12)
+#define OCR_VDD_25_26 (1 << 13)
+#define OCR_VDD_26_27 (1 << 14)
+#define OCR_VDD_27_28 (1 << 15)
+#define OCR_VDD_28_29 (1 << 16)
+#define OCR_VDD_29_30 (1 << 17)
+#define OCR_VDD_30_31 (1 << 18)
+#define OCR_VDD_31_32 (1 << 19)
+#define OCR_VDD_32_33 (1 << 20)
+#define OCR_VDD_33_34 (1 << 21)
+#define OCR_VDD_34_35 (1 << 22)
+#define OCR_VDD_35_36 (1 << 23)
+// R1 response statuses
+#define STATUS_APP_CMD (1UL << 5)
+#define STATUS_SWITCH_ERROR (1UL << 7)
+#define STATUS_READY_FOR_DATA (1UL << 8)
+#define STATUS_IDLE (0UL << 9)
+#define STATUS_READY (1UL << 9)
+#define STATUS_IDENT (2UL << 9)
+#define STATUS_STBY (3UL << 9)
+#define STATUS_TRAN (4UL << 9)
+#define STATUS_DATA (5UL << 9)
+#define STATUS_RCV (6UL << 9)
+#define STATUS_PRG (7UL << 9)
+#define STATUS_DIS (8UL << 9)
+#define STATUS_STATE (0xFUL << 9)
+#define STATUS_ERASE_RESET (1UL << 13)
+#define STATUS_WP_ERASE_SKIP (1UL << 15)
+#define STATUS_CIDCSD_OVERWRITE (1UL << 16)
+#define STATUS_OVERRUN (1UL << 17)
+#define STATUS_UNERRUN (1UL << 18)
+#define STATUS_ERROR (1UL << 19)
+#define STATUS_CC_ERROR (1UL << 20)
+#define STATUS_CARD_ECC_FAILED (1UL << 21)
+#define STATUS_ILLEGAL_COMMAND (1UL << 22)
+#define STATUS_COM_CRC_ERROR (1UL << 23)
+#define STATUS_UN_LOCK_FAILED (1UL << 24)
+#define STATUS_CARD_IS_LOCKED (1UL << 25)
+#define STATUS_WP_VIOLATION (1UL << 26)
+#define STATUS_ERASE_PARAM (1UL << 27)
+#define STATUS_ERASE_SEQ_ERROR (1UL << 28)
+#define STATUS_BLOCK_LEN_ERROR (1UL << 29)
+#define STATUS_ADDRESS_MISALIGN (1UL << 30)
+#define STATUS_ADDR_OUT_OR_RANGE (1UL << 31)
+// R1 response sets
+#define ERROR_STATUS (STATUS_ADDR_OUT_OR_RANGE | STATUS_ADDRESS_MISALIGN | STATUS_BLOCK_LEN_ERROR | STATUS_ERASE_SEQ_ERROR | \
+ STATUS_ERASE_PARAM | STATUS_WP_VIOLATION | STATUS_CARD_IS_LOCKED | STATUS_UN_LOCK_FAILED | \
+ STATUS_COM_CRC_ERROR | STATUS_ILLEGAL_COMMAND | STATUS_CARD_ECC_FAILED | STATUS_CC_ERROR | STATUS_ERROR | \
+ STATUS_UNERRUN | STATUS_OVERRUN | STATUS_CIDCSD_OVERWRITE | STATUS_SWITCH_ERROR)
+// command arguments
+#define CMD0_IDLE_STATE_ARGUMENT 0
+#define CMD1_ACCESS_MODE_SECTOR (1UL << 30)
+#define CMD1_HOST_VOLTAGE_RANGE (OCR_VDD_27_28 | OCR_VDD_28_29 | OCR_VDD_29_30 | OCR_VDD_30_31 | \
+ OCR_VDD_31_32 | OCR_VDD_32_33 | OCR_VDD_33_34 | OCR_VDD_34_35 | \
+ OCR_VDD_35_36)
+#define CMD2_ARGUMENT 0
+#define CMD6_SET_4_LINE_BUS 0x03B70100
+#define CMD6_SET_HS_MODE 0x03B90100
+// relative card address
+#define REVALITE_CARD_ADDRESS (1 << 16)
+// command responses length
+#define NO_RESPONSE_LENGTH 0
+#define R1_RESPONSE_LENGTH 1
+#define R2_RESPONSE_LENGTH 4
+#define R3_RESPONSE_LENGTH 1
+// retry amount of card initialization
+#define RETRY_AMOUNT 10000
+// memory frequency masks for CDS memory register
+#define FREQ_UNITS_MASK 0x07
+#define FREQ_MULTIPLIER_MASK 0x78
+#define FREQ_MULTIPLIER_OFFSET 0x03
+// csd register definitions
+#define CSD_SPEC_VERS_FOUR 4
+
+/******************************************************************************
+ External global variables section
+******************************************************************************/
+/******************************************************************************
+ Types section
+******************************************************************************/
+typedef union
+{
+ uint32_t reg;
+ struct
+ {
+ uint32_t reserved1 : 5;
+ uint32_t appCmd : 1;
+ uint32_t urgentBkops : 1;
+ uint32_t switchError : 1;
+ uint32_t readyForData : 1;
+ uint32_t currentState : 4;
+ uint32_t eraseReset : 1;
+ uint32_t reserved2 : 1;
+ uint32_t wpEraseSkip : 1;
+ uint32_t cidCsdOverwrite : 1;
+ uint32_t overrun : 1;
+ uint32_t underrun : 1;
+ uint32_t error : 1;
+ uint32_t ccEror : 1;
+ uint32_t cardEccFailed : 1;
+ uint32_t illegalCommand : 1;
+ uint32_t comCrcError : 1;
+ uint32_t lockUnlockFailed : 1;
+ uint32_t cardIsLocked : 1;
+ uint32_t wpViolation : 1;
+ uint32_t eraseParam : 1;
+ uint32_t eraseSeqError : 1;
+ uint32_t blockLenError : 1;
+ uint32_t addressMisalign : 1;
+ uint32_t addressOutOfRange: 1;
+ };
+} MmcCardStatus_t;
+
+typedef union
+{
+ uint32_t reg;
+ struct
+ {
+ uint32_t reserverd1 : 7;
+ uint32_t voltage170_195: 1;
+ uint32_t voltage20_26 : 7;
+ uint32_t voltage27_36 : 9;
+ uint32_t reserved2 : 5;
+ uint32_t accessMode : 2;
+ uint32_t busy : 1;
+ };
+} MmcOcrRegister_t;
+
+typedef struct
+{
+ uint8_t tranSpeed;
+ uint8_t nsac;
+ uint8_t taac;
+ uint8_t reserved3 : 2;
+ uint8_t specVersion : 4;
+ uint8_t csdStructure : 2;
+ uint32_t cSizeDown : 10;
+ uint32_t reserved2 : 2;
+ uint32_t dsrImp : 1;
+ uint32_t readBlkMisalign : 1;
+ uint32_t writeBlkMisalign: 1;
+ uint32_t readBlPartial : 1;
+ uint32_t readBlLen : 4;
+ uint32_t ccc : 12;
+ uint32_t wpGroupSize : 5;
+ uint32_t eraseGroupMult : 5;
+ uint32_t eraseGroupSize : 5;
+ uint32_t cSizeMult : 3;
+ uint32_t vddWCurrMax : 3;
+ uint32_t vddWCurrMin : 3;
+ uint32_t vddRCurrMax : 3;
+ uint32_t vddRCurrMin : 3;
+ uint32_t cSizeUp : 2;
+ uint8_t notUsed : 1;
+ uint8_t crc : 7;
+ uint8_t ecc : 2;
+ uint8_t fileFormat : 2;
+ uint8_t tmpWriteProtect : 1;
+ uint8_t permWriteProtect : 1;
+ uint8_t copy : 1;
+ uint8_t fileFormatGroup : 1;
+ uint16_t contentPropApp : 1;
+ uint16_t reserved1 : 4;
+ uint16_t writeBlPartial : 1;
+ uint16_t writeBlLen : 4;
+ uint16_t r2wFactor : 3;
+ uint16_t defaultEcc : 2;
+ uint16_t wpGroupEnable : 1;
+} MmcCSDRegister_t;
+
+/******************************************************************************
+ Constants section
+******************************************************************************/
+static const uint32_t mmcFrequencyUnits[8] = {100, 1000, 10000, 100000, 0, 0, 0, 0};
+static const uint32_t mmcFrequencyMulptiplier[16] = {0, 10, 12, 13, 15, 20, 26, 30, 35, 40, 45, 52, 55, 60, 70, 80};
+
+/******************************************************************************
+ Prototypes section
+******************************************************************************/
+static bool memSendCommand(HAL_HsmciDescriptor_t *descriptor, uint32_t command, uint32_t argument, uint8_t respLength);
+static bool memCheckState(HAL_HsmciDescriptor_t *descriptor, uint16_t state);
+static bool setMaximumCommunicationFrequency(HAL_HsmciDescriptor_t *descriptor, uint8_t freqCode, bool hsMode);
+static MemStatus_t setBusWidthAndHsMode(HAL_HsmciDescriptor_t *descriptor, MmcCSDRegister_t *csdReg);
+static void (*absMemoryCallback)(MemStatus_t) = NULL;
+static HAL_HsmciDescriptor_t *memDescriptor = NULL;
+
+/******************************************************************************
+ Implementations section
+******************************************************************************/
+/**************************************************************************//**
+\brief HSMCI write callback.
+******************************************************************************/
+void memWriteCallback(void)
+{
+ MmcCardStatus_t *cardStatus;
+
+ cardStatus = (MmcCardStatus_t *)(memDescriptor->commandDescriptor->responseBuffer);
+ if (0 != (cardStatus->reg & ERROR_STATUS))
+ absMemoryCallback(hsmciWriteError);
+ absMemoryCallback(memSuccess);
+}
+
+/**************************************************************************//**
+\brief HSMCI read callback.
+******************************************************************************/
+void memReadCallback(void)
+{
+ MmcCardStatus_t *cardStatus;
+
+ cardStatus = (MmcCardStatus_t *)(memDescriptor->commandDescriptor->responseBuffer);
+ if (0 != (cardStatus->reg & ERROR_STATUS))
+ absMemoryCallback(hsmciReadError);
+ absMemoryCallback(memSuccess);
+}
+/**************************************************************************//**
+\brief Performs MMC memory initialization.
+\param[in]
+ commandDescr - pointer to hsmci command descriptor.
+\return
+ status of initialization procedure.
+******************************************************************************/
+MemStatus_t memInit(HAL_HsmciDescriptor_t *descriptor)
+{
+ uint16_t i = RETRY_AMOUNT;
+ MmcCardStatus_t *cardStatus;
+ MmcOcrRegister_t *ocrRegister;
+ MmcCSDRegister_t *csdReg;
+ HAL_HsmciCommandDescriptor_t *commandDescr = descriptor->commandDescriptor;
+ uint32_t sendOpCondResponse;
+ MemStatus_t status;
+
+ /* send first command - CMD0 with power init parameters */
+ if (!memSendCommand(descriptor, POWER_ON_INIT, CMD0_IDLE_STATE_ARGUMENT, NO_RESPONSE_LENGTH))
+ return hsmciError;
+ /* wait for hsmci bus becomes free */
+ while (!HAL_HsmciCheckReady());
+ /* send CMD0 command to go to idle mode */
+ if (!memSendCommand(descriptor, GO_IDLE_STATE, CMD0_IDLE_STATE_ARGUMENT, NO_RESPONSE_LENGTH))
+ return hsmciError;
+ /* wait for hsmci bus becomes free */
+ while (!HAL_HsmciCheckReady());
+ /* wait for internal initialization process */
+ for (; i > 0; i--)
+ {
+ /* send CMD1 command to check host and device voltage correlation */
+ if (!memSendCommand(descriptor, SEND_OP_COND, CMD1_HOST_VOLTAGE_RANGE | CMD1_ACCESS_MODE_SECTOR, R3_RESPONSE_LENGTH))
+ return hsmciError;
+ /* wait for hsmci bus becomes free */
+ while (!HAL_HsmciCheckReady());
+ ocrRegister = (MmcOcrRegister_t *)(commandDescr->responseBuffer);
+ if (!(ocrRegister->reg & CMD1_HOST_VOLTAGE_RANGE))
+ return voltageError;
+ if (0 == ocrRegister->busy)
+ continue;
+ break;
+ }
+ if (0 == i)
+ return initTimeoutError;
+ sendOpCondResponse = commandDescr->responseBuffer[0];
+ i = RETRY_AMOUNT;
+ while (i--)
+ {
+ /* send CMD2 command to get card CID number */
+ if (!memSendCommand(descriptor, ALL_SEND_CID, CMD2_ARGUMENT, R2_RESPONSE_LENGTH))
+ return hsmciError;
+ /* wait for hsmci bus becomes free */
+ while (!HAL_HsmciCheckReady());
+ if (sendOpCondResponse != commandDescr->responseBuffer[0])
+ break;
+ }
+ if (0 == i)
+ return stateError;
+ /* send CMD3 command to set card relative address */
+ if (!memSendCommand(descriptor, SEND_RELATIVE_ADDR, REVALITE_CARD_ADDRESS, R1_RESPONSE_LENGTH))
+ return hsmciError;
+ /* wait for hsmci bus becomes free */
+ while (!HAL_HsmciCheckReady());
+ cardStatus = (MmcCardStatus_t *)(commandDescr->responseBuffer);
+ if (0 != (cardStatus->reg & ERROR_STATUS))
+ return commandError;
+ if (!memCheckState(descriptor, STATUS_STBY))
+ return stateError;
+ /* send CMD9 command to read CSD register */
+ if (!memSendCommand(descriptor, SEND_CSD, REVALITE_CARD_ADDRESS, R2_RESPONSE_LENGTH))
+ return hsmciError;
+ /* wait for hsmci bus becomes free */
+ while (!HAL_HsmciCheckReady());
+ /* read allowed maximum communication frequency and set it */
+ csdReg = (MmcCSDRegister_t *)(commandDescr->responseBuffer);
+ status = setBusWidthAndHsMode(descriptor, csdReg);
+ if (status != memSuccess)
+ return setMaxFreqError;
+
+ return memSuccess;
+}
+
+/**************************************************************************//**
+\brief Reads MMC memory capacity.
+\param[in]
+ descriptor - pointer to hsmci descriptor.
+\param[out]
+ capInfo - pointer to memory capacity structure.
+\return
+ status of read capacity procedure.
+******************************************************************************/
+MemStatus_t memGetCapacityInfo(HAL_HsmciDescriptor_t *descriptor, MemCapacityInfo_t *capInfo)
+{
+ MmcCardStatus_t *cardStatus;
+ MmcCSDRegister_t *csdReg;
+ HAL_HsmciCommandDescriptor_t *commandDescr = descriptor->commandDescriptor;
+
+ /* send CMD13 command to discover current state */
+ if (!memSendCommand(descriptor, SEND_STATUS, REVALITE_CARD_ADDRESS, R1_RESPONSE_LENGTH))
+ return hsmciError;
+ /* wait for hsmci bus becomes free */
+ while (!HAL_HsmciCheckReady());
+
+ cardStatus = (MmcCardStatus_t *)(commandDescr->responseBuffer);
+ if (STATUS_TRAN == (cardStatus->reg & STATUS_TRAN))
+ {
+ /* send CMD7 command to switch to stand-by state*/
+ if (!memSendCommand(descriptor, SELECT_CARD, ~REVALITE_CARD_ADDRESS, R1_RESPONSE_LENGTH))
+ return hsmciError;
+ /* wait for hsmci bus becomes free */
+ while (!HAL_HsmciCheckReady());
+ cardStatus = (MmcCardStatus_t *)(commandDescr->responseBuffer);
+ if (0 != (cardStatus->reg & ERROR_STATUS))
+ return commandError;
+ if (!memCheckState(descriptor, STATUS_STBY))
+ return stateError;
+ }
+ /* send CMD9 command to read CSD register */
+ if (!memSendCommand(descriptor, SEND_CSD, REVALITE_CARD_ADDRESS, R2_RESPONSE_LENGTH))
+ return hsmciError;
+ /* wait for hsmci bus becomes free */
+ while (!HAL_HsmciCheckReady());
+
+ capInfo->logicalBlockLength = STANDARD_BLOCK_LENGTH;
+ csdReg = (MmcCSDRegister_t *)(commandDescr->responseBuffer);
+ capInfo->lastLogicalBlock = (1 << (csdReg->cSizeMult + 2)) * (csdReg->cSizeUp + 1 + (csdReg->cSizeDown << 2)) * ((1 << csdReg->readBlLen) / STANDARD_BLOCK_LENGTH) - 1;
+
+ if (!memCheckState(descriptor, STATUS_STBY))
+ return stateError;
+
+ /* send CMD7 command to switch to transfer state */
+ if (!memSendCommand(descriptor, SELECT_CARD, REVALITE_CARD_ADDRESS, R1_RESPONSE_LENGTH))
+ return hsmciError;
+ /* wait for hsmci bus becomes free */
+ while (!HAL_HsmciCheckReady());
+ cardStatus = (MmcCardStatus_t *)(commandDescr->responseBuffer);
+ if (0 != (cardStatus->reg & ERROR_STATUS))
+ return commandError;
+ if (!memCheckState(descriptor, STATUS_TRAN))
+ return stateError;
+
+ return memSuccess;
+}
+
+/**************************************************************************//**
+\brief Checks MMC memory state.
+\param[in]
+ descriptor - pointer to hsmci descriptor;
+ state - state in which MMC memory meant to be.
+\return
+ false - check failed;
+ true - check success.
+******************************************************************************/
+static bool memSendCommand(HAL_HsmciDescriptor_t *descriptor, uint32_t command, uint32_t argument, uint8_t respLength)
+{
+ descriptor->commandDescriptor->command = command;
+ descriptor->commandDescriptor->argument = argument;
+ descriptor->commandDescriptor->responseLength = respLength;
+
+ if (-1 == HAL_WriteHsmciCommand(descriptor))
+ return false;
+
+ return true;
+}
+
+/**************************************************************************//**
+\brief Sends MMC command.
+\param[in]
+ descriptor - pointer to hsmci descriptor;
+ command - command index and attributes;
+ argument - command argument;
+ respLength - command response length.
+\return
+ false - command sent failed;
+ true - command sent success.
+******************************************************************************/
+static bool memCheckState(HAL_HsmciDescriptor_t *descriptor, uint16_t state)
+{
+ MmcCardStatus_t *cardStatus;
+ /* send CMD13 command to discover current state */
+ if (!memSendCommand(descriptor, SEND_STATUS, REVALITE_CARD_ADDRESS, R1_RESPONSE_LENGTH))
+ return hsmciError;
+ /* wait for hsmci bus becomes free */
+ while (!HAL_HsmciCheckReady());
+ cardStatus = (MmcCardStatus_t *)(descriptor->commandDescriptor->responseBuffer);
+
+ return (cardStatus->reg & STATUS_STATE) == state;
+}
+
+/**************************************************************************//**
+\brief Writes one data block to MMC memory at "address".
+\param[in]
+ descriptor - pointer to hsmci descriptor;
+ address - address of block to write.
+\return
+ status of write procedure.
+******************************************************************************/
+MemStatus_t memWriteBlock(HAL_HsmciDescriptor_t *descriptor, uint32_t address, void (*callback)(MemStatus_t))
+{
+ HAL_HsmciCommandDescriptor_t *commandDescr = descriptor->commandDescriptor;
+ HAL_HsmciDataTransferDescriptor_t *dataDescr = descriptor->dataTransferDescriptor;
+
+ memDescriptor = descriptor;
+
+ if (!memCheckState(descriptor, STATUS_TRAN))
+ return stateError;
+
+ commandDescr->command = WRITE_BLOCK;
+ commandDescr->argument = address << 9;
+ commandDescr->responseLength = R1_RESPONSE_LENGTH;
+
+ dataDescr->direction = HSMCI_WRITE;
+ dataDescr->blockSize = STANDARD_BLOCK_LENGTH;
+ absMemoryCallback = callback;
+ descriptor->callback = memWriteCallback;
+
+ if (-1 == HAL_WriteHsmci(descriptor))
+ return hsmciWriteError;
+
+ return memSuccess;
+}
+
+/**************************************************************************//**
+\brief Reads one data block from MMC memory at "address".
+\param[in]
+ descriptor - pointer to hsmci descriptor;
+ address - address of block to read.
+\return
+ status of read procedure.
+******************************************************************************/
+MemStatus_t memReadBlock(HAL_HsmciDescriptor_t *descriptor, uint32_t address, void (*callback)(MemStatus_t))
+{
+ HAL_HsmciCommandDescriptor_t *commandDescr = descriptor->commandDescriptor;
+ HAL_HsmciDataTransferDescriptor_t *dataDescr = descriptor->dataTransferDescriptor;
+
+ memDescriptor = descriptor;
+
+ if (!memCheckState(descriptor, STATUS_TRAN))
+ return stateError;
+
+ commandDescr->command = READ_SINGLE_BLOCK;
+ commandDescr->argument = address << 9;
+ commandDescr->responseLength = R1_RESPONSE_LENGTH;
+
+ dataDescr->direction = HSMCI_READ;
+ dataDescr->blockSize = STANDARD_BLOCK_LENGTH;
+ absMemoryCallback = callback;
+ descriptor->callback = memReadCallback;
+
+ if (-1 == HAL_ReadHsmci(descriptor))
+ return hsmciReadError;
+
+ return memSuccess;
+}
+
+/**************************************************************************//**
+\brief Checks if MMC memory is ready for any data transfer.
+\return
+ false - memory is busy;
+ true - memory is ready.
+******************************************************************************/
+bool memIsBusy(void)
+{
+ return HAL_HsmciCheckReady();
+}
+
+/**************************************************************************//**
+\brief Sets maximum bus frequency for MMC memory.
+\param[in]
+ descriptor - pointer to hsmci descriptor;
+ freqCode - frequency code.
+\return
+ false - setting failed;
+ true - setting success.
+******************************************************************************/
+static bool setMaximumCommunicationFrequency(HAL_HsmciDescriptor_t *descriptor, uint8_t freqCode, bool hsMode)
+{
+ uint32_t freqUnit = mmcFrequencyUnits[freqCode & FREQ_UNITS_MASK];
+ uint32_t freqMult = mmcFrequencyMulptiplier[(freqCode & FREQ_MULTIPLIER_MASK) >> FREQ_MULTIPLIER_OFFSET];
+
+ descriptor->clockRate = freqUnit * freqMult * 100;
+ if (hsMode)
+ descriptor->clockRate *= 2;
+ if (-1 == HAL_SetHsmciSpeed(descriptor))
+ return false;
+
+ return true;
+}
+
+/**************************************************************************//**
+\brief Sets maximum 4-line dat bus and high speed mode if card supports it.
+\param[in]
+ descriptor - pointer to hsmci descriptor;
+ csdReg - pointer to csd register structure.
+\return
+ status of operation.
+******************************************************************************/
+static MemStatus_t setBusWidthAndHsMode(HAL_HsmciDescriptor_t *descriptor, MmcCSDRegister_t *csdReg)
+{
+ MmcCardStatus_t *cardStatus;
+ uint8_t specVersion = csdReg->specVersion;
+ uint8_t tranSpeed = csdReg->tranSpeed;
+ HAL_HsmciCommandDescriptor_t *commandDescr = descriptor->commandDescriptor;
+
+ /* send CMD7 command to switch to transfer state */
+ if (!memSendCommand(descriptor, SELECT_CARD, REVALITE_CARD_ADDRESS, R1_RESPONSE_LENGTH))
+ return hsmciError;
+ /* wait for hsmci bus becomes free */
+ while (!HAL_HsmciCheckReady());
+ cardStatus = (MmcCardStatus_t *)(commandDescr->responseBuffer);
+ if (0 != (cardStatus->reg & ERROR_STATUS))
+ return commandError;
+ if (!memCheckState(descriptor, STATUS_TRAN))
+ return stateError;
+
+ /* send CMD16 command to set card block length */
+ if (!memSendCommand(descriptor, SET_BLOCKLEN, STANDARD_BLOCK_LENGTH, R1_RESPONSE_LENGTH))
+ return hsmciError;
+ /* wait for hsmci bus becomes free */
+ while (!HAL_HsmciCheckReady());
+ cardStatus = (MmcCardStatus_t *)(commandDescr->responseBuffer);
+ if (0 != (cardStatus->reg & ERROR_STATUS))
+ return commandError;
+ if (!memCheckState(descriptor, STATUS_TRAN))
+ return stateError;
+
+ if (specVersion < CSD_SPEC_VERS_FOUR)
+ {
+ if (!setMaximumCommunicationFrequency(descriptor, tranSpeed, false))
+ return hsmciError;
+ else
+ return memSuccess;
+ }
+
+ /* send CMD6 command to switch to 4-line bus */
+ if (!memSendCommand(descriptor, SWITCH, CMD6_SET_4_LINE_BUS, R1_RESPONSE_LENGTH))
+ return hsmciError;
+ /* wait for hsmci bus becomes free */
+ while (!HAL_HsmciCheckReady());
+ cardStatus = (MmcCardStatus_t *)(commandDescr->responseBuffer);
+ if (0 != (cardStatus->reg & ERROR_STATUS))
+ return commandError;
+ if (!memCheckState(descriptor, STATUS_TRAN))
+ return stateError;
+
+ descriptor->busWidth = HSMCI_BUS_WIDTH_4;
+ if (-1 == HAL_SetHsmciBusWidth(descriptor))
+ return hsmciError;
+
+ /* send CMD6 command to switch to high speed mode */
+ if (!memSendCommand(descriptor, SWITCH, CMD6_SET_HS_MODE, R1_RESPONSE_LENGTH))
+ return hsmciError;
+ /* wait for hsmci bus becomes free */
+ while (!HAL_HsmciCheckReady());
+ cardStatus = (MmcCardStatus_t *)(commandDescr->responseBuffer);
+ if (0 != (cardStatus->reg & ERROR_STATUS))
+ return commandError;
+ if (!memCheckState(descriptor, STATUS_TRAN))
+ return stateError;
+
+ descriptor->highSpeedMode = true;
+ if (-1 == HAL_SetHsmciHighSpeedMode(descriptor))
+ return hsmciError;
+
+ if (!setMaximumCommunicationFrequency(descriptor, tranSpeed, false))
+ return hsmciError;
+
+ return memSuccess;
+}
+
+//eof mmc.c
diff --git a/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/mscProtocol.c b/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/mscProtocol.c
new file mode 100644
index 00000000..47e5c2d8
--- /dev/null
+++ b/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/mscProtocol.c
@@ -0,0 +1,53 @@
+/****************************************************************************//**
+ \file mscProtocol.c
+
+ \brief Implementation of communication device protocol command.
+
+ \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 <mscProtocol.h>
+#include <usb.h>
+
+/******************************************************************************
+ Implementations section
+******************************************************************************/
+/**************************************************************************//**
+\brief Mass storage device request handler.
+\param[in]
+ data - pointer to host's request.
+******************************************************************************/
+void msdRequestHandler(uint8_t *data)
+{
+ UsbMscRequest_t *pRequest = NULL;
+
+ pRequest = (UsbMscRequest_t *)data;
+ if (NULL == pRequest)
+ return;
+
+ // Check request code
+ switch (pRequest->request.bRequest)
+ {
+ case BULK_ONLY_MASS_STORAGE_RESET:
+ break;
+ case GET_MAX_LUN:
+ HAL_Stall(0);
+ break;
+ default:
+ HAL_Stall(0);
+ break;
+ }
+}
+
+//eof mscProtocol.c
diff --git a/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/scsiProtocol.c b/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/scsiProtocol.c
new file mode 100644
index 00000000..68c3cfb6
--- /dev/null
+++ b/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/MSD/src/scsiProtocol.c
@@ -0,0 +1,398 @@
+/****************************************************************************//**
+ \files scsiProtocol.h
+
+ \brief Implementation of communication device protocol command.
+
+ \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:
+ 30/08/11 N. Fomin - Created
+*******************************************************************************/
+/******************************************************************************
+ Includes section
+******************************************************************************/
+#include <scsiProtocol.h>
+
+/******************************************************************************
+ Define(s) section
+******************************************************************************/
+// scsi commands
+#define INQUIRY 0x12
+#define READ_CAPACITY_10 0x25
+#define READ_10 0x28
+#define REQUEST_SENSE 0x03
+#define TEST_UNIT_READY 0x00
+#define WRITE_10 0x2A
+#define PREVENT_ALLOW_MEDIUM_REMOVAL 0x1E
+#define MODE_SENSE_6 0x1A
+#define READ_FORMAT_CAPACITIES 0x23
+#define VERIFY_10 0x2F
+
+// capacity definitions
+#define BLOCK_SIZE 512
+
+//inquiry definitions
+#define INQUIRY_PERIPHERAL 0x00
+#define INQUIRY_REMOVABLE 0x80
+#define INQUIRY_VERSION 0x04
+#define INQUIRY_RESPONSE_FORMAT 0x02
+#define INQUIRY_ADDITIONAL_LENGTH 0x20
+#define INQUIRY_FLAGS 0x00
+#define INQUIRY_VENDOR_ID "Atmel "
+#define INQUIRY_PRODUCT_ID "Mass Storage "
+#define INQUIRY_PRODUCT_REVISION "0001"
+
+// request sense definitions
+#define REQUEST_SENSE_CODE 0xF0
+#define REQUEST_SENSE_OBSOLETE 0x00
+#define REQUEST_SENSE_NORMAL_FLAGS 0x00
+#define REQUEST_SENSE_ERROR_FLAGS 0x05
+#define REQUEST_SENSE_INFO 0x00
+#define REQUEST_SENSE_ADDITIONAL_SENSE_LENGTH 0x0A
+#define REQUEST_SENSE_CMD_SPECIFIC_INFO 0x00
+#define REQUEST_SENSE_NORMAL_ADDITIONAL_SENSE_CODE 0x00
+#define REQUEST_SENSE_ERROR_ADDITIONAL_SENSE_CODE 0x20
+#define REQUEST_SENSE_ADDITIONAL_SENSE_CODE_QUALIFIER 0x00
+#define REQUEST_SENSE_FIELD_REPLACABLE_UNIT_CODE 0x00
+#define REQUEST_SENSE_SENSE_KEY_SPECIFIC_VALID 0x80
+#define REQUEST_SENSE_SENSE_KEY_SPECIFIC 0x00
+
+// mode sense definitions
+#define MODE_SENSE_LENGTH 0x03
+#define MODE_SENSE_MEDIA_TYPE 0x00
+#define MODE_SENSE_DEVICE_SPECIFIC 0x00
+#define MODE_SENSE_BLOCK_DESC_LENGTH 0x00
+
+// format capacities definitions
+#define FORMAT_CAPACITIES_RESERVED 0x00
+#define FORMAT_CAPACITIES_LENGTH 0x08
+#define FORMAT_CAPACITIES_DESC_TYPE 0x01
+
+/******************************************************************************
+ Types section
+******************************************************************************/
+BEGIN_PACK
+typedef struct PACK
+{
+ uint32_t lastLogicalBlock;
+ uint32_t logicalBlockLength;
+} ScsiReadCapacityResponse_t;
+
+typedef struct PACK
+{
+ uint8_t peripheral;
+ uint8_t removable;
+ uint8_t version;
+ uint8_t responseDataFormat;
+ uint8_t additionalLength;
+ uint8_t flags[3];
+ uint8_t vendorId[8];
+ uint8_t productId[16];
+ uint8_t productRevision[4];
+} ScsiInquiryResponse_t;
+
+typedef struct PACK
+{
+ uint8_t responseCodeAndValid;
+ uint8_t obsolete;
+ uint8_t flags;
+ uint32_t information;
+ uint8_t addSenseLen;
+ uint32_t cmdSpecificInfo;
+ uint8_t additionalSenseCode;
+ uint8_t additionalSenseCodeQualifier;
+ uint8_t fieldReplacableUnitCode;
+ uint8_t senseKeySpecific[3];
+} ScsiRequestSenseResponse_t;
+
+typedef struct PACK
+{
+ uint8_t modeDataLength;
+ uint8_t mediumType;
+ uint8_t deviceSpecific;
+ uint8_t blockDescriptorLength;
+} ScsiModeSense6Response_t;
+
+typedef struct PACK
+{
+ uint8_t reserved[3];
+ uint8_t length;
+ uint32_t blocksNumber;
+ uint8_t descType;
+ uint8_t blockLengthUp;
+ uint16_t blockLengthDown;
+} ScsiReadFormatCapacities_t;
+
+typedef struct PACK
+{
+ uint8_t flags;
+ uint32_t logicalBlockAddress;
+ uint8_t groupNumber;
+ uint16_t transferLength;
+ uint8_t control;
+} ScsiReadWriteCommand_t;
+
+typedef struct PACK
+{
+ uint8_t index;
+ union
+ {
+ ScsiReadWriteCommand_t rwCommand;
+ };
+} ScsiCommand_t;
+END_PACK
+
+/******************************************************************************
+ Global variables section
+******************************************************************************/
+static bool defaultRequestSenseResponse;
+static uint32_t lastLogicalBlockNum;
+
+/******************************************************************************
+ Constants section
+******************************************************************************/
+const ScsiInquiryResponse_t inquiryResponse = {
+ INQUIRY_PERIPHERAL,
+ INQUIRY_REMOVABLE,
+ INQUIRY_VERSION,
+ INQUIRY_RESPONSE_FORMAT,
+ INQUIRY_ADDITIONAL_LENGTH,
+ {INQUIRY_FLAGS, INQUIRY_FLAGS, INQUIRY_FLAGS},
+ INQUIRY_VENDOR_ID,
+ INQUIRY_PRODUCT_ID,
+ INQUIRY_PRODUCT_REVISION
+};
+
+const ScsiRequestSenseResponse_t normalRequestSenseResponse = {
+ REQUEST_SENSE_CODE,
+ REQUEST_SENSE_OBSOLETE,
+ REQUEST_SENSE_NORMAL_FLAGS,
+ SWAP32(REQUEST_SENSE_INFO),
+ REQUEST_SENSE_ADDITIONAL_SENSE_LENGTH,
+ SWAP32(REQUEST_SENSE_CMD_SPECIFIC_INFO),
+ REQUEST_SENSE_NORMAL_ADDITIONAL_SENSE_CODE,
+ REQUEST_SENSE_ADDITIONAL_SENSE_CODE_QUALIFIER,
+ REQUEST_SENSE_FIELD_REPLACABLE_UNIT_CODE,
+ {REQUEST_SENSE_SENSE_KEY_SPECIFIC_VALID, REQUEST_SENSE_SENSE_KEY_SPECIFIC, REQUEST_SENSE_SENSE_KEY_SPECIFIC}
+};
+
+const ScsiRequestSenseResponse_t errorRequestSenseResponse = {
+ REQUEST_SENSE_CODE,
+ REQUEST_SENSE_OBSOLETE,
+ REQUEST_SENSE_ERROR_FLAGS,
+ SWAP32(REQUEST_SENSE_INFO),
+ REQUEST_SENSE_ADDITIONAL_SENSE_LENGTH,
+ SWAP32(REQUEST_SENSE_CMD_SPECIFIC_INFO),
+ REQUEST_SENSE_ERROR_ADDITIONAL_SENSE_CODE,
+ REQUEST_SENSE_ADDITIONAL_SENSE_CODE_QUALIFIER,
+ REQUEST_SENSE_FIELD_REPLACABLE_UNIT_CODE,
+ {REQUEST_SENSE_SENSE_KEY_SPECIFIC_VALID, REQUEST_SENSE_SENSE_KEY_SPECIFIC, REQUEST_SENSE_SENSE_KEY_SPECIFIC}
+};
+
+const ScsiModeSense6Response_t modeSense6Response = {
+ MODE_SENSE_LENGTH,
+ MODE_SENSE_MEDIA_TYPE,
+ MODE_SENSE_DEVICE_SPECIFIC,
+ MODE_SENSE_BLOCK_DESC_LENGTH
+};
+
+/******************************************************************************
+ Implementations section
+******************************************************************************/
+
+/**************************************************************************//**
+\brief Checks if received scsi command is supported.
+\param[in]
+ data - pointer to received command with parameters.
+\return
+ false - command is not supported;
+ true - command is supported.
+******************************************************************************/
+bool scsiIsValidCommand(uint8_t *data)
+{
+ ScsiCommand_t *command = (ScsiCommand_t *)data;
+
+ command->rwCommand.transferLength = SWAP16(command->rwCommand.transferLength);
+ command->rwCommand.logicalBlockAddress = SWAP32(command->rwCommand.logicalBlockAddress);
+
+ switch (command->index)
+ {
+ case INQUIRY:
+ case READ_CAPACITY_10:
+ case TEST_UNIT_READY:
+ case PREVENT_ALLOW_MEDIUM_REMOVAL:
+ case READ_10:
+ case WRITE_10:
+ case MODE_SENSE_6:
+ case READ_FORMAT_CAPACITIES:
+ case VERIFY_10:
+ defaultRequestSenseResponse = true;
+ break;
+ case REQUEST_SENSE:
+ return true;
+ default:
+ defaultRequestSenseResponse = false;
+ break;
+ }
+
+ return defaultRequestSenseResponse;
+}
+
+/**************************************************************************//**
+\brief Checks if any response or data transfer needed for received
+ scsi command.
+\param[in]
+ command - received command.
+\return
+ false - response is not needed;
+ true - response is needed.
+******************************************************************************/
+bool scsiIsDataInOutPhaseNeeded(uint8_t *data)
+{
+ ScsiCommand_t *command = (ScsiCommand_t *)data;
+
+ if ((TEST_UNIT_READY == command->index) || (PREVENT_ALLOW_MEDIUM_REMOVAL == command->index)
+ || (VERIFY_10 == command->index))
+ return false;
+ if ((READ_10 == command->index) || (WRITE_10 == command->index))
+ if (0 == command->rwCommand.transferLength)
+ return false;
+ return true;
+}
+
+/**************************************************************************//**
+\brief Checks if command is read or write command.
+\param[in]
+ command - received command.
+\return
+ false - command is not read/write command;
+ true - command is read/write command.
+******************************************************************************/
+bool scsiIsReadWriteCommand(uint8_t *data)
+{
+ ScsiCommand_t *command = (ScsiCommand_t *)data;
+
+ return ((READ_10 == command->index) || (WRITE_10 == command->index));
+}
+
+/**************************************************************************//**
+\brief Checks if command is read command.
+\param[in]
+ command - received command.
+\return
+ false - command is not read command;
+ true - command is read command.
+******************************************************************************/
+bool scsiIsReadCommand(uint8_t *data)
+{
+ ScsiCommand_t *command = (ScsiCommand_t *)data;
+
+ return (READ_10 == command->index);
+}
+
+/**************************************************************************//**
+\brief Blocks for read/write command.
+\param[in]
+ data - pointer to received command with parameters.
+\return
+ number of blocks to read or write from memory.
+******************************************************************************/
+uint16_t scsiBlocksAmount(uint8_t *data)
+{
+ ScsiCommand_t *command = (ScsiCommand_t *)data;
+
+ if ((READ_10 == command->index) || (WRITE_10 == command->index))
+ return command->rwCommand.transferLength;
+
+ return 0;
+}
+
+/**************************************************************************//**
+\brief Response for scsi command.
+\param[in]
+ command - received command.
+\param[out]
+ buffer - buffer with scsi command response.
+\return
+ length of response
+******************************************************************************/
+uint8_t scsiGetCommandResponse(uint8_t *data, uint8_t *buffer)
+{
+ ScsiCommand_t *command = (ScsiCommand_t *)data;
+ ScsiReadCapacityResponse_t readCapacityResponse = {
+ .lastLogicalBlock = SWAP32(lastLogicalBlockNum),
+ .logicalBlockLength = SWAP32(BLOCK_SIZE)
+ };
+ ScsiReadFormatCapacities_t readFormatCapacitiesResponse = {
+ .reserved = {FORMAT_CAPACITIES_RESERVED, FORMAT_CAPACITIES_RESERVED, FORMAT_CAPACITIES_RESERVED},
+ .length = FORMAT_CAPACITIES_LENGTH,
+ .blocksNumber = SWAP32(lastLogicalBlockNum + 1),
+ .descType = FORMAT_CAPACITIES_DESC_TYPE,
+ .blockLengthUp = 0,
+ .blockLengthDown = SWAP16(BLOCK_SIZE)
+ };
+
+ if (INQUIRY == command->index)
+ {
+ memcpy(buffer, (uint8_t *)&inquiryResponse, sizeof(ScsiInquiryResponse_t));
+ return sizeof(ScsiInquiryResponse_t);
+ }
+ if (READ_CAPACITY_10 == command->index)
+ {
+ memcpy(buffer, (uint8_t *)&readCapacityResponse, sizeof(ScsiReadCapacityResponse_t));
+ return sizeof(ScsiReadCapacityResponse_t);
+ }
+ if (REQUEST_SENSE == command->index)
+ {
+ if (defaultRequestSenseResponse)
+ memcpy(buffer, (uint8_t *)&normalRequestSenseResponse, sizeof(ScsiRequestSenseResponse_t));
+ else
+ memcpy(buffer, (uint8_t *)&errorRequestSenseResponse, sizeof(ScsiRequestSenseResponse_t));
+ return sizeof(ScsiRequestSenseResponse_t);
+ }
+ if (MODE_SENSE_6 == command->index)
+ {
+ memcpy(buffer, (uint8_t *)&modeSense6Response, sizeof(ScsiModeSense6Response_t));
+ return sizeof(ScsiModeSense6Response_t);
+ }
+ if (READ_FORMAT_CAPACITIES == command->index)
+ {
+ memcpy(buffer, (uint8_t *)&readFormatCapacitiesResponse, sizeof(ScsiReadFormatCapacities_t));
+ return sizeof(ScsiReadFormatCapacities_t);
+ }
+ return 0;
+}
+
+/**************************************************************************//**
+\brief Sets number of last available memory block for scsi response.
+\param[in]
+ lastBlock - received command.
+\param[out]
+ buffer - number of last available memory block
+******************************************************************************/
+void scsiSetCapacity(uint32_t lastBlock)
+{
+ lastLogicalBlockNum = lastBlock;
+}
+
+/**************************************************************************//**
+\brief Block address for read/write command.
+\param[in]
+ data - pointer to received command with parameters.
+\return
+ block address for read or write from memory.
+******************************************************************************/
+uint32_t scsiGetBlockAddress(uint8_t *data)
+{
+ ScsiCommand_t *command = (ScsiCommand_t *)data;
+
+ return command->rwCommand.logicalBlockAddress;
+}
+
+//eof scsiProtocol.c