mirror of
https://github.com/oopuuu/zTC1.git
synced 2025-12-19 08:23:22 +08:00
修改了Web后台的部分界面,增加了HAmqtt中的总电量传感器,后台新增mqtt上报频率设置
This commit is contained in:
@@ -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>© 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****/
|
||||
|
||||
|
||||
|
||||
@@ -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>© 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****/
|
||||
|
||||
@@ -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>© 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****/
|
||||
|
||||
@@ -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>© 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****/
|
||||
@@ -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>© 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****/
|
||||
|
||||
|
||||
|
||||
@@ -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>© 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****/
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user