修改了Web后台的部分界面,增加了HAmqtt中的总电量传感器,后台新增mqtt上报频率设置

This commit is contained in:
OOP
2025-03-03 21:49:41 +08:00
parent e1e00b60ce
commit 9f9d4c7a56
4468 changed files with 1473046 additions and 10728 deletions

View File

@@ -0,0 +1,222 @@
/**
******************************************************************************
* @file usbh_msc.h
* @author MCD Application Team
* @version V3.0.0
* @date 18-February-2014
* @brief This file contains all the prototypes for the usbh_msc_core.c
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
*
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/software_license_agreement_liberty_v2
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Define to prevent recursive ----------------------------------------------*/
#ifndef __USBH_MSC_H
#define __USBH_MSC_H
/* Includes ------------------------------------------------------------------*/
#include "usbh_core.h"
#include "usbh_msc_bot.h"
#include "usbh_msc_scsi.h"
/** @addtogroup USBH_LIB
* @{
*/
/** @addtogroup USBH_CLASS
* @{
*/
/** @addtogroup USBH_MSC_CLASS
* @{
*/
/** @defgroup USBH_MSC_CORE
* @brief This file is the Header file for usbh_msc_core.c
* @{
*/
/** @defgroup USBH_MSC_CORE_Exported_Types
* @{
*/
typedef enum
{
MSC_INIT = 0,
MSC_IDLE,
MSC_TEST_UNIT_READY,
MSC_READ_CAPACITY10,
MSC_READ_INQUIRY,
MSC_REQUEST_SENSE,
MSC_READ,
MSC_WRITE,
MSC_UNRECOVERED_ERROR,
MSC_PERIODIC_CHECK,
}
MSC_StateTypeDef;
typedef enum
{
MSC_OK,
MSC_NOT_READY,
MSC_ERROR,
}
MSC_ErrorTypeDef;
typedef enum
{
MSC_REQ_IDLE = 0,
MSC_REQ_RESET,
MSC_REQ_GET_MAX_LUN,
MSC_REQ_ERROR,
}
MSC_ReqStateTypeDef;
#define MAX_SUPPORTED_LUN 2
/* Structure for LUN */
typedef struct
{
MSC_StateTypeDef state;
MSC_ErrorTypeDef error;
USBH_StatusTypeDef prev_ready_state;
SCSI_CapacityTypeDef capacity;
SCSI_SenseTypeDef sense;
SCSI_StdInquiryDataTypeDef inquiry;
uint8_t state_changed;
}
MSC_LUNTypeDef;
/* Structure for MSC process */
typedef struct _MSC_Process
{
uint32_t max_lun;
uint8_t InPipe;
uint8_t OutPipe;
uint8_t OutEp;
uint8_t InEp;
uint16_t OutEpSize;
uint16_t InEpSize;
MSC_StateTypeDef state;
MSC_ErrorTypeDef error;
MSC_ReqStateTypeDef req_state;
MSC_ReqStateTypeDef prev_req_state;
BOT_HandleTypeDef hbot;
MSC_LUNTypeDef unit[MAX_SUPPORTED_LUN];
uint16_t current_lun;
uint16_t rw_lun;
uint32_t timer;
}
MSC_HandleTypeDef;
/**
* @}
*/
/** @defgroup USBH_MSC_CORE_Exported_Defines
* @{
*/
#define USB_REQ_BOT_RESET 0xFF
#define USB_REQ_GET_MAX_LUN 0xFE
/* MSC Class Codes */
#define USB_MSC_CLASS 0x08
/* Interface Descriptor field values for HID Boot Protocol */
#define MSC_BOT 0x50
#define MSC_TRANSPARENT 0x06
/**
* @}
*/
/** @defgroup USBH_MSC_CORE_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_CORE_Exported_Variables
* @{
*/
extern USBH_ClassTypeDef USBH_msc;
#define USBH_MSC_CLASS &USBH_msc
/**
* @}
*/
/** @defgroup USBH_MSC_CORE_Exported_FunctionsPrototype
* @{
*/
/* Common APIs */
uint8_t USBH_MSC_IsReady (USBH_HandleTypeDef *phost);
/* APIs for LUN */
int8_t USBH_MSC_GetMaxLUN (USBH_HandleTypeDef *phost);
uint8_t USBH_MSC_UnitIsReady (USBH_HandleTypeDef *phost, uint8_t lun);
USBH_StatusTypeDef USBH_MSC_GetLUNInfo(USBH_HandleTypeDef *phost, uint8_t lun, MSC_LUNTypeDef *info);
USBH_StatusTypeDef USBH_MSC_Read(USBH_HandleTypeDef *phost,
uint8_t lun,
uint32_t address,
uint8_t *pbuf,
uint32_t length);
USBH_StatusTypeDef USBH_MSC_Write(USBH_HandleTypeDef *phost,
uint8_t lun,
uint32_t address,
uint8_t *pbuf,
uint32_t length);
/**
* @}
*/
#endif /* __USBH_MSC_H */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,233 @@
/**
******************************************************************************
* @file usbh_msc_bot.h
* @author MCD Application Team
* @version V3.0.0
* @date 18-February-2014
* @brief Header file for usbh_msc_bot.c
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
*
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/software_license_agreement_liberty_v2
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Define to prevent recursive ----------------------------------------------*/
#ifndef __USBH_MSC_BOT_H__
#define __USBH_MSC_BOT_H__
/* Includes ------------------------------------------------------------------*/
#include "usbh_core.h"
#include "usbh_msc_bot.h"
/** @addtogroup USBH_LIB
* @{
*/
/** @addtogroup USBH_CLASS
* @{
*/
/** @addtogroup USBH_MSC_CLASS
* @{
*/
/** @defgroup USBH_MSC_BOT
* @brief This file is the Header file for usbh_msc_core.c
* @{
*/
/** @defgroup USBH_MSC_BOT_Exported_Types
* @{
*/
typedef enum {
BOT_OK = 0,
BOT_FAIL = 1,
BOT_PHASE_ERROR = 2,
BOT_BUSY = 3
}
BOT_StatusTypeDef;
typedef enum {
BOT_CMD_IDLE = 0,
BOT_CMD_SEND,
BOT_CMD_WAIT,
}
BOT_CMDStateTypeDef;
/* CSW Status Definitions */
typedef enum
{
BOT_CSW_CMD_PASSED = 0x00,
BOT_CSW_CMD_FAILED = 0x01,
BOT_CSW_PHASE_ERROR = 0x02,
}
BOT_CSWStatusTypeDef;
typedef enum {
BOT_SEND_CBW = 1,
BOT_SEND_CBW_WAIT,
BOT_DATA_IN,
BOT_DATA_IN_WAIT,
BOT_DATA_OUT,
BOT_DATA_OUT_WAIT,
BOT_RECEIVE_CSW,
BOT_RECEIVE_CSW_WAIT,
BOT_ERROR_IN,
BOT_ERROR_OUT,
BOT_UNRECOVERED_ERROR
}
BOT_StateTypeDef;
typedef union
{
struct __CBW
{
uint32_t Signature;
uint32_t Tag;
uint32_t DataTransferLength;
uint8_t Flags;
uint8_t LUN;
uint8_t CBLength;
uint8_t CB[16];
}field;
uint8_t data[31];
}
BOT_CBWTypeDef;
typedef union
{
struct __CSW
{
uint32_t Signature;
uint32_t Tag;
uint32_t DataResidue;
uint8_t Status;
}field;
uint8_t data[13];
}
BOT_CSWTypeDef;
typedef struct
{
uint32_t data[16];
BOT_StateTypeDef state;
BOT_StateTypeDef prev_state;
BOT_CMDStateTypeDef cmd_state;
BOT_CBWTypeDef cbw;
uint8_t Reserved1;
BOT_CSWTypeDef csw;
uint8_t Reserved2[3];
uint8_t *pbuf;
}
BOT_HandleTypeDef;
/**
* @}
*/
/** @defgroup USBH_MSC_BOT_Exported_Defines
* @{
*/
#define BOT_CBW_SIGNATURE 0x43425355
#define BOT_CBW_TAG 0x20304050
#define BOT_CSW_SIGNATURE 0x53425355
#define BOT_CBW_LENGTH 31
#define BOT_CSW_LENGTH 13
#define BOT_SEND_CSW_DISABLE 0
#define BOT_SEND_CSW_ENABLE 1
#define BOT_DIR_IN 0
#define BOT_DIR_OUT 1
#define BOT_DIR_BOTH 2
#define BOT_PAGE_LENGTH 512
#define BOT_CBW_CB_LENGTH 16
#define USB_REQ_BOT_RESET 0xFF
#define USB_REQ_GET_MAX_LUN 0xFE
#define MAX_BULK_STALL_COUNT_LIMIT 0x04 /* If STALL is seen on Bulk
Endpoint continously, this means
that device and Host has phase error
Hence a Reset is needed */
/**
* @}
*/
/** @defgroup USBH_MSC_BOT_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_BOT_Exported_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_BOT_Exported_FunctionsPrototype
* @{
*/
USBH_StatusTypeDef USBH_MSC_BOT_REQ_Reset(USBH_HandleTypeDef *phost);
USBH_StatusTypeDef USBH_MSC_BOT_REQ_GetMaxLUN(USBH_HandleTypeDef *phost, uint8_t *Maxlun);
USBH_StatusTypeDef USBH_MSC_BOT_Init(USBH_HandleTypeDef *phost);
USBH_StatusTypeDef USBH_MSC_BOT_Process (USBH_HandleTypeDef *phost, uint8_t lun);
USBH_StatusTypeDef USBH_MSC_BOT_Error(USBH_HandleTypeDef *phost, uint8_t lun);
/**
* @}
*/
#endif //__USBH_MSC_BOT_H__
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,218 @@
/**
******************************************************************************
* @file usbh_msc_scsi.h
* @author MCD Application Team
* @version V3.0.0
* @date 18-February-2014
* @brief Header file for usbh_msc_scsi.c
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
*
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/software_license_agreement_liberty_v2
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Define to prevent recursive ----------------------------------------------*/
#ifndef __USBH_MSC_SCSI_H__
#define __USBH_MSC_SCSI_H__
/* Includes ------------------------------------------------------------------*/
#include "usbh_core.h"
/** @addtogroup USBH_LIB
* @{
*/
/** @addtogroup USBH_CLASS
* @{
*/
/** @addtogroup USBH_MSC_CLASS
* @{
*/
/** @defgroup USBH_MSC_SCSI
* @brief This file is the Header file for usbh_msc_scsi.c
* @{
*/
// Capacity data.
typedef struct
{
uint32_t block_nbr;
uint16_t block_size;
} SCSI_CapacityTypeDef;
// Sense data.
typedef struct
{
uint8_t key;
uint8_t asc;
uint8_t ascq;
} SCSI_SenseTypeDef;
// INQUIRY data.
typedef struct
{
uint8_t PeripheralQualifier;
uint8_t DeviceType;
uint8_t RemovableMedia;
uint8_t vendor_id[9];
uint8_t product_id[17];
uint8_t revision_id[5];
}SCSI_StdInquiryDataTypeDef;
/** @defgroup USBH_MSC_SCSI_Exported_Defines
* @{
*/
#define OPCODE_TEST_UNIT_READY 0x00
#define OPCODE_READ_CAPACITY10 0x25
#define OPCODE_READ10 0x28
#define OPCODE_WRITE10 0x2A
#define OPCODE_REQUEST_SENSE 0x03
#define OPCODE_INQUIRY 0x12
#define DATA_LEN_MODE_TEST_UNIT_READY 0
#define DATA_LEN_READ_CAPACITY10 8
#define DATA_LEN_INQUIRY 36
#define DATA_LEN_REQUEST_SENSE 14
#define CBW_CB_LENGTH 16
#define CBW_LENGTH 10
/** @defgroup USBH_MSC_SCSI_Exported_Defines
* @{
*/
#define SCSI_SENSE_KEY_NO_SENSE 0x00
#define SCSI_SENSE_KEY_RECOVERED_ERROR 0x01
#define SCSI_SENSE_KEY_NOT_READY 0x02
#define SCSI_SENSE_KEY_MEDIUM_ERROR 0x03
#define SCSI_SENSE_KEY_HARDWARE_ERROR 0x04
#define SCSI_SENSE_KEY_ILLEGAL_REQUEST 0x05
#define SCSI_SENSE_KEY_UNIT_ATTENTION 0x06
#define SCSI_SENSE_KEY_DATA_PROTECT 0x07
#define SCSI_SENSE_KEY_BLANK_CHECK 0x08
#define SCSI_SENSE_KEY_VENDOR_SPECIFIC 0x09
#define SCSI_SENSE_KEY_COPY_ABORTED 0x0A
#define SCSI_SENSE_KEY_ABORTED_COMMAND 0x0B
#define SCSI_SENSE_KEY_VOLUME_OVERFLOW 0x0D
#define SCSI_SENSE_KEY_MISCOMPARE 0x0E
/**
* @}
*/
/** @defgroup USBH_MSC_SCSI_Exported_Defines
* @{
*/
#define SCSI_ASC_NO_ADDITIONAL_SENSE_INFORMATION 0x00
#define SCSI_ASC_LOGICAL_UNIT_NOT_READY 0x04
#define SCSI_ASC_INVALID_FIELD_IN_CDB 0x24
#define SCSI_ASC_WRITE_PROTECTED 0x27
#define SCSI_ASC_FORMAT_ERROR 0x31
#define SCSI_ASC_INVALID_COMMAND_OPERATION_CODE 0x20
#define SCSI_ASC_NOT_READY_TO_READY_CHANGE 0x28
#define SCSI_ASC_MEDIUM_NOT_PRESENT 0x3A
/**
* @}
*/
/** @defgroup USBH_MSC_SCSI_Exported_Defines
* @{
*/
#define SCSI_ASCQ_FORMAT_COMMAND_FAILED 0x01
#define SCSI_ASCQ_INITIALIZING_COMMAND_REQUIRED 0x02
#define SCSI_ASCQ_OPERATION_IN_PROGRESS 0x07
/**
* @}
*/
/** @defgroup USBH_MSC_SCSI_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup _Exported_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_SCSI_Exported_FunctionsPrototype
* @{
*/
USBH_StatusTypeDef USBH_MSC_SCSI_TestUnitReady (USBH_HandleTypeDef *phost,
uint8_t lun);
USBH_StatusTypeDef USBH_MSC_SCSI_ReadCapacity (USBH_HandleTypeDef *phost,
uint8_t lun,
SCSI_CapacityTypeDef *capacity);
USBH_StatusTypeDef USBH_MSC_SCSI_Inquiry (USBH_HandleTypeDef *phost,
uint8_t lun,
SCSI_StdInquiryDataTypeDef *inquiry);
USBH_StatusTypeDef USBH_MSC_SCSI_RequestSense (USBH_HandleTypeDef *phost,
uint8_t lun,
SCSI_SenseTypeDef *sense_data);
USBH_StatusTypeDef USBH_MSC_SCSI_Write(USBH_HandleTypeDef *phost,
uint8_t lun,
uint32_t address,
uint8_t *pbuf,
uint32_t length);
USBH_StatusTypeDef USBH_MSC_SCSI_Read(USBH_HandleTypeDef *phost,
uint8_t lun,
uint32_t address,
uint8_t *pbuf,
uint32_t length);
/**
* @}
*/
#endif //__USBH_MSC_SCSI_H__
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,796 @@
/**
******************************************************************************
* @file usbh_msc.c
* @author MCD Application Team
* @version V3.0.0
* @date 18-February-2014
* @brief This file implements the MSC class driver functions
* ===================================================================
* MSC Class Description
* ===================================================================
* This module manages the MSC class V1.0 following the "Universal
* Serial Bus Mass Storage Class (MSC) Bulk-Only Transport (BOT) Version 1.0
* Sep. 31, 1999".
* This driver implements the following aspects of the specification:
* - Bulk-Only Transport protocol
* - Subclass : SCSI transparent command set (ref. SCSI Primary Commands - 3 (SPC-3))
*
* @endverbatim
*
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
*
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/software_license_agreement_liberty_v2
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbh_msc.h"
#include "usbh_msc_bot.h"
#include "usbh_msc_scsi.h"
/** @addtogroup USBH_LIB
* @{
*/
/** @addtogroup USBH_CLASS
* @{
*/
/** @addtogroup USBH_MSC_CLASS
* @{
*/
/** @defgroup USBH_MSC_CORE
* @brief This file includes the mass storage related functions
* @{
*/
/** @defgroup USBH_MSC_CORE_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_CORE_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_CORE_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_CORE_Private_Variables
* @{
*/
/**
* @}
*/
uint16_t USBH_CLASS = USBH_CLASS_EVENT;
/** @defgroup USBH_MSC_CORE_Private_FunctionPrototypes
* @{
*/
static USBH_StatusTypeDef USBH_MSC_InterfaceInit (USBH_HandleTypeDef *phost);
static USBH_StatusTypeDef USBH_MSC_InterfaceDeInit (USBH_HandleTypeDef *phost);
static USBH_StatusTypeDef USBH_MSC_Process(USBH_HandleTypeDef *phost);
static USBH_StatusTypeDef USBH_MSC_ClassRequest(USBH_HandleTypeDef *phost);
static USBH_StatusTypeDef USBH_MSC_SOFProcess(USBH_HandleTypeDef *phost);
static USBH_StatusTypeDef USBH_MSC_RdWrProcess(USBH_HandleTypeDef *phost, uint8_t lun);
USBH_ClassTypeDef USBH_msc =
{
"MSC",
USB_MSC_CLASS,
USBH_MSC_InterfaceInit,
USBH_MSC_InterfaceDeInit,
USBH_MSC_ClassRequest,
USBH_MSC_Process,
USBH_MSC_SOFProcess,
NULL,
};
/**
* @}
*/
/** @defgroup USBH_MSC_CORE_Exported_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_CORE_Private_Functions
* @{
*/
/**
* @brief USBH_MSC_InterfaceInit
* The function init the MSC class.
* @param phost: Host handle
* @retval USBH Status
*/
static USBH_StatusTypeDef USBH_MSC_InterfaceInit (USBH_HandleTypeDef *phost)
{
uint8_t interface = 0;
USBH_StatusTypeDef status = USBH_FAIL ;
MSC_HandleTypeDef *MSC_Handle;
interface = USBH_FindInterface(phost, phost->pActiveClass->ClassCode, MSC_TRANSPARENT, MSC_BOT);
if(interface == 0xFF) /* Not Valid Interface */
{
USBH_DbgLog ("Cannot Find the interface for %s class.", phost->pActiveClass->Name);
status = USBH_FAIL;
}
else
{
USBH_SelectInterface (phost, interface);
phost->pActiveClass->pData = (MSC_HandleTypeDef *)USBH_malloc (sizeof(MSC_HandleTypeDef));
MSC_Handle = phost->pActiveClass->pData;
if(phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[0].bEndpointAddress & 0x80)
{
MSC_Handle->InEp = (phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[0].bEndpointAddress);
MSC_Handle->InEpSize = phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[0].wMaxPacketSize;
}
else
{
MSC_Handle->OutEp = (phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[0].bEndpointAddress);
MSC_Handle->OutEpSize = phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[0].wMaxPacketSize;
}
if(phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[1].bEndpointAddress & 0x80)
{
MSC_Handle->InEp = (phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[1].bEndpointAddress);
MSC_Handle->InEpSize = phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[1].wMaxPacketSize;
}
else
{
MSC_Handle->OutEp = (phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[1].bEndpointAddress);
MSC_Handle->OutEpSize = phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[1].wMaxPacketSize;
}
MSC_Handle->current_lun = 0;
MSC_Handle->rw_lun = 0;
MSC_Handle->state = MSC_INIT;
MSC_Handle->error = MSC_OK;
MSC_Handle->req_state = MSC_REQ_IDLE;
MSC_Handle->OutPipe = USBH_AllocPipe(phost, MSC_Handle->OutEp);
MSC_Handle->InPipe = USBH_AllocPipe(phost, MSC_Handle->InEp);
USBH_MSC_BOT_Init(phost);
/* De-Initialize LUNs information */
USBH_memset(MSC_Handle->unit, 0, sizeof(MSC_Handle->unit));
/* Open the new channels */
USBH_OpenPipe (phost,
MSC_Handle->OutPipe,
MSC_Handle->OutEp,
phost->device.address,
phost->device.speed,
USB_EP_TYPE_BULK,
MSC_Handle->OutEpSize);
USBH_OpenPipe (phost,
MSC_Handle->InPipe,
MSC_Handle->InEp,
phost->device.address,
phost->device.speed,
USB_EP_TYPE_BULK,
MSC_Handle->InEpSize);
USBH_LL_SetToggle (phost, MSC_Handle->InPipe,0);
USBH_LL_SetToggle (phost, MSC_Handle->OutPipe,0);
status = USBH_OK;
}
return status;
}
/**
* @brief USBH_MSC_InterfaceDeInit
* The function DeInit the Pipes used for the MSC class.
* @param phost: Host handle
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_MSC_InterfaceDeInit (USBH_HandleTypeDef *phost)
{
MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData;
if ( MSC_Handle->OutPipe)
{
USBH_ClosePipe(phost, MSC_Handle->OutPipe);
USBH_FreePipe (phost, MSC_Handle->OutPipe);
MSC_Handle->OutPipe = 0; /* Reset the Channel as Free */
}
if ( MSC_Handle->InPipe)
{
USBH_ClosePipe(phost, MSC_Handle->InPipe);
USBH_FreePipe (phost, MSC_Handle->InPipe);
MSC_Handle->InPipe = 0; /* Reset the Channel as Free */
}
if(phost->pActiveClass->pData)
{
USBH_free (phost->pActiveClass->pData);
phost->pActiveClass->pData = 0;
}
return USBH_OK;
}
/**
* @brief USBH_MSC_ClassRequest
* The function is responsible for handling Standard requests
* for MSC class.
* @param phost: Host handle
* @retval USBH Status
*/
static USBH_StatusTypeDef USBH_MSC_ClassRequest(USBH_HandleTypeDef *phost)
{
MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData;
USBH_StatusTypeDef status = USBH_BUSY;
uint8_t i;
/* Switch MSC REQ state machine */
switch (MSC_Handle->req_state)
{
case MSC_REQ_IDLE:
case MSC_REQ_GET_MAX_LUN:
/* Issue GetMaxLUN request */
if(USBH_MSC_BOT_REQ_GetMaxLUN(phost, (uint8_t *)&MSC_Handle->max_lun) == USBH_OK )
{
MSC_Handle->max_lun = (uint8_t )(MSC_Handle->max_lun) + 1;
USBH_UsrLog ("Number of supported LUN: %lu", (int32_t)(MSC_Handle->max_lun));
for(i = 0; i < MSC_Handle->max_lun; i++)
{
MSC_Handle->unit[i].prev_ready_state = USBH_FAIL;
MSC_Handle->unit[i].state_changed = 0;
}
status = USBH_OK;
}
break;
case MSC_REQ_ERROR :
/* a Clear Feature should be issued here */
if(USBH_ClrFeature(phost, 0x00) == USBH_OK)
{
MSC_Handle->req_state = MSC_Handle->prev_req_state;
}
break;
default:
break;
}
return status;
}
/**
* @brief USBH_MSC_Process
* The function is for managing state machine for MSC data transfers
* @param phost: Host handle
* @retval USBH Status
*/
static USBH_StatusTypeDef USBH_MSC_Process(USBH_HandleTypeDef *phost)
{
MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData;
USBH_StatusTypeDef error = USBH_BUSY ;
USBH_StatusTypeDef scsi_status = USBH_BUSY ;
USBH_StatusTypeDef ready_status = USBH_BUSY ;
switch (MSC_Handle->state)
{
case MSC_INIT:
if(MSC_Handle->current_lun < MSC_Handle->max_lun)
{
MSC_Handle->unit[MSC_Handle->current_lun].error = MSC_NOT_READY;
/* Switch MSC REQ state machine */
switch (MSC_Handle->unit[MSC_Handle->current_lun].state)
{
case MSC_INIT:
USBH_UsrLog ("LUN #%d: ", MSC_Handle->current_lun);
MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_READ_INQUIRY;
MSC_Handle->timer = phost->Timer + 10000;
case MSC_READ_INQUIRY:
scsi_status = USBH_MSC_SCSI_Inquiry(phost, MSC_Handle->current_lun, &MSC_Handle->unit[MSC_Handle->current_lun].inquiry);
if( scsi_status == USBH_OK)
{
USBH_UsrLog ("Inquiry Vendor : %s", MSC_Handle->unit[MSC_Handle->current_lun].inquiry.vendor_id);
USBH_UsrLog ("Inquiry Product : %s", MSC_Handle->unit[MSC_Handle->current_lun].inquiry.product_id);
USBH_UsrLog ("Inquiry Version : %s", MSC_Handle->unit[MSC_Handle->current_lun].inquiry.revision_id);
MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_TEST_UNIT_READY;
}
if( scsi_status == USBH_FAIL)
{
MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_REQUEST_SENSE;
}
else if(scsi_status == USBH_UNRECOVERED_ERROR)
{
MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_IDLE;
MSC_Handle->unit[MSC_Handle->current_lun].error = MSC_ERROR;
}
break;
case MSC_TEST_UNIT_READY:
ready_status = USBH_MSC_SCSI_TestUnitReady(phost, MSC_Handle->current_lun);
if( ready_status == USBH_OK)
{
if( MSC_Handle->unit[MSC_Handle->current_lun].prev_ready_state != USBH_OK)
{
MSC_Handle->unit[MSC_Handle->current_lun].state_changed = 1;
USBH_UsrLog ("Mass Storage Device ready");
}
else
{
MSC_Handle->unit[MSC_Handle->current_lun].state_changed = 0;
}
MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_READ_CAPACITY10;
MSC_Handle->unit[MSC_Handle->current_lun].error = MSC_OK;
MSC_Handle->unit[MSC_Handle->current_lun].prev_ready_state = USBH_OK;
}
if( ready_status == USBH_FAIL)
{
/* Media not ready, so try to check again during 10s */
if( MSC_Handle->unit[MSC_Handle->current_lun].prev_ready_state != USBH_FAIL)
{
MSC_Handle->unit[MSC_Handle->current_lun].state_changed = 1;
USBH_UsrLog ("Mass Storage Device NOT ready");
}
else
{
MSC_Handle->unit[MSC_Handle->current_lun].state_changed = 0;
}
MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_REQUEST_SENSE;
MSC_Handle->unit[MSC_Handle->current_lun].error = MSC_NOT_READY;
MSC_Handle->unit[MSC_Handle->current_lun].prev_ready_state = USBH_FAIL;
}
else if(ready_status == USBH_UNRECOVERED_ERROR)
{
MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_IDLE;
MSC_Handle->unit[MSC_Handle->current_lun].error = MSC_ERROR;
}
break;
case MSC_READ_CAPACITY10:
scsi_status = USBH_MSC_SCSI_ReadCapacity(phost,MSC_Handle->current_lun, &MSC_Handle->unit[MSC_Handle->current_lun].capacity) ;
if(scsi_status == USBH_OK)
{
if(MSC_Handle->unit[MSC_Handle->current_lun].state_changed == 1)
{
USBH_UsrLog ("Mass Storage Device capacity : %lu MB", \
(int32_t)((MSC_Handle->unit[MSC_Handle->current_lun].capacity.block_nbr * MSC_Handle->unit[MSC_Handle->current_lun].capacity.block_size)/1024/1024));
USBH_UsrLog ("Block number : %lu", (int32_t)(MSC_Handle->unit[MSC_Handle->current_lun].capacity.block_nbr));
USBH_UsrLog ("Block Size : %lu", (int32_t)(MSC_Handle->unit[MSC_Handle->current_lun].capacity.block_size));
}
MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_IDLE;
MSC_Handle->unit[MSC_Handle->current_lun].error = MSC_OK;
MSC_Handle->current_lun++;
}
else if( scsi_status == USBH_FAIL)
{
MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_REQUEST_SENSE;
}
else if(scsi_status == USBH_UNRECOVERED_ERROR)
{
MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_IDLE;
MSC_Handle->unit[MSC_Handle->current_lun].error = MSC_ERROR;
}
break;
case MSC_REQUEST_SENSE:
scsi_status = USBH_MSC_SCSI_RequestSense(phost, MSC_Handle->current_lun, &MSC_Handle->unit[MSC_Handle->current_lun].sense);
if( scsi_status == USBH_OK)
{
if((MSC_Handle->unit[MSC_Handle->current_lun].sense.key == SCSI_SENSE_KEY_UNIT_ATTENTION) ||
(MSC_Handle->unit[MSC_Handle->current_lun].sense.key == SCSI_SENSE_KEY_NOT_READY) )
{
if(phost->Timer <= MSC_Handle->timer)
{
MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_TEST_UNIT_READY;
break;
}
}
USBH_UsrLog ("Sense Key : %x", MSC_Handle->unit[MSC_Handle->current_lun].sense.key);
USBH_UsrLog ("Additional Sense Code : %x", MSC_Handle->unit[MSC_Handle->current_lun].sense.asc);
USBH_UsrLog ("Additional Sense Code Qualifier: %x", MSC_Handle->unit[MSC_Handle->current_lun].sense.ascq);
MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_IDLE;
MSC_Handle->current_lun++;
}
if( scsi_status == USBH_FAIL)
{
USBH_UsrLog ("Mass Storage Device NOT ready");
MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_UNRECOVERED_ERROR;
}
else if(scsi_status == USBH_UNRECOVERED_ERROR)
{
MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_IDLE;
MSC_Handle->unit[MSC_Handle->current_lun].error = MSC_ERROR;
}
break;
case MSC_UNRECOVERED_ERROR:
MSC_Handle->current_lun++;
break;
default:
break;
}
#if (USBH_USE_OS == 1)
mico_rtos_push_to_queue((mico_queue_t *) &(phost->os_event), &USBH_CLASS, 0 );
#endif
}
else
{
MSC_Handle->current_lun = 0;
MSC_Handle->state = MSC_IDLE;
#if (USBH_USE_OS == 1)
mico_rtos_push_to_queue((mico_queue_t *) &(phost->os_event), &USBH_CLASS, 0 );
#endif
phost->pUser(phost, HOST_USER_CLASS_ACTIVE);
}
break;
case MSC_IDLE:
error = USBH_OK;
break;
default:
break;
}
return error;
}
/**
* @brief USBH_MSC_SOFProcess
* The function is for SOF state
* @param phost: Host handle
* @retval USBH Status
*/
static USBH_StatusTypeDef USBH_MSC_SOFProcess(USBH_HandleTypeDef *phost)
{
return USBH_OK;
}
/**
* @brief USBH_MSC_RdWrProcess
* The function is for managing state machine for MSC I/O Process
* @param phost: Host handle
* @param lun: logical Unit Number
* @retval USBH Status
*/
static USBH_StatusTypeDef USBH_MSC_RdWrProcess(USBH_HandleTypeDef *phost, uint8_t lun)
{
MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData;
USBH_StatusTypeDef error = USBH_BUSY ;
USBH_StatusTypeDef scsi_status = USBH_BUSY ;
/* Switch MSC REQ state machine */
switch (MSC_Handle->unit[lun].state)
{
case MSC_READ:
scsi_status = USBH_MSC_SCSI_Read(phost,lun, 0, NULL, 0) ;
if(scsi_status == USBH_OK)
{
MSC_Handle->unit[lun].state = MSC_IDLE;
error = USBH_OK;
}
else if( scsi_status == USBH_FAIL)
{
MSC_Handle->unit[lun].state = MSC_REQUEST_SENSE;
}
else if(scsi_status == USBH_UNRECOVERED_ERROR)
{
MSC_Handle->unit[lun].state = MSC_UNRECOVERED_ERROR;
error = USBH_FAIL;
}
#if (USBH_USE_OS == 1)
mico_rtos_push_to_queue((mico_queue_t *) &(phost->os_event), &USBH_CLASS, 0 );
#endif
break;
case MSC_WRITE:
scsi_status = USBH_MSC_SCSI_Write(phost,lun, 0, NULL, 0) ;
if(scsi_status == USBH_OK)
{
MSC_Handle->unit[lun].state = MSC_IDLE;
error = USBH_OK;
}
else if( scsi_status == USBH_FAIL)
{
MSC_Handle->unit[lun].state = MSC_REQUEST_SENSE;
}
else if(scsi_status == USBH_UNRECOVERED_ERROR)
{
MSC_Handle->unit[lun].state = MSC_UNRECOVERED_ERROR;
error = USBH_FAIL;
}
#if (USBH_USE_OS == 1)
mico_rtos_push_to_queue((mico_queue_t *) &(phost->os_event), &USBH_CLASS, 0 );
#endif
break;
case MSC_REQUEST_SENSE:
scsi_status = USBH_MSC_SCSI_RequestSense(phost, lun, &MSC_Handle->unit[lun].sense);
if( scsi_status == USBH_OK)
{
USBH_UsrLog ("Sense Key : %x", MSC_Handle->unit[lun].sense.key);
USBH_UsrLog ("Additional Sense Code : %x", MSC_Handle->unit[lun].sense.asc);
USBH_UsrLog ("Additional Sense Code Qualifier: %x", MSC_Handle->unit[lun].sense.ascq);
MSC_Handle->unit[lun].state = MSC_IDLE;
MSC_Handle->unit[lun].error = MSC_ERROR;
error = USBH_FAIL;
}
if( scsi_status == USBH_FAIL)
{
USBH_UsrLog ("Mass Storage Device NOT ready");
}
else if(scsi_status == USBH_UNRECOVERED_ERROR)
{
MSC_Handle->unit[lun].state = MSC_UNRECOVERED_ERROR;
error = USBH_FAIL;
}
#if (USBH_USE_OS == 1)
mico_rtos_push_to_queue((mico_queue_t *) &(phost->os_event), &USBH_CLASS, 0 );
#endif
break;
default:
break;
}
return error;
}
/**
* @brief USBH_MSC_IsReady
* The function check if the MSC function is ready
* @param phost: Host handle
* @retval USBH Status
*/
uint8_t USBH_MSC_IsReady (USBH_HandleTypeDef *phost)
{
MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData;
if(phost->gState == HOST_CLASS)
{
return (MSC_Handle->state == MSC_IDLE);
}
else
{
return 0;
}
}
/**
* @brief USBH_MSC_GetMaxLUN
* The function return the Max LUN supported
* @param phost: Host handle
* @retval logical Unit Number supported
*/
int8_t USBH_MSC_GetMaxLUN (USBH_HandleTypeDef *phost)
{
MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData;
if ((phost->gState != HOST_CLASS) && (MSC_Handle->state == MSC_IDLE))
{
return MSC_Handle->max_lun;
}
return 0xFF;
}
/**
* @brief USBH_MSC_UnitIsReady
* The function check whether a LUN is ready
* @param phost: Host handle
* @param lun: logical Unit Number
* @retval Lun status (0: not ready / 1: ready)
*/
uint8_t USBH_MSC_UnitIsReady (USBH_HandleTypeDef *phost, uint8_t lun)
{
MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData;
if(phost->gState == HOST_CLASS)
{
return (MSC_Handle->unit[lun].error == MSC_OK);
}
else
{
return 0;
}
}
/**
* @brief USBH_MSC_GetLUNInfo
* The function return a LUN information
* @param phost: Host handle
* @param lun: logical Unit Number
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_MSC_GetLUNInfo(USBH_HandleTypeDef *phost, uint8_t lun, MSC_LUNTypeDef *info)
{
MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData;
if(phost->gState == HOST_CLASS)
{
USBH_memcpy(info,&MSC_Handle->unit[lun], sizeof(MSC_LUNTypeDef));
return USBH_OK;
}
else
{
return USBH_FAIL;
}
}
/**
* @brief USBH_MSC_Read
* The function performs a Read operation
* @param phost: Host handle
* @param lun: logical Unit Number
* @param address: sector address
* @param pbuf: pointer to data
* @param length: number of sector to read
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_MSC_Read(USBH_HandleTypeDef *phost,
uint8_t lun,
uint32_t address,
uint8_t *pbuf,
uint32_t length)
{
uint32_t timeout;
MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData;
if ((phost->device.is_connected == 0) ||
(phost->gState != HOST_CLASS) ||
(MSC_Handle->unit[lun].state != MSC_IDLE))
{
return USBH_FAIL;
}
MSC_Handle->state = MSC_READ;
MSC_Handle->unit[lun].state = MSC_READ;
MSC_Handle->rw_lun = lun;
USBH_MSC_SCSI_Read(phost,
lun,
address,
pbuf,
length);
timeout = phost->Timer + (10000 * length);
while (USBH_MSC_RdWrProcess(phost, lun) == USBH_BUSY)
{
if((phost->Timer > timeout) || (phost->device.is_connected == 0))
{
MSC_Handle->state = MSC_IDLE;
return USBH_FAIL;
}
}
MSC_Handle->state = MSC_IDLE;
return USBH_OK;
}
/**
* @brief USBH_MSC_Write
* The function performs a Write operation
* @param phost: Host handle
* @param lun: logical Unit Number
* @param address: sector address
* @param pbuf: pointer to data
* @param length: number of sector to write
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_MSC_Write(USBH_HandleTypeDef *phost,
uint8_t lun,
uint32_t address,
uint8_t *pbuf,
uint32_t length)
{
uint32_t timeout;
MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData;
if ((phost->device.is_connected == 0) ||
(phost->gState != HOST_CLASS) ||
(MSC_Handle->unit[lun].state != MSC_IDLE))
{
return USBH_FAIL;
}
MSC_Handle->state = MSC_WRITE;
MSC_Handle->unit[lun].state = MSC_WRITE;
MSC_Handle->rw_lun = lun;
USBH_MSC_SCSI_Write(phost,
lun,
address,
pbuf,
length);
timeout = phost->Timer + (10000 * length);
while (USBH_MSC_RdWrProcess(phost, lun) == USBH_BUSY)
{
if((phost->Timer > timeout) || (phost->device.is_connected == 0))
{
MSC_Handle->state = MSC_IDLE;
return USBH_FAIL;
}
}
MSC_Handle->state = MSC_IDLE;
return USBH_OK;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,634 @@
/**
******************************************************************************
* @file usbh_msc_bot.c
* @author MCD Application Team
* @version V3.0.0
* @date 18-February-2014
* @brief This file includes the BOT protocol related functions
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
*
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/software_license_agreement_liberty_v2
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbh_msc_bot.h"
#include "usbh_msc.h"
/** @addtogroup USBH_LIB
* @{
*/
/** @addtogroup USBH_CLASS
* @{
*/
/** @addtogroup USBH_MSC_CLASS
* @{
*/
/** @defgroup USBH_MSC_BOT
* @brief This file includes the mass storage related functions
* @{
*/
/** @defgroup USBH_MSC_BOT_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_BOT_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_BOT_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_BOT_Private_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_BOT_Private_FunctionPrototypes
* @{
*/
static USBH_StatusTypeDef USBH_MSC_BOT_Abort(USBH_HandleTypeDef *phost, uint8_t lun, uint8_t dir);
static BOT_CSWStatusTypeDef USBH_MSC_DecodeCSW(USBH_HandleTypeDef *phost);
/**
* @}
*/
/** @defgroup USBH_MSC_BOT_Exported_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_BOT_Private_Functions
* @{
*/
/**
* @brief USBH_MSC_BOT_REQ_Reset
* The function the MSC BOT Reset request.
* @param phost: Host handle
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_MSC_BOT_REQ_Reset(USBH_HandleTypeDef *phost)
{
phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_TYPE_CLASS | \
USB_REQ_RECIPIENT_INTERFACE;
phost->Control.setup.b.bRequest = USB_REQ_BOT_RESET;
phost->Control.setup.b.wValue.w = 0;
phost->Control.setup.b.wIndex.w = 0;
phost->Control.setup.b.wLength.w = 0;
return USBH_CtlReq(phost, 0 , 0 );
}
/**
* @brief USBH_MSC_BOT_REQ_GetMaxLUN
* The function the MSC BOT GetMaxLUN request.
* @param phost: Host handle
* @param Maxlun: pointer to Maxlun variable
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_MSC_BOT_REQ_GetMaxLUN(USBH_HandleTypeDef *phost, uint8_t *Maxlun)
{
phost->Control.setup.b.bmRequestType = USB_D2H | USB_REQ_TYPE_CLASS | \
USB_REQ_RECIPIENT_INTERFACE;
phost->Control.setup.b.bRequest = USB_REQ_GET_MAX_LUN;
phost->Control.setup.b.wValue.w = 0;
phost->Control.setup.b.wIndex.w = 0;
phost->Control.setup.b.wLength.w = 1;
return USBH_CtlReq(phost, Maxlun , 1 );
}
/**
* @brief USBH_MSC_BOT_Init
* The function Initializes the BOT protocol.
* @param phost: Host handle
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_MSC_BOT_Init(USBH_HandleTypeDef *phost)
{
MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData;
MSC_Handle->hbot.cbw.field.Signature = BOT_CBW_SIGNATURE;
MSC_Handle->hbot.cbw.field.Tag = BOT_CBW_TAG;
MSC_Handle->hbot.state = BOT_SEND_CBW;
MSC_Handle->hbot.cmd_state = BOT_CMD_SEND;
return USBH_OK;
}
/**
* @brief USBH_MSC_BOT_Process
* The function handle the BOT protocol.
* @param phost: Host handle
* @param lun: Logical Unit Number
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_MSC_BOT_Process (USBH_HandleTypeDef *phost, uint8_t lun)
{
USBH_StatusTypeDef status = USBH_BUSY;
USBH_StatusTypeDef error = USBH_BUSY;
BOT_CSWStatusTypeDef CSW_Status = BOT_CSW_CMD_FAILED;
USBH_URBStateTypeDef URB_Status = USBH_URB_IDLE;
MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData;
uint8_t toggle = 0;
uint16_t USBH_URB = USBH_URB_EVENT;
switch (MSC_Handle->hbot.state)
{
case BOT_SEND_CBW:
MSC_Handle->hbot.cbw.field.LUN = lun;
MSC_Handle->hbot.state = BOT_SEND_CBW_WAIT;
USBH_BulkSendData (phost,
MSC_Handle->hbot.cbw.data,
BOT_CBW_LENGTH,
MSC_Handle->OutPipe,
1);
break;
case BOT_SEND_CBW_WAIT:
URB_Status = USBH_LL_GetURBState(phost, MSC_Handle->OutPipe);
if(URB_Status == USBH_URB_DONE)
{
if ( MSC_Handle->hbot.cbw.field.DataTransferLength != 0 )
{
/* If there is Data Transfer Stage */
if (((MSC_Handle->hbot.cbw.field.Flags) & USB_REQ_DIR_MASK) == USB_D2H)
{
/* Data Direction is IN */
MSC_Handle->hbot.state = BOT_DATA_IN;
}
else
{
/* Data Direction is OUT */
MSC_Handle->hbot.state = BOT_DATA_OUT;
}
}
else
{/* If there is NO Data Transfer Stage */
MSC_Handle->hbot.state = BOT_RECEIVE_CSW;
}
#if (USBH_USE_OS == 1)
mico_rtos_push_to_queue((mico_queue_t *) &(phost->os_event), &USBH_URB, 0 );
#endif
}
else if(URB_Status == USBH_URB_NOTREADY)
{
/* Re-send CBW */
MSC_Handle->hbot.state = BOT_SEND_CBW;
#if (USBH_USE_OS == 1)
mico_rtos_push_to_queue((mico_queue_t *) &(phost->os_event), &USBH_URB, 0 );
#endif
}
else if(URB_Status == USBH_URB_STALL)
{
MSC_Handle->hbot.state = BOT_ERROR_OUT;
#if (USBH_USE_OS == 1)
mico_rtos_push_to_queue((mico_queue_t *) &(phost->os_event), &USBH_URB, 0 );
#endif
}
break;
case BOT_DATA_IN:
/* Send first packet */
USBH_BulkReceiveData (phost,
MSC_Handle->hbot.pbuf,
MSC_Handle->InEpSize ,
MSC_Handle->InPipe);
MSC_Handle->hbot.state = BOT_DATA_IN_WAIT;
break;
case BOT_DATA_IN_WAIT:
URB_Status = USBH_LL_GetURBState(phost, MSC_Handle->InPipe);
if(URB_Status == USBH_URB_DONE)
{
/* Adjudt Data pointer and data length */
if(MSC_Handle->hbot.cbw.field.DataTransferLength > MSC_Handle->InEpSize)
{
MSC_Handle->hbot.pbuf += MSC_Handle->InEpSize;
MSC_Handle->hbot.cbw.field.DataTransferLength -= MSC_Handle->InEpSize;
}
else
{
MSC_Handle->hbot.cbw.field.DataTransferLength = 0;
}
/* More Data To be Received */
if(MSC_Handle->hbot.cbw.field.DataTransferLength > 0)
{
/* Send next packet */
USBH_BulkReceiveData (phost,
MSC_Handle->hbot.pbuf,
MSC_Handle->InEpSize ,
MSC_Handle->InPipe);
}
else
{
/* If value was 0, and successful transfer, then change the state */
MSC_Handle->hbot.state = BOT_RECEIVE_CSW;
#if (USBH_USE_OS == 1)
mico_rtos_push_to_queue((mico_queue_t *) &(phost->os_event), &USBH_URB, 0 );
#endif
}
}
else if(URB_Status == USBH_URB_STALL)
{
/* This is Data IN Stage STALL Condition */
MSC_Handle->hbot.state = BOT_ERROR_IN;
/* Refer to USB Mass-Storage Class : BOT (www.usb.org)
6.7.2 Host expects to receive data from the device
3. On a STALL condition receiving data, then:
The host shall accept the data received.
The host shall clear the Bulk-In pipe.
4. The host shall attempt to receive a CSW.*/
#if (USBH_USE_OS == 1)
mico_rtos_push_to_queue((mico_queue_t *) &(phost->os_event), &USBH_URB, 0 );
#endif
}
break;
case BOT_DATA_OUT:
USBH_BulkSendData (phost,
MSC_Handle->hbot.pbuf,
MSC_Handle->OutEpSize ,
MSC_Handle->OutPipe,
1);
MSC_Handle->hbot.state = BOT_DATA_OUT_WAIT;
break;
case BOT_DATA_OUT_WAIT:
URB_Status = USBH_LL_GetURBState(phost, MSC_Handle->OutPipe);
if(URB_Status == USBH_URB_DONE)
{
/* Adjudt Data pointer and data length */
if(MSC_Handle->hbot.cbw.field.DataTransferLength > MSC_Handle->OutEpSize)
{
MSC_Handle->hbot.pbuf += MSC_Handle->OutEpSize;
MSC_Handle->hbot.cbw.field.DataTransferLength -= MSC_Handle->OutEpSize;
}
else
{
MSC_Handle->hbot.cbw.field.DataTransferLength = 0;
}
/* More Data To be Sent */
if(MSC_Handle->hbot.cbw.field.DataTransferLength > 0)
{
USBH_BulkSendData (phost,
MSC_Handle->hbot.pbuf,
MSC_Handle->OutEpSize ,
MSC_Handle->OutPipe,
1);
}
else
{
/* If value was 0, and successful transfer, then change the state */
MSC_Handle->hbot.state = BOT_RECEIVE_CSW;
}
#if (USBH_USE_OS == 1)
mico_rtos_push_to_queue((mico_queue_t *) &(phost->os_event), &USBH_URB, 0 );
#endif
}
else if(URB_Status == USBH_URB_NOTREADY)
{
/* Re-send same data */
MSC_Handle->hbot.state = BOT_DATA_OUT;
#if (USBH_USE_OS == 1)
mico_rtos_push_to_queue((mico_queue_t *) &(phost->os_event), &USBH_URB, 0 );
#endif
}
else if(URB_Status == USBH_URB_STALL)
{
MSC_Handle->hbot.state = BOT_ERROR_OUT;
/* Refer to USB Mass-Storage Class : BOT (www.usb.org)
6.7.3 Ho - Host expects to send data to the device
3. On a STALL condition sending data, then:
" The host shall clear the Bulk-Out pipe.
4. The host shall attempt to receive a CSW.
*/
#if (USBH_USE_OS == 1)
mico_rtos_push_to_queue((mico_queue_t *) &(phost->os_event), &USBH_URB, 0 );
#endif
}
break;
case BOT_RECEIVE_CSW:
USBH_BulkReceiveData (phost,
MSC_Handle->hbot.csw.data,
BOT_CSW_LENGTH ,
MSC_Handle->InPipe);
MSC_Handle->hbot.state = BOT_RECEIVE_CSW_WAIT;
break;
case BOT_RECEIVE_CSW_WAIT:
URB_Status = USBH_LL_GetURBState(phost, MSC_Handle->InPipe);
/* Decode CSW */
if(URB_Status == USBH_URB_DONE)
{
MSC_Handle->hbot.state = BOT_SEND_CBW;
MSC_Handle->hbot.cmd_state = BOT_CMD_SEND;
CSW_Status = USBH_MSC_DecodeCSW(phost);
if(CSW_Status == BOT_CSW_CMD_PASSED)
{
status = USBH_OK;
}
else
{
status = USBH_FAIL;
}
#if (USBH_USE_OS == 1)
mico_rtos_push_to_queue((mico_queue_t *) &(phost->os_event), &USBH_URB, 0 );
#endif
}
else if(URB_Status == USBH_URB_STALL)
{
MSC_Handle->hbot.state = BOT_ERROR_IN;
#if (USBH_USE_OS == 1)
mico_rtos_push_to_queue((mico_queue_t *) &(phost->os_event), &USBH_URB, 0 );
#endif
}
break;
case BOT_ERROR_IN:
error = USBH_MSC_BOT_Abort(phost, lun, BOT_DIR_IN);
if (error == USBH_OK)
{
MSC_Handle->hbot.state = BOT_RECEIVE_CSW;
}
else if (error == USBH_UNRECOVERED_ERROR)
{
/* This means that there is a STALL Error limit, Do Reset Recovery */
MSC_Handle->hbot.state = BOT_UNRECOVERED_ERROR;
}
break;
case BOT_ERROR_OUT:
error = USBH_MSC_BOT_Abort(phost, lun, BOT_DIR_OUT);
if ( error == USBH_OK)
{
toggle = USBH_LL_GetToggle(phost, MSC_Handle->OutPipe);
USBH_LL_SetToggle(phost, MSC_Handle->OutPipe, 1- toggle);
USBH_LL_SetToggle(phost, MSC_Handle->InPipe, 0);
MSC_Handle->hbot.state = BOT_ERROR_IN;
}
else if (error == USBH_UNRECOVERED_ERROR)
{
MSC_Handle->hbot.state = BOT_UNRECOVERED_ERROR;
}
break;
case BOT_UNRECOVERED_ERROR:
status = USBH_MSC_BOT_REQ_Reset(phost);
if ( status == USBH_OK)
{
MSC_Handle->hbot.state = BOT_SEND_CBW;
}
break;
default:
break;
}
return status;
}
/**
* @brief USBH_MSC_BOT_Abort
* The function handle the BOT Abort process.
* @param phost: Host handle
* @param lun: Logical Unit Number
* @param dir: direction (0: out / 1 : in)
* @retval USBH Status
*/
static USBH_StatusTypeDef USBH_MSC_BOT_Abort(USBH_HandleTypeDef *phost, uint8_t lun, uint8_t dir)
{
USBH_StatusTypeDef status = USBH_FAIL;
MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData;
switch (dir)
{
case BOT_DIR_IN :
/* send ClrFeture on Bulk IN endpoint */
status = USBH_ClrFeature(phost, MSC_Handle->InEp);
break;
case BOT_DIR_OUT :
/*send ClrFeature on Bulk OUT endpoint */
status = USBH_ClrFeature(phost, MSC_Handle->OutEp);
break;
default:
break;
}
return status;
}
/**
* @brief USBH_MSC_BOT_DecodeCSW
* This function decodes the CSW received by the device and updates the
* same to upper layer.
* @param phost: Host handle
* @retval USBH Status
* @notes
* Refer to USB Mass-Storage Class : BOT (www.usb.org)
* 6.3.1 Valid CSW Conditions :
* The host shall consider the CSW valid when:
* 1. dCSWSignature is equal to 53425355h
* 2. the CSW is 13 (Dh) bytes in length,
* 3. dCSWTag matches the dCBWTag from the corresponding CBW.
*/
static BOT_CSWStatusTypeDef USBH_MSC_DecodeCSW(USBH_HandleTypeDef *phost)
{
MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData;
BOT_CSWStatusTypeDef status = BOT_CSW_CMD_FAILED;
/*Checking if the transfer length is diffrent than 13*/
if(USBH_LL_GetLastXferSize(phost, MSC_Handle->InPipe) != BOT_CSW_LENGTH)
{
/*(4) Hi > Dn (Host expects to receive data from the device,
Device intends to transfer no data)
(5) Hi > Di (Host expects to receive data from the device,
Device intends to send data to the host)
(9) Ho > Dn (Host expects to send data to the device,
Device intends to transfer no data)
(11) Ho > Do (Host expects to send data to the device,
Device intends to receive data from the host)*/
status = BOT_CSW_PHASE_ERROR;
}
else
{ /* CSW length is Correct */
/* Check validity of the CSW Signature and CSWStatus */
if(MSC_Handle->hbot.csw.field.Signature == BOT_CSW_SIGNATURE)
{/* Check Condition 1. dCSWSignature is equal to 53425355h */
if(MSC_Handle->hbot.csw.field.Tag == MSC_Handle->hbot.cbw.field.Tag)
{
/* Check Condition 3. dCSWTag matches the dCBWTag from the
corresponding CBW */
if(MSC_Handle->hbot.csw.field.Status == 0)
{
/* Refer to USB Mass-Storage Class : BOT (www.usb.org)
Hn Host expects no data transfers
Hi Host expects to receive data from the device
Ho Host expects to send data to the device
Dn Device intends to transfer no data
Di Device intends to send data to the host
Do Device intends to receive data from the host
Section 6.7
(1) Hn = Dn (Host expects no data transfers,
Device intends to transfer no data)
(6) Hi = Di (Host expects to receive data from the device,
Device intends to send data to the host)
(12) Ho = Do (Host expects to send data to the device,
Device intends to receive data from the host)
*/
status = BOT_CSW_CMD_PASSED;
}
else if(MSC_Handle->hbot.csw.field.Status == 1)
{
status = BOT_CSW_CMD_FAILED;
}
else if(MSC_Handle->hbot.csw.field.Status == 2)
{
/* Refer to USB Mass-Storage Class : BOT (www.usb.org)
Section 6.7
(2) Hn < Di ( Host expects no data transfers,
Device intends to send data to the host)
(3) Hn < Do ( Host expects no data transfers,
Device intends to receive data from the host)
(7) Hi < Di ( Host expects to receive data from the device,
Device intends to send data to the host)
(8) Hi <> Do ( Host expects to receive data from the device,
Device intends to receive data from the host)
(10) Ho <> Di (Host expects to send data to the device,
Di Device intends to send data to the host)
(13) Ho < Do (Host expects to send data to the device,
Device intends to receive data from the host)
*/
status = BOT_CSW_PHASE_ERROR;
}
} /* CSW Tag Matching is Checked */
} /* CSW Signature Correct Checking */
else
{
/* If the CSW Signature is not valid, We sall return the Phase Error to
Upper Layers for Reset Recovery */
status = BOT_CSW_PHASE_ERROR;
}
} /* CSW Length Check*/
return status;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,458 @@
/**
******************************************************************************
* @file usbh_msc_scsi.c
* @author MCD Application Team
* @version V3.0.0
* @date 18-February-2014
* @brief This file implements the SCSI commands
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
*
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/software_license_agreement_liberty_v2
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbh_msc.h"
#include "usbh_msc_scsi.h"
#include "usbh_msc_bot.h"
/** @addtogroup USBH_LIB
* @{
*/
/** @addtogroup USBH_CLASS
* @{
*/
/** @addtogroup USBH_MSC_CLASS
* @{
*/
/** @defgroup USBH_MSC_SCSI
* @brief This file includes the mass storage related functions
* @{
*/
/** @defgroup USBH_MSC_SCSI_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_SCSI_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_SCSI_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_SCSI_Private_FunctionPrototypes
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_SCSI_Exported_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_SCSI_Private_Functions
* @{
*/
/**
* @brief USBH_MSC_SCSI_TestUnitReady
* Issue TestUnitReady command.
* @param phost: Host handle
* @param lun: Logical Unit Number
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_MSC_SCSI_TestUnitReady (USBH_HandleTypeDef *phost,
uint8_t lun)
{
USBH_StatusTypeDef error = USBH_FAIL ;
MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData;
switch(MSC_Handle->hbot.cmd_state)
{
case BOT_CMD_SEND:
/*Prepare the CBW and relevent field*/
MSC_Handle->hbot.cbw.field.DataTransferLength = DATA_LEN_MODE_TEST_UNIT_READY;
MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_OUT;
MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH;
USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_CB_LENGTH);
MSC_Handle->hbot.cbw.field.CB[0] = OPCODE_TEST_UNIT_READY;
MSC_Handle->hbot.state = BOT_SEND_CBW;
MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT;
error = USBH_BUSY;
break;
case BOT_CMD_WAIT:
error = USBH_MSC_BOT_Process(phost, lun);
break;
default:
break;
}
return error;
}
/**
* @brief USBH_MSC_SCSI_ReadCapacity
* Issue Read Capacity command.
* @param phost: Host handle
* @param lun: Logical Unit Number
* @param capacity: pointer to the capacity structure
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_MSC_SCSI_ReadCapacity (USBH_HandleTypeDef *phost,
uint8_t lun,
SCSI_CapacityTypeDef *capacity)
{
USBH_StatusTypeDef error = USBH_BUSY ;
MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData;
switch(MSC_Handle->hbot.cmd_state)
{
case BOT_CMD_SEND:
/*Prepare the CBW and relevent field*/
MSC_Handle->hbot.cbw.field.DataTransferLength = DATA_LEN_READ_CAPACITY10;
MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_IN;
MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH;
USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_CB_LENGTH);
MSC_Handle->hbot.cbw.field.CB[0] = OPCODE_READ_CAPACITY10;
MSC_Handle->hbot.state = BOT_SEND_CBW;
MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT;
MSC_Handle->hbot.pbuf = (uint8_t *)MSC_Handle->hbot.data;
error = USBH_BUSY;
break;
case BOT_CMD_WAIT:
error = USBH_MSC_BOT_Process(phost, lun);
if(error == USBH_OK)
{
/*assign the capacity*/
capacity->block_nbr = MSC_Handle->hbot.pbuf[3] | (MSC_Handle->hbot.pbuf[2] << 8) |\
(MSC_Handle->hbot.pbuf[1] << 16) | (MSC_Handle->hbot.pbuf[0] << 24);
/*assign the page length*/
capacity->block_size = MSC_Handle->hbot.pbuf[7] | (MSC_Handle->hbot.pbuf[6] << 8);
}
break;
default:
break;
}
return error;
}
/**
* @brief USBH_MSC_SCSI_Inquiry
* Issue Inquiry command.
* @param phost: Host handle
* @param lun: Logical Unit Number
* @param capacity: pointer to the inquiry structure
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_MSC_SCSI_Inquiry (USBH_HandleTypeDef *phost,
uint8_t lun,
SCSI_StdInquiryDataTypeDef *inquiry)
{
USBH_StatusTypeDef error = USBH_FAIL ;
MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData;
switch(MSC_Handle->hbot.cmd_state)
{
case BOT_CMD_SEND:
/*Prepare the CBW and relevent field*/
MSC_Handle->hbot.cbw.field.DataTransferLength = DATA_LEN_INQUIRY;
MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_IN;
MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH;
USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_LENGTH);
MSC_Handle->hbot.cbw.field.CB[0] = OPCODE_INQUIRY;
MSC_Handle->hbot.cbw.field.CB[1] = (lun << 5);
MSC_Handle->hbot.cbw.field.CB[2] = 0;
MSC_Handle->hbot.cbw.field.CB[3] = 0;
MSC_Handle->hbot.cbw.field.CB[4] = 0x24;
MSC_Handle->hbot.cbw.field.CB[5] = 0;
MSC_Handle->hbot.state = BOT_SEND_CBW;
MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT;
MSC_Handle->hbot.pbuf = (uint8_t *)MSC_Handle->hbot.data;
error = USBH_BUSY;
break;
case BOT_CMD_WAIT:
error = USBH_MSC_BOT_Process(phost, lun);
if(error == USBH_OK)
{
USBH_memset(inquiry, 0, sizeof(SCSI_StdInquiryDataTypeDef));
/*assign Inquiry Data */
inquiry->DeviceType = MSC_Handle->hbot.pbuf[0] & 0x1F;
inquiry->PeripheralQualifier = MSC_Handle->hbot.pbuf[0] >> 5;
inquiry->RemovableMedia = (MSC_Handle->hbot.pbuf[1] & 0x80)== 0x80;
USBH_memcpy (inquiry->vendor_id, &MSC_Handle->hbot.pbuf[8], 8);
USBH_memcpy (inquiry->product_id, &MSC_Handle->hbot.pbuf[16], 16);
USBH_memcpy (inquiry->revision_id, &MSC_Handle->hbot.pbuf[32], 4);
}
break;
default:
break;
}
return error;
}
/**
* @brief USBH_MSC_SCSI_RequestSense
* Issue RequestSense command.
* @param phost: Host handle
* @param lun: Logical Unit Number
* @param capacity: pointer to the sense data structure
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_MSC_SCSI_RequestSense (USBH_HandleTypeDef *phost,
uint8_t lun,
SCSI_SenseTypeDef *sense_data)
{
USBH_StatusTypeDef error = USBH_FAIL ;
MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData;
switch(MSC_Handle->hbot.cmd_state)
{
case BOT_CMD_SEND:
/*Prepare the CBW and relevent field*/
MSC_Handle->hbot.cbw.field.DataTransferLength = DATA_LEN_REQUEST_SENSE;
MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_IN;
MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH;
USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_CB_LENGTH);
MSC_Handle->hbot.cbw.field.CB[0] = OPCODE_REQUEST_SENSE;
MSC_Handle->hbot.cbw.field.CB[1] = (lun << 5);
MSC_Handle->hbot.cbw.field.CB[2] = 0;
MSC_Handle->hbot.cbw.field.CB[3] = 0;
MSC_Handle->hbot.cbw.field.CB[4] = DATA_LEN_REQUEST_SENSE;
MSC_Handle->hbot.cbw.field.CB[5] = 0;
MSC_Handle->hbot.state = BOT_SEND_CBW;
MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT;
MSC_Handle->hbot.pbuf = (uint8_t *)MSC_Handle->hbot.data;
error = USBH_BUSY;
break;
case BOT_CMD_WAIT:
error = USBH_MSC_BOT_Process(phost, lun);
if(error == USBH_OK)
{
sense_data->key = MSC_Handle->hbot.pbuf[2] & 0x0F;
sense_data->asc = MSC_Handle->hbot.pbuf[12];
sense_data->ascq = MSC_Handle->hbot.pbuf[13];
}
break;
default:
break;
}
return error;
}
/**
* @brief USBH_MSC_SCSI_Write
* Issue write10 command.
* @param phost: Host handle
* @param lun: Logical Unit Number
* @param address: sector address
* @param pbuf: pointer to data
* @param length: number of sector to write
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_MSC_SCSI_Write(USBH_HandleTypeDef *phost,
uint8_t lun,
uint32_t address,
uint8_t *pbuf,
uint32_t length)
{
USBH_StatusTypeDef error = USBH_FAIL ;
MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData;
switch(MSC_Handle->hbot.cmd_state)
{
case BOT_CMD_SEND:
/*Prepare the CBW and relevent field*/
MSC_Handle->hbot.cbw.field.DataTransferLength = length * 512;
MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_OUT;
MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH;
USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_CB_LENGTH);
MSC_Handle->hbot.cbw.field.CB[0] = OPCODE_WRITE10;
/*logical block address*/
MSC_Handle->hbot.cbw.field.CB[2] = (((uint8_t*)&address)[3]);
MSC_Handle->hbot.cbw.field.CB[3] = (((uint8_t*)&address)[2]);
MSC_Handle->hbot.cbw.field.CB[4] = (((uint8_t*)&address)[1]);
MSC_Handle->hbot.cbw.field.CB[5] = (((uint8_t*)&address)[0]);
/*Tranfer length */
MSC_Handle->hbot.cbw.field.CB[7] = (((uint8_t *)&length)[1]) ;
MSC_Handle->hbot.cbw.field.CB[8] = (((uint8_t *)&length)[0]) ;
MSC_Handle->hbot.state = BOT_SEND_CBW;
MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT;
MSC_Handle->hbot.pbuf = pbuf;
error = USBH_BUSY;
break;
case BOT_CMD_WAIT:
error = USBH_MSC_BOT_Process(phost, lun);
break;
default:
break;
}
return error;
}
/**
* @brief USBH_MSC_SCSI_Read
* Issue Read10 command.
* @param phost: Host handle
* @param lun: Logical Unit Number
* @param address: sector address
* @param pbuf: pointer to data
* @param length: number of sector to read
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_MSC_SCSI_Read(USBH_HandleTypeDef *phost,
uint8_t lun,
uint32_t address,
uint8_t *pbuf,
uint32_t length)
{
USBH_StatusTypeDef error = USBH_FAIL ;
MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData;
switch(MSC_Handle->hbot.cmd_state)
{
case BOT_CMD_SEND:
/*Prepare the CBW and relevent field*/
MSC_Handle->hbot.cbw.field.DataTransferLength = length * 512;
MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_IN;
MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH;
USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_CB_LENGTH);
MSC_Handle->hbot.cbw.field.CB[0] = OPCODE_READ10;
/*logical block address*/
MSC_Handle->hbot.cbw.field.CB[2] = (((uint8_t*)&address)[3]);
MSC_Handle->hbot.cbw.field.CB[3] = (((uint8_t*)&address)[2]);
MSC_Handle->hbot.cbw.field.CB[4] = (((uint8_t*)&address)[1]);
MSC_Handle->hbot.cbw.field.CB[5] = (((uint8_t*)&address)[0]);
/*Tranfer length */
MSC_Handle->hbot.cbw.field.CB[7] = (((uint8_t *)&length)[1]) ;
MSC_Handle->hbot.cbw.field.CB[8] = (((uint8_t *)&length)[0]) ;
MSC_Handle->hbot.state = BOT_SEND_CBW;
MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT;
MSC_Handle->hbot.pbuf = pbuf;
error = USBH_BUSY;
break;
case BOT_CMD_WAIT:
error = USBH_MSC_BOT_Process(phost, lun);
break;
default:
break;
}
return error;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/