Renamed main folder to firmware

This commit is contained in:
Christina Quast
2015-04-07 18:24:06 +02:00
parent f5cd7efede
commit 5a67c0fef3
326 changed files with 0 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

View File

@@ -0,0 +1,637 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/** \file
* \addtogroup usbd_msd
*@{
*/
/*-----------------------------------------------------------------------------
* Includes
*-----------------------------------------------------------------------------*/
#include "SBCMethods.h"
#include "MSDDStateMachine.h"
/*-----------------------------------------------------------------------------
* Internal functions
*-----------------------------------------------------------------------------*/
/**
* Returns the expected transfer length and direction (IN, OUT or don't care)
* from the host point-of-view.
* \param cbw Pointer to the CBW to examinate
* \param pLength Expected length of command
* \param pType Expected direction of command
*/
static void MSDD_GetCommandInformation(MSCbw *cbw,
unsigned int *length,
unsigned char *type)
{
/* Expected host transfer direction and length */
(*length) = cbw->dCBWDataTransferLength;
if (*length == 0) {
(*type) = MSDD_NO_TRANSFER;
}
else if ((cbw->bmCBWFlags & MSD_CBW_DEVICE_TO_HOST) != 0) {
(*type) = MSDD_DEVICE_TO_HOST;
}
else {
(*type) = MSDD_HOST_TO_DEVICE;
}
}
/**
* Pre-processes a command by checking the differences between the host and
* device expectations in term of transfer type and length.
* Once one of the thirteen cases is identified, the actions to do during the
* post-processing phase are stored in the dCase variable of the command
* state.
* \param pMsdDriver Pointer to a MSDDriver instance
* \return 1 if the command is supported, false otherwise
*/
static unsigned char MSDD_PreProcessCommand(MSDDriver *pMsdDriver)
{
unsigned int hostLength = 0;
unsigned int deviceLength = 0;
unsigned char hostType;
unsigned char deviceType;
unsigned char isCommandSupported;
MSDCommandState *commandState = &(pMsdDriver->commandState);
MSCsw *csw = &(commandState->csw);
MSCbw *cbw = &(commandState->cbw);
MSDLun *lun = &(pMsdDriver->luns[(unsigned char) cbw->bCBWLUN]);
/* Get information about the command */
/* Host-side */
MSDD_GetCommandInformation(cbw, &hostLength, &hostType);
/* Device-side */
isCommandSupported = SBC_GetCommandInformation(cbw->pCommand,
&deviceLength,
&deviceType,
lun);
/* Initialize data residue and result status */
csw->dCSWDataResidue = 0;
csw->bCSWStatus = MSD_CSW_COMMAND_PASSED;
/* Check if the command is supported */
if (isCommandSupported) {
/* Identify the command case */
if(hostType == MSDD_NO_TRANSFER) {
/* Case 1 (Hn = Dn) */
if(deviceType == MSDD_NO_TRANSFER) {
/*TRACE_WARNING("Case 1\n\r"); */
commandState->postprocess = 0;
commandState->length = 0;
}
else if(deviceType == MSDD_DEVICE_TO_HOST) {
/* Case 2 (Hn < Di) */
TRACE_WARNING(
"MSDD_PreProcessCommand: Case 2\n\r");
commandState->postprocess = MSDD_CASE_PHASE_ERROR;
commandState->length = 0;
}
else { /*if(deviceType == MSDD_HOST_TO_DEVICE) { */
/* Case 3 (Hn < Do) */
TRACE_WARNING(
"MSDD_PreProcessCommand: Case 3\n\r");
commandState->postprocess = MSDD_CASE_PHASE_ERROR;
commandState->length = 0;
}
}
/* Case 4 (Hi > Dn) */
else if(hostType == MSDD_DEVICE_TO_HOST) {
if(deviceType == MSDD_NO_TRANSFER) {
TRACE_WARNING(
"MSDD_PreProcessCommand: Case 4\n\r");
commandState->postprocess = MSDD_CASE_STALL_IN;
commandState->length = 0;
csw->dCSWDataResidue = hostLength;
}
else if(deviceType == MSDD_DEVICE_TO_HOST) {
if(hostLength > deviceLength) {
/* Case 5 (Hi > Di) */
TRACE_WARNING(
"MSDD_PreProcessCommand: Case 5\n\r");
commandState->postprocess = MSDD_CASE_STALL_IN;
commandState->length = deviceLength;
csw->dCSWDataResidue = hostLength - deviceLength;
}
else if(hostLength == deviceLength) {
/* Case 6 (Hi = Di) */
commandState->postprocess = 0;
commandState->length = deviceLength;
}
else { /*if(hostLength < deviceLength) { */
/* Case 7 (Hi < Di) */
TRACE_WARNING(
"MSDD_PreProcessCommand: Case 7\n\r");
commandState->postprocess = MSDD_CASE_PHASE_ERROR;
commandState->length = hostLength;
}
}
else { /*if(deviceType == MSDD_HOST_TO_DEVICE) { */
/* Case 8 (Hi <> Do) */
TRACE_WARNING(
"MSDD_PreProcessCommand: Case 8\n\r");
commandState->postprocess =
MSDD_CASE_STALL_IN | MSDD_CASE_PHASE_ERROR;
commandState->length = 0;
}
}
else if(hostType == MSDD_HOST_TO_DEVICE) {
if(deviceType == MSDD_NO_TRANSFER) {
/* Case 9 (Ho > Dn) */
TRACE_WARNING(
"MSDD_PreProcessCommand: Case 9\n\r");
commandState->postprocess = MSDD_CASE_STALL_OUT;
commandState->length = 0;
csw->dCSWDataResidue = hostLength;
}
else if(deviceType == MSDD_DEVICE_TO_HOST) {
/* Case 10 (Ho <> Di) */
TRACE_WARNING(
"MSDD_PreProcessCommand: Case 10\n\r");
commandState->postprocess =
MSDD_CASE_STALL_OUT | MSDD_CASE_PHASE_ERROR;
commandState->length = 0;
}
else { /*if(deviceType == MSDD_HOST_TO_DEVICE) { */
if(hostLength > deviceLength) {
/* Case 11 (Ho > Do) */
TRACE_WARNING(
"MSDD_PreProcessCommand: Case 11\n\r");
commandState->postprocess = MSDD_CASE_STALL_OUT;
/* commandState->length = deviceLength; */
/* csw->dCSWDataResidue = hostLength - deviceLength; */
commandState->length = 0;
csw->dCSWDataResidue = deviceLength;
}
else if(hostLength == deviceLength) {
/* Case 12 (Ho = Do) */
/*TRACE_WARNING( */
/* "MSDD_PreProcessCommand: Case 12\n\r"); */
commandState->postprocess = 0;
commandState->length = deviceLength;
}
else { /*if(hostLength < deviceLength) { */
/* Case 13 (Ho < Do) */
TRACE_WARNING(
"MSDD_PreProcessCommand: Case 13\n\r");
commandState->postprocess = MSDD_CASE_PHASE_ERROR;
commandState->length = hostLength;
}
}
}
}
return isCommandSupported;
}
/**
* Post-processes a command given the case identified during the
* pre-processing step.
* Depending on the case, one of the following actions can be done:
* - Bulk IN endpoint is stalled
* - Bulk OUT endpoint is stalled
* - CSW status set to phase error
* \param pMsdDriver Pointer to a MSDDriver instance
* \return If the device is halted
*/
static unsigned char MSDD_PostProcessCommand(MSDDriver *pMsdDriver)
{
MSDCommandState *commandState = &(pMsdDriver->commandState);
MSCsw *csw = &(commandState->csw);
unsigned char haltStatus = 0;
/* STALL Bulk IN endpoint ? */
if ((commandState->postprocess & MSDD_CASE_STALL_IN) != 0) {
TRACE_INFO_WP("StallIn ");
//MSDD_Halt(MSDD_CASE_STALL_IN);
USBD_Halt(commandState->pipeIN);
haltStatus = 1;
}
/* STALL Bulk OUT endpoint ? */
if ((commandState->postprocess & MSDD_CASE_STALL_OUT) != 0) {
TRACE_INFO_WP("StallOut ");
//MSDD_Halt(MSDD_CASE_STALL_OUT);
USBD_Halt(commandState->pipeOUT);
haltStatus = 1;
}
/* Set CSW status code to phase error ? */
if ((commandState->postprocess & MSDD_CASE_PHASE_ERROR) != 0) {
TRACE_INFO_WP("PhaseErr ");
csw->bCSWStatus = MSD_CSW_PHASE_ERROR;
}
return haltStatus;
}
/**
* Processes the latest command received by the %device.
* \param pMsdDriver Pointer to a MSDDriver instance
* \return 1 if the command has been completed, false otherwise.
*/
static unsigned char MSDD_ProcessCommand(MSDDriver * pMsdDriver)
{
unsigned char status;
MSDCommandState *commandState = &(pMsdDriver->commandState);
MSCbw *cbw = &(commandState->cbw);
MSCsw *csw = &(commandState->csw);
MSDLun *lun = &(pMsdDriver->luns[(unsigned char) cbw->bCBWLUN]);
unsigned char isCommandComplete = 0;
/* Check if LUN is valid */
if (cbw->bCBWLUN > pMsdDriver->maxLun) {
TRACE_WARNING(
"MSDD_ProcessCommand: LUN %d not exist\n\r", cbw->bCBWLUN);
status = MSDD_STATUS_ERROR;
}
else {
/* Process command */
if (pMsdDriver->maxLun > 0) {
TRACE_INFO_WP("LUN%d ", cbw->bCBWLUN);
}
status = SBC_ProcessCommand(lun, commandState);
}
/* Check command result code */
if (status == MSDD_STATUS_PARAMETER) {
TRACE_WARNING(
"MSDD_ProcessCommand: Unknown cmd 0x%02X\n\r",
cbw->pCommand[0]);
/* Update sense data */
SBC_UpdateSenseData(&(lun->requestSenseData),
SBC_SENSE_KEY_ILLEGAL_REQUEST,
SBC_ASC_INVALID_FIELD_IN_CDB,
0);
/* Result codes */
csw->bCSWStatus = MSD_CSW_COMMAND_FAILED;
isCommandComplete = 1;
/* stall the request, IN or OUT */
if (((cbw->bmCBWFlags & MSD_CBW_DEVICE_TO_HOST) == 0)
&& (cbw->dCBWDataTransferLength > 0)) {
/* Stall the OUT endpoint : host to device */
/* MSDD_Halt(MSDD_CASE_STALL_OUT); */
commandState->postprocess = MSDD_CASE_STALL_OUT;
TRACE_INFO_WP("StaOUT ");
}
else {
/* Stall the IN endpoint : device to host */
/* MSDD_Halt(MSDD_CASE_STALL_IN); */
commandState->postprocess = MSDD_CASE_STALL_IN;
TRACE_INFO_WP("StaIN ");
}
}
else if (status == MSDD_STATUS_ERROR) {
TRACE_WARNING("MSD_ProcessCommand: Cmd %x fail\n\r",
((SBCCommand*)commandState->cbw.pCommand)->bOperationCode);
/* Update sense data */
SBC_UpdateSenseData(&(lun->requestSenseData),
SBC_SENSE_KEY_MEDIUM_ERROR,
SBC_ASC_INVALID_FIELD_IN_CDB,
0);
/* Result codes */
csw->bCSWStatus = MSD_CSW_COMMAND_FAILED;
isCommandComplete = 1;
}
else if (status == MSDD_STATUS_RW) {
csw->bCSWStatus = MSD_CSW_COMMAND_FAILED;
isCommandComplete = 1;
}
else {
/* Update sense data */
SBC_UpdateSenseData(&(lun->requestSenseData),
SBC_SENSE_KEY_NO_SENSE,
0,
0);
/* Is command complete ? */
if (status == MSDD_STATUS_SUCCESS) {
isCommandComplete = 1;
}
}
/* Check if command has been completed */
if (isCommandComplete) {
TRACE_INFO_WP("Cplt ");
/* Adjust data residue */
if (commandState->length != 0) {
csw->dCSWDataResidue += commandState->length;
/* STALL the endpoint waiting for data */
if ((cbw->bmCBWFlags & MSD_CBW_DEVICE_TO_HOST) == 0) {
/* Stall the OUT endpoint : host to device */
/* MSDD_Halt(MSDD_CASE_STALL_OUT); */
commandState->postprocess = MSDD_CASE_STALL_OUT;
TRACE_INFO_WP("StaOUT ");
}
else {
/* Stall the IN endpoint : device to host */
/* MSDD_Halt(MSDD_CASE_STALL_IN); */
commandState->postprocess = MSDD_CASE_STALL_IN;
TRACE_INFO_WP("StaIN ");
}
}
/* Reset command state */
commandState->state = 0;
}
return isCommandComplete;
}
/**
* State machine for the MSD %device driver
* \param pMsdDriver Pointer to a MSDDriver instance
*/
void MSDD_StateMachine(MSDDriver * pMsdDriver)
{
MSDCommandState *commandState = &(pMsdDriver->commandState);
MSCbw *cbw = &(commandState->cbw);
MSCsw *csw = &(commandState->csw);
MSDTransfer *transfer = &(commandState->transfer);
unsigned char status;
/* Identify current driver state */
switch (pMsdDriver->state) {
/*---------------------- */
case MSDD_STATE_READ_CBW:
/*---------------------- */
/* Start the CBW read operation */
transfer->semaphore = 0;
#if 1
status = USBD_Read(commandState->pipeOUT,
cbw,
MSD_CBW_SIZE,
(TransferCallback) MSDDriver_Callback,
(void *) transfer);
#else
status = MSDD_Read(cbw,
MSD_CBW_SIZE,
(TransferCallback) MSDDriver_Callback,
(void *) transfer);
#endif
/* Check operation result code */
if (status == USBD_STATUS_SUCCESS) {
/* If the command was successful, wait for transfer */
pMsdDriver->state = MSDD_STATE_WAIT_CBW;
}
break;
/*---------------------- */
case MSDD_STATE_WAIT_CBW:
/*---------------------- */
/* Check transfer semaphore */
if (transfer->semaphore > 0) {
/* Take semaphore and terminate transfer */
transfer->semaphore--;
/* Check if transfer was successful */
if (transfer->status == USBD_STATUS_SUCCESS) {
TRACE_INFO_WP("------------------------------\n\r");
/* Process received command */
pMsdDriver->state = MSDD_STATE_PROCESS_CBW;
}
else if (transfer->status == USBD_STATUS_RESET) {
TRACE_INFO("MSDD_StateMachine: EP resetted\n\r");
pMsdDriver->state = MSDD_STATE_READ_CBW;
}
else {
TRACE_WARNING(
"MSDD_StateMachine: Failed to read CBW\n\r");
pMsdDriver->state = MSDD_STATE_READ_CBW;
}
}
break;
/*------------------------- */
case MSDD_STATE_PROCESS_CBW:
/*------------------------- */
/* Check if this is a new command */
if (commandState->state == 0) {
/* Copy the CBW tag */
csw->dCSWTag = cbw->dCBWTag;
/* Check that the CBW is 31 bytes long */
if ((transfer->transferred != MSD_CBW_SIZE) ||
(transfer->remaining != 0)) {
TRACE_WARNING(
"MSDD_StateMachine: Invalid CBW (len %d)\n\r",
(int)transfer->transferred);
/* Wait for a reset recovery */
pMsdDriver->waitResetRecovery = 1;
/* Halt the Bulk-IN and Bulk-OUT pipes */
//MSDD_Halt(MSDD_CASE_STALL_OUT | MSDD_CASE_STALL_IN);
USBD_Halt(commandState->pipeIN);
USBD_Halt(commandState->pipeOUT);
csw->bCSWStatus = MSD_CSW_COMMAND_FAILED;
pMsdDriver->state = MSDD_STATE_READ_CBW;
}
/* Check the CBW Signature */
else if (cbw->dCBWSignature != MSD_CBW_SIGNATURE) {
TRACE_WARNING(
"MSD_BOTStateMachine: Invalid CBW (Bad signature)\n\r");
/* Wait for a reset recovery */
pMsdDriver->waitResetRecovery = 1;
/* Halt the Bulk-IN and Bulk-OUT pipes */
//MSDD_Halt(MSDD_CASE_STALL_OUT | MSDD_CASE_STALL_IN);
USBD_Halt(commandState->pipeIN);
USBD_Halt(commandState->pipeOUT);
csw->bCSWStatus = MSD_CSW_COMMAND_FAILED;
pMsdDriver->state = MSDD_STATE_READ_CBW;
}
else {
/* Pre-process command */
MSDD_PreProcessCommand(pMsdDriver);
}
}
/* Process command */
if (csw->bCSWStatus == MSDD_STATUS_SUCCESS) {
if (MSDD_ProcessCommand(pMsdDriver)) {
/* Post-process command if it is finished */
if (MSDD_PostProcessCommand(pMsdDriver)) {
TRACE_INFO_WP("WaitHALT ");
pMsdDriver->state = MSDD_STATE_WAIT_HALT;
}
else {
pMsdDriver->state = MSDD_STATE_SEND_CSW;
}
}
TRACE_INFO_WP("\n\r");
}
break;
/*---------------------- */
case MSDD_STATE_SEND_CSW:
/*---------------------- */
/* Set signature */
csw->dCSWSignature = MSD_CSW_SIGNATURE;
/* Start the CSW write operation */
#if 1
status = USBD_Write(commandState->pipeIN,
csw,
MSD_CSW_SIZE,
(TransferCallback) MSDDriver_Callback,
(void *) transfer);
#else
status = MSDD_Write(csw,
MSD_CSW_SIZE,
(TransferCallback) MSDDriver_Callback,
(void *) transfer);
#endif
/* Check operation result code */
if (status == USBD_STATUS_SUCCESS) {
TRACE_INFO_WP("SendCSW ");
/* Wait for end of transfer */
pMsdDriver->state = MSDD_STATE_WAIT_CSW;
}
break;
/*---------------------- */
case MSDD_STATE_WAIT_CSW:
/*---------------------- */
/* Check transfer semaphore */
if (transfer->semaphore > 0) {
/* Take semaphore and terminate transfer */
transfer->semaphore--;
/* Check if transfer was successful */
if (transfer->status == USBD_STATUS_RESET) {
TRACE_INFO("MSDD_StateMachine: EP resetted\n\r");
}
else if (transfer->status == USBD_STATUS_ABORTED) {
TRACE_WARNING(
"MSDD_StateMachine: Failed to send CSW\n\r");
}
else {
TRACE_INFO_WP("ok");
}
/* Read new CBW */
pMsdDriver->state = MSDD_STATE_READ_CBW;
}
break;
/*---------------------- */
case MSDD_STATE_WAIT_HALT:
/*---------------------- */
//if (MSDD_IsHalted() == 0) {
if (!USBD_IsHalted(commandState->pipeIN)) {
pMsdDriver->state = MSDD_STATE_SEND_CSW;
}
break;
}
}
/**@}*/

View File

@@ -0,0 +1,113 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/** \file
* \addtogroup usbd_msd
*@{
* Implement a single interface device with single MS function in.
*/
/*------------------------------------------------------------------------------
* Includes
*------------------------------------------------------------------------------*/
#include <MSDDriver.h>
#include <MSDFunction.h>
#include <USBLib_Trace.h>
#include <USBD.h>
#include <USBD_HAL.h>
#include <USBDDriver.h>
/*-----------------------------------------------------------------------------
* Internal variables
*-----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------
* Internal functions
*-----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------
* Exported functions
*-----------------------------------------------------------------------------*/
/**
* Initializes the MSD driver and the associated USB driver.
* \param pDescriptors Pointer to Descriptors list for MSD Device.
* \param pLuns Pointer to a list of LUNs
* \param numLuns Number of LUN in list
* \see MSDLun
*/
void MSDDriver_Initialize(
const USBDDriverDescriptors *pDescriptors,
MSDLun *pLuns, unsigned char numLuns)
{
USBDDriver *pUsbd = USBD_GetDriver();
USBDDriver_Initialize(pUsbd, pDescriptors, 0);
MSDFunction_Initialize(pUsbd, 0, pLuns, numLuns);
USBD_Init();
}
/**
* Invoked when the configuration of the device changes. Resets the mass
* storage driver.
* \param pMsdDriver Pointer to MSDDriver instance.
* \param cfgnum New configuration number.
*/
void MSDDriver_ConfigurationChangeHandler(
uint8_t cfgnum)
{
USBDDriver *pUsbd = USBD_GetDriver();
USBConfigurationDescriptor *pDesc;
if (cfgnum) {
pDesc = USBDDriver_GetCfgDescriptors(pUsbd, cfgnum);
MSDFunction_Configure((USBGenericDescriptor*)pDesc,
pDesc->wTotalLength);
}
}
/**
* Handler for incoming SETUP requests on default Control endpoint 0.
*
* Standard requests are forwarded to the USBDDriver_RequestHandler
* method.
* \param pMsdDriver Pointer to MSDDriver instance.
* \param request Pointer to a USBGenericRequest instance
*/
void MSDDriver_RequestHandler(
const USBGenericRequest *request)
{
USBDDriver *pUsbd = USBD_GetDriver();
TRACE_INFO_WP("NewReq ");
if (MSDFunction_RequestHandler(request)) {
USBDDriver_RequestHandler(pUsbd, request);
}
}
/**@}*/

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

View File

@@ -0,0 +1,311 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/** \file
* \addtogroup usbd_msd
*@{
* Implements Massstorage Function for USB device.
*/
/*------------------------------------------------------------------------------
* Includes
*------------------------------------------------------------------------------*/
#include <MSDescriptors.h>
#include <MSDDriver.h>
#include <USBLib_Trace.h>
#include <USBD.h>
#include <USBD_HAL.h>
#include <USBDDriver.h>
/*-----------------------------------------------------------------------------
* Internal Types
*-----------------------------------------------------------------------------*/
/** Parse data extension */
typedef struct _MSDParseData {
/** Pointer to driver instance */
MSDDriver *pMsdd;
/** Pointer to currently processed interface descriptor */
USBInterfaceDescriptor *pIf;
} MSDParseData;
/*-----------------------------------------------------------------------------
* Internal variables
*-----------------------------------------------------------------------------*/
/** MSD Driver instance for device function */
static MSDDriver msdFunction;
/*-----------------------------------------------------------------------------
* Internal functions
*-----------------------------------------------------------------------------*/
/**
* Parse descriptors: Bulk EP IN/OUT.
* \param desc Pointer to current processed descriptor.
* \param arg Pointer to data extention struct for parsing.
*/
static uint8_t MSDFunction_Parse(USBGenericDescriptor* desc, MSDParseData* arg)
{
MSDDriver *pMsdd = arg->pMsdd;
USBInterfaceDescriptor *pIf;
/* Not a valid descriptor */
if (desc->bLength == 0) {
return USBD_STATUS_INVALID_PARAMETER;
}
/* Find interface descriptor */
if (desc->bDescriptorType == USBGenericDescriptor_INTERFACE) {
pIf = (USBInterfaceDescriptor*)desc;
if (pIf->bInterfaceClass == MSInterfaceDescriptor_CLASS) {
/* First found IF */
if (pMsdd->interfaceNb == 0xFF) {
pMsdd->interfaceNb = pIf->bInterfaceNumber;
arg->pIf = pIf;
}
/* Specific IF */
else if (pMsdd->interfaceNb == pIf->bInterfaceNumber) {
arg->pIf = pIf;
}
}
}
/* Start parse endpoints */
if (arg->pIf) {
if (desc->bDescriptorType == USBGenericDescriptor_ENDPOINT) {
USBEndpointDescriptor *pEP = (USBEndpointDescriptor*)desc;
if (pEP->bmAttributes == USBEndpointDescriptor_BULK) {
if (pEP->bEndpointAddress & 0x80)
pMsdd->commandState.pipeIN = pEP->bEndpointAddress & 0x7F;
else
pMsdd->commandState.pipeOUT = pEP->bEndpointAddress;
}
}
/* Finish when found all pipes */
if (pMsdd->commandState.pipeIN != 0
&& pMsdd->commandState.pipeOUT != 0) {
return USBRC_FINISHED;
}
}
return 0;
}
/**
* Resets the state of the MSD driver
*/
static void MSDFunction_Reset(void)
{
MSDDriver *pMsdd = &msdFunction;
TRACE_INFO_WP("MSDReset ");
pMsdd->state = MSDD_STATE_READ_CBW;
pMsdd->waitResetRecovery = 0;
pMsdd->commandState.state = 0;
}
/*-----------------------------------------------------------------------------
* Exported functions
*-----------------------------------------------------------------------------*/
/**
* Initializes the MSD driver and the associated USB driver.
* \param pUsbd Pointer to USBDDriver instance.
* \param bInterfaceNb Interface number for the function.
* \param pLuns Pointer to a list of LUNs
* \param numLuns Number of LUN in list
* \see MSDLun
*/
void MSDFunction_Initialize(
USBDDriver *pUsbd, uint8_t bInterfaceNb,
MSDLun *pLuns, uint8_t numLuns)
{
MSDDriver *pMsdDriver = &msdFunction;
TRACE_INFO("MSDFun init\n\r");
/* Driver instance */
pMsdDriver->pUsbd = pUsbd;
pMsdDriver->interfaceNb = bInterfaceNb;
/* Command state initialization */
pMsdDriver->commandState.state = 0;
pMsdDriver->commandState.postprocess = 0;
pMsdDriver->commandState.length = 0;
pMsdDriver->commandState.transfer.semaphore = 0;
/* LUNs */
pMsdDriver->luns = pLuns;
pMsdDriver->maxLun = (uint8_t) (numLuns - 1);
/* Reset BOT driver */
MSDFunction_Reset();
}
/**
* Invoked when the configuration of the device changes.
* Pass endpoints and resets the mass storage function.
* \pDescriptors Pointer to the descriptors for function configure.
* \wLength Length of descriptors in number of bytes.
*/
void MSDFunction_Configure(USBGenericDescriptor *pDescriptors,
uint16_t wLength)
{
MSDDriver *pMsdDriver = &msdFunction;
MSDParseData parseData;
TRACE_INFO_WP("MSDFunCfg ");
pMsdDriver->state = MSDD_STATE_READ_CBW;
pMsdDriver->waitResetRecovery = 0;
pMsdDriver->commandState.state = 0;
parseData.pIf = 0;
parseData.pMsdd = pMsdDriver;
USBGenericDescriptor_Parse((USBGenericDescriptor*)pDescriptors, wLength,
(USBDescriptorParseFunction)MSDFunction_Parse, &parseData);
MSDFunction_Reset();
}
/**
* Handler for incoming SETUP requests on default Control endpoint 0.
*
* Standard requests are forwarded to the USBDDriver_RequestHandler
* method.
* \param pMsdDriver Pointer to MSDDriver instance.
* \param request Pointer to a USBGenericRequest instance
*/
uint32_t MSDFunction_RequestHandler(
const USBGenericRequest *request)
{
MSDDriver *pMsdDriver = &msdFunction;
uint32_t reqCode = (USBGenericRequest_GetType(request) << 8)
| (USBGenericRequest_GetRequest(request));
TRACE_INFO_WP("Msdf ");
/* Handle requests */
switch (reqCode) {
/*--------------------- */
case USBGenericRequest_CLEARFEATURE:
/*--------------------- */
TRACE_INFO_WP("ClrFeat ");
switch (USBFeatureRequest_GetFeatureSelector(request)) {
/*--------------------- */
case USBFeatureRequest_ENDPOINTHALT:
/*--------------------- */
TRACE_INFO_WP("Hlt ");
/* Do not clear the endpoint halt status if the device is waiting */
/* for a reset recovery sequence */
if (!pMsdDriver->waitResetRecovery) {
/* Forward the request to the standard handler */
USBDDriver_RequestHandler(USBD_GetDriver(), request);
}
else {
TRACE_INFO_WP("No ");
}
USBD_Write(0, 0, 0, 0, 0);
return USBRC_SUCCESS; /* Handled */
}
break;
/*------------------- */
case (USBGenericRequest_CLASS<<8)|MSD_GET_MAX_LUN:
/*------------------- */
TRACE_INFO_WP("gMaxLun ");
/* Check request parameters */
if ((request->wValue == 0)
&& (request->wIndex == pMsdDriver->interfaceNb)
&& (request->wLength == 1)) {
USBD_Write(0, &(pMsdDriver->maxLun), 1, 0, 0);
}
else {
TRACE_WARNING(
"MSDDriver_RequestHandler: GetMaxLUN(%d,%d,%d)\n\r",
request->wValue, request->wIndex, request->wLength);
USBD_Stall(0);
}
return USBRC_SUCCESS; /* Handled */
/*----------------------- */
case (USBGenericRequest_CLASS<<8)|MSD_BULK_ONLY_RESET:
/*----------------------- */
TRACE_INFO_WP("Rst ");
/* Check parameters */
if ((request->wValue == 0)
&& (request->wIndex == pMsdDriver->interfaceNb)
&& (request->wLength == 0)) {
/* Reset the MSD driver */
MSDFunction_Reset();
USBD_Write(0, 0, 0, 0, 0);
}
else {
TRACE_WARNING(
"MSDDriver_RequestHandler: Reset(%d,%d,%d)\n\r",
request->wValue, request->wIndex, request->wLength);
USBD_Stall(0);
}
return USBRC_SUCCESS; /* Handled */
}
return USBRC_PARAM_ERR;
}
/**
* State machine for the MSD driver
*/
void MSDFunction_StateMachine(void)
{
if (USBD_GetState() < USBD_STATE_CONFIGURED){}
else MSDD_StateMachine(&msdFunction);
}
/**@}*/

View File

@@ -0,0 +1,75 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/** \file
* \addtogroup usbd_msd
*@{
*/
/*------------------------------------------------------------------------------
* Headers
*------------------------------------------------------------------------------*/
#include "MSDIOFifo.h"
/*------------------------------------------------------------------------------
* Internal variables
*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------
* Exported functions
*------------------------------------------------------------------------------*/
/**
* \brief Initializes a MSDIOFifo instance.
* \param pFifo Pointer to the MSDIOFifo instance to initialize
* \param pBuffer Pointer to a buffer used for read/write operation and
* which must be blockSize bytes aligned.
* \param bufferSize Total size of the buffer in bytes
*/
void MSDIOFifo_Init(MSDIOFifo *pFifo,
void * pBuffer, unsigned short bufferSize)
{
pFifo->pBuffer = pBuffer;
pFifo->bufferSize = bufferSize;
pFifo->inputNdx = 0;
pFifo->outputNdx = 0;
pFifo->inputTotal = 0;
pFifo->outputTotal = 0;
pFifo->inputState = MSDIO_IDLE;
pFifo->outputState = MSDIO_IDLE;
pFifo->fullCnt = 0;
pFifo->nullCnt = 0;
}
/**@}*/

View File

@@ -0,0 +1,389 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/** \file
* \addtogroup usbd_msd
*@{
*/
/*------------------------------------------------------------------------------
* Headers
*------------------------------------------------------------------------------*/
#include "MSDLun.h"
#include <USBLib_Trace.h>
#include <USBD.h>
/*------------------------------------------------------------------------------
* Constants
*------------------------------------------------------------------------------*/
/** Default LUN block size in bytes */
#define DEFAULT_LUN_BLOCK_SIZE 512
/*------------------------------------------------------------------------------
* Internal variables
*------------------------------------------------------------------------------*/
/** Inquiry data to return to the host for the Lun. */
static SBCInquiryData inquiryData = {
SBC_DIRECT_ACCESS_BLOCK_DEVICE, /* Direct-access block device */
SBC_PERIPHERAL_DEVICE_CONNECTED,/* Peripheral device is connected */
0x00, /* Reserved bits */
0x01, /* Media is removable */
SBC_SPC_VERSION_4, /* SPC-4 supported */
0x2, /* Response data format, must be 0x2 */
0, /* Hierarchical addressing not supported */
0, /* ACA not supported */
0x0, /* Obsolete bits */
sizeof(SBCInquiryData) - 5, /* Additional length */
0, /* No embedded SCC */
0, /* No access control coordinator */
SBC_TPGS_NONE, /* No target port support group */
0, /* Third-party copy not supported */
0x0, /* Reserved bits */
0, /* Protection information not supported */
0x0, /* Obsolete bit */
0, /* No embedded enclosure service component */
0x0, /* ??? */
0, /* Device is not multi-port */
0x0, /* Obsolete bits */
0x0, /* Unused feature */
0x0, /* Unused features */
0, /* Task management model not supported */
0x0, /* ??? */
{'A','T','M','E','L',' ',' ',' '},
{'M','a','s','s',' ',
'S','t','o','r','a','g','e',' ',
'M','S','D'},
{'0','.','0','1'},
{'M','a','s','s',' ',
'S','t','o','r','a','g','e',' ',
'E','x','a','m','p','l','e'},
0x00, /* Unused features */
0x00, /* Reserved bits */
{SBC_VERSION_DESCRIPTOR_SBC_3}, /* SBC-3 compliant device */
{0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0} /* Reserved */
};
/*------------------------------------------------------------------------------
* Exported functions
*------------------------------------------------------------------------------*/
/**
* \brief Initializes a LUN instance. Must be invoked at least once even no
* Media is linked.
* \param lun Pointer to the MSDLun instance to initialize
* \param media Media on which the LUN is constructed, set to 0 to
* disconnect the Media or initialize an ejected LUN.
* \param ioBuffer Pointer to a buffer used for read/write operation and
* which must be blockSize bytes long.
* \param ioBufferSize Size of the allocated IO buffer.
* \param baseAddress Base address of the LUN in number of media blocks
* \param size Total size of the LUN in number of media blocks
* \param blockSize One block of the LUN in number of media blocks
* \param protected The LUN area is forced to readonly even the media
* is writable
* \param dataMonitor Pointer to a Monitor Function to analyze the flow of
* this LUN.
*/
void LUN_Init(MSDLun *lun,
Media *media,
uint8_t *ioBuffer,
uint32_t ioBufferSize,
uint32_t baseAddress,
uint32_t size,
uint16_t blockSize,
uint8_t protected,
void (*dataMonitor)(uint8_t flowDirection,
uint32_t dataLength,
uint32_t fifoNullCount,
uint32_t fifoFullCount))
{
uint32_t logicalBlockAddress;
TRACE_INFO("LUN init\n\r");
/* Initialize inquiry data */
lun->inquiryData = &inquiryData;
/* Initialize request sense data */
lun->requestSenseData.bResponseCode = SBC_SENSE_DATA_FIXED_CURRENT;
lun->requestSenseData.isValid = 1;
lun->requestSenseData.bObsolete1 = 0;
lun->requestSenseData.bSenseKey = SBC_SENSE_KEY_NO_SENSE;
lun->requestSenseData.bReserved1 = 0;
lun->requestSenseData.isILI = 0;
lun->requestSenseData.isEOM = 0;
lun->requestSenseData.isFilemark = 0;
lun->requestSenseData.pInformation[0] = 0;
lun->requestSenseData.pInformation[1] = 0;
lun->requestSenseData.pInformation[2] = 0;
lun->requestSenseData.pInformation[3] = 0;
lun->requestSenseData.bAdditionalSenseLength
= sizeof(SBCRequestSenseData) - 8;
lun->requestSenseData.bAdditionalSenseCode = 0;
lun->requestSenseData.bAdditionalSenseCodeQualifier = 0;
lun->requestSenseData.bFieldReplaceableUnitCode = 0;
lun->requestSenseData.bSenseKeySpecific = 0;
lun->requestSenseData.pSenseKeySpecific[0] = 0;
lun->requestSenseData.pSenseKeySpecific[0] = 0;
lun->requestSenseData.isSKSV = 0;
STORE_DWORDB(0, lun->readCapacityData.pLogicalBlockAddress);
STORE_DWORDB(0, lun->readCapacityData.pLogicalBlockLength);
/* Initialize LUN */
lun->media = media;
if (media == 0) {
lun->status = LUN_NOT_PRESENT;
return;
}
lun->baseAddress = baseAddress;
/* Customized block size */
if (blockSize) {
lun->blockSize = blockSize;
}
else {
if (media->blockSize < DEFAULT_LUN_BLOCK_SIZE)
lun->blockSize = DEFAULT_LUN_BLOCK_SIZE / media->blockSize;
else
lun->blockSize = 1;
}
if (size) {
lun->size = size;
}
else {
lun->size = media->size;
/*if (blockSize) */
/* lun->size = media->size / blockSize; */
/*else { */
/* if (media->blockSize < DEFAULT_LUN_BLOCK_SIZE) */
/* lun->size = media->size / lun->blockSize; */
/* else */
/* lun->size = media->size; */
/*} */
}
TRACE_INFO("LUN: blkSize %d, size %d\n\r", (int)lun->blockSize, (int)lun->size);
if (protected) lun->protected = 1;
else lun->protected = media->protected;
lun->ioFifo.pBuffer = ioBuffer;
lun->ioFifo.bufferSize = ioBufferSize;
lun->dataMonitor = dataMonitor;
/* Initialize read capacity data */
logicalBlockAddress = lun->size / lun->blockSize - 1;
STORE_DWORDB(logicalBlockAddress,
lun->readCapacityData.pLogicalBlockAddress);
STORE_DWORDB(lun->blockSize * media->blockSize,
lun->readCapacityData.pLogicalBlockLength);
/* Indicate media change */
lun->status = LUN_CHANGED;
}
/**
* \brief Eject the media from a LUN
* \param lun Pointer to the MSDLun instance to initialize
* \return Operation result code
*/
uint32_t LUN_Eject(MSDLun *lun)
{
if (lun->media) {
/* Avoid any LUN R/W in progress */
if (lun->media->state == MED_STATE_BUSY) {
return USBD_STATUS_LOCKED;
}
/* Remove the link of the media */
lun->media = 0;
}
/* LUN is removed */
lun->status = LUN_NOT_PRESENT;
return USBD_STATUS_SUCCESS;
}
/**
* \brief Writes data on the a LUN starting at the specified block address.
* \param lun Pointer to a MSDLun instance
* \param blockAddress First block address to write
* \param data Pointer to the data to write
* \param length Number of blocks to write
* \param callback Optional callback to invoke when the write finishes
* \param argument Optional callback argument.
* \return Operation result code
*/
uint32_t LUN_Write(MSDLun *lun,
uint32_t blockAddress,
void *data,
uint32_t length,
TransferCallback callback,
void *argument)
{
uint32_t medBlk, medLen;
uint8_t status;
TRACE_INFO_WP("LUNWrite(%u) ", blockAddress);
/* Check that the data is not too big */
if ((length + blockAddress) * lun->blockSize > lun->size) {
TRACE_WARNING("LUN_Write: Data too big\n\r");
status = USBD_STATUS_ABORTED;
}
else if (lun->media == 0 || lun->status != LUN_READY) {
TRACE_WARNING("LUN_Write: Media not ready\n\r");
status = USBD_STATUS_ABORTED;
}
else if (lun->protected) {
TRACE_WARNING("LUN_Write: LUN is readonly\n\r");
status = USBD_STATUS_ABORTED;
}
else {
/* Compute write start address */
medBlk = lun->baseAddress + blockAddress * lun->blockSize;
medLen = length * lun->blockSize;
/* Start write operation */
status = MED_Write(lun->media,
medBlk,
data,
medLen,
(MediaCallback) callback,
argument);
/* Check operation result code */
if (status == MED_STATUS_SUCCESS) {
status = USBD_STATUS_SUCCESS;
}
else {
TRACE_WARNING("LUN_Write: Cannot write media\n\r");
status = USBD_STATUS_ABORTED;
}
}
return status;
}
/**
* \brief Reads data from a LUN, starting at the specified block address.
* \param lun Pointer to a MSDLun instance
* \param blockAddress First block address to read
* \param data Pointer to a data buffer in which to store the data
* \param length Number of blocks to read
* \param callback Optional callback to invoke when the read finishes
* \param argument Optional callback argument.
* \return Operation result code
*/
uint32_t LUN_Read(MSDLun *lun,
uint32_t blockAddress,
void *data,
uint32_t length,
TransferCallback callback,
void *argument)
{
uint32_t medBlk, medLen;
uint8_t status;
/* Check that the data is not too big */
if ((length + blockAddress) * lun->blockSize > lun->size) {
TRACE_WARNING("LUN_Read: Area: (%d + %d)*%d > %d\n\r",
(int)length, (int)blockAddress, (int)lun->blockSize, (int)lun->size);
status = USBD_STATUS_ABORTED;
}
else if (lun->media == 0 || lun->status != LUN_READY) {
TRACE_WARNING("LUN_Read: Media not present\n\r");
status = USBD_STATUS_ABORTED;
}
else {
TRACE_INFO_WP("LUNRead(%u) ", blockAddress);
/* Compute read start address */
medBlk = lun->baseAddress + (blockAddress * lun->blockSize);
medLen = length * lun->blockSize;
/* Start write operation */
status = MED_Read(lun->media,
medBlk,
data,
medLen,
(MediaCallback) callback,
argument);
/* Check result code */
if (status == MED_STATUS_SUCCESS) {
status = USBD_STATUS_SUCCESS;
}
else {
TRACE_WARNING("LUN_Read: Cannot read media\n\r");
status = USBD_STATUS_ABORTED;
}
}
return status;
}
/**@}*/

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

File diff suppressed because it is too large Load Diff