diff options
Diffstat (limited to 'stmhal/usbhost/Class/MSC')
-rw-r--r-- | stmhal/usbhost/Class/MSC/Inc/usbh_msc.h | 222 | ||||
-rw-r--r-- | stmhal/usbhost/Class/MSC/Inc/usbh_msc_bot.h | 233 | ||||
-rw-r--r-- | stmhal/usbhost/Class/MSC/Inc/usbh_msc_scsi.h | 218 | ||||
-rw-r--r-- | stmhal/usbhost/Class/MSC/Src/usbh_msc.c | 795 | ||||
-rw-r--r-- | stmhal/usbhost/Class/MSC/Src/usbh_msc_bot.c | 633 | ||||
-rw-r--r-- | stmhal/usbhost/Class/MSC/Src/usbh_msc_scsi.c | 458 |
6 files changed, 2559 insertions, 0 deletions
diff --git a/stmhal/usbhost/Class/MSC/Inc/usbh_msc.h b/stmhal/usbhost/Class/MSC/Inc/usbh_msc.h new file mode 100644 index 0000000000..ea173a7da8 --- /dev/null +++ b/stmhal/usbhost/Class/MSC/Inc/usbh_msc.h @@ -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****/
+
+
+
diff --git a/stmhal/usbhost/Class/MSC/Inc/usbh_msc_bot.h b/stmhal/usbhost/Class/MSC/Inc/usbh_msc_bot.h new file mode 100644 index 0000000000..5422c80eb7 --- /dev/null +++ b/stmhal/usbhost/Class/MSC/Inc/usbh_msc_bot.h @@ -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****/
+
diff --git a/stmhal/usbhost/Class/MSC/Inc/usbh_msc_scsi.h b/stmhal/usbhost/Class/MSC/Inc/usbh_msc_scsi.h new file mode 100644 index 0000000000..76b51902a1 --- /dev/null +++ b/stmhal/usbhost/Class/MSC/Inc/usbh_msc_scsi.h @@ -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****/
+
diff --git a/stmhal/usbhost/Class/MSC/Src/usbh_msc.c b/stmhal/usbhost/Class/MSC/Src/usbh_msc.c new file mode 100644 index 0000000000..53a2cd81df --- /dev/null +++ b/stmhal/usbhost/Class/MSC/Src/usbh_msc.c @@ -0,0 +1,795 @@ +/**
+ ******************************************************************************
+ * @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
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+/** @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)
+ osMessagePut ( phost->os_event, USBH_CLASS_EVENT, 0);
+#endif
+ }
+ else
+ {
+ MSC_Handle->current_lun = 0;
+ MSC_Handle->state = MSC_IDLE;
+#if (USBH_USE_OS == 1)
+ osMessagePut ( phost->os_event, USBH_CLASS_EVENT, 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)
+ osMessagePut ( phost->os_event, USBH_CLASS_EVENT, 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)
+ osMessagePut ( phost->os_event, USBH_CLASS_EVENT, 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)
+ osMessagePut ( phost->os_event, USBH_CLASS_EVENT, 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****/
diff --git a/stmhal/usbhost/Class/MSC/Src/usbh_msc_bot.c b/stmhal/usbhost/Class/MSC/Src/usbh_msc_bot.c new file mode 100644 index 0000000000..5489ce2978 --- /dev/null +++ b/stmhal/usbhost/Class/MSC/Src/usbh_msc_bot.c @@ -0,0 +1,633 @@ +/**
+ ******************************************************************************
+ * @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;
+
+ 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)
+ osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
+#endif
+
+ }
+ else if(URB_Status == USBH_URB_NOTREADY)
+ {
+ /* Re-send CBW */
+ MSC_Handle->hbot.state = BOT_SEND_CBW;
+#if (USBH_USE_OS == 1)
+ osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
+#endif
+ }
+ else if(URB_Status == USBH_URB_STALL)
+ {
+ MSC_Handle->hbot.state = BOT_ERROR_OUT;
+#if (USBH_USE_OS == 1)
+ osMessagePut ( phost->os_event, USBH_URB_EVENT, 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)
+ osMessagePut ( phost->os_event, USBH_URB_EVENT, 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)
+ osMessagePut ( phost->os_event, USBH_URB_EVENT, 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)
+ osMessagePut ( phost->os_event, USBH_URB_EVENT, 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)
+ osMessagePut ( phost->os_event, USBH_URB_EVENT, 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)
+ osMessagePut ( phost->os_event, USBH_URB_EVENT, 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)
+ osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
+#endif
+ }
+ else if(URB_Status == USBH_URB_STALL)
+ {
+ MSC_Handle->hbot.state = BOT_ERROR_IN;
+#if (USBH_USE_OS == 1)
+ osMessagePut ( phost->os_event, USBH_URB_EVENT, 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****/
+
+
+
diff --git a/stmhal/usbhost/Class/MSC/Src/usbh_msc_scsi.c b/stmhal/usbhost/Class/MSC/Src/usbh_msc_scsi.c new file mode 100644 index 0000000000..5d069b40a8 --- /dev/null +++ b/stmhal/usbhost/Class/MSC/Src/usbh_msc_scsi.c @@ -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****/
+
+
+
|