1 /*
2  * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016 - 2023 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #ifndef __USB_DEVICE_MSC_H__
10 #define __USB_DEVICE_MSC_H__
11 
12 #include "usb_device_msc_ufi.h"
13 /*!
14  * @addtogroup usb_msc
15  * @{
16  */
17 /*! @brief prevent media removal flag */
18 #define USB_DEVICE_CONFIG_MSC_SUPPORT_DISK_LOCKING_MECHANISM (0U)
19 #define USB_DEVICE_CONFIG_MSC_IMPLEMENTING_DISK_DRIVE (0U)
20 /*! @brief The class code of the MSC class */
21 #define USB_DEVICE_CONFIG_MSC_CLASS_CODE (0x08U)
22 
23 /*! @brief Bulk-Only Mass Storage Reset (class-specific request) */
24 #define USB_DEVICE_MSC_BULK_ONLY_MASS_STORAGE_RESET (0xFFU)
25 /*! @brief Get Maximum LUN (class-specific request) */
26 #define USB_DEVICE_MSC_GET_MAX_LUN (0xFEU)
27 
28 /*! @brief CBW dCBWSignature*/
29 #define USB_DEVICE_MSC_DCBWSIGNATURE USB_LONG_TO_BIG_ENDIAN(0x55534243UL)
30 /*! @brief CSW dCSSWSignature*/
31 #define USB_DEVICE_MSC_DCSWSIGNATURE USB_LONG_TO_BIG_ENDIAN(0x55534253UL)
32 /*! @brief CSW bmCBWFlags bit7 */
33 #define USB_DEVICE_MSC_CBW_DIRECTION_BIT (0x80U)
34 #define USB_DEVICE_MSC_CBW_DIRECTION_SHIFT (7U)
35 /*! @brief CBW command length*/
36 #define USB_DEVICE_MSC_CBW_LENGTH (31U)
37 /*! @brief CSW command length*/
38 #define USB_DEVICE_MSC_CSW_LENGTH (13U)
39 /*! @brief Command Block Status Values*/
40 #define USB_DEVICE_MSC_COMMAND_PASSED (0x00U)
41 #define USB_DEVICE_MSC_COMMAND_FAILED (0x01U)
42 #define USB_DEVICE_MSC_PHASE_ERROR (0x02U)
43 /*! @brief UFI Commands code*/
44 #define USB_DEVICE_MSC_INQUIRY_COMMAND (0x12U)
45 #define USB_DEVICE_MSC_READ_10_COMMAND (0x28U)
46 #define USB_DEVICE_MSC_READ_12_COMMAND (0xA8U)
47 #define USB_DEVICE_MSC_REQUEST_SENSE_COMMAND (0x03U)
48 #define USB_DEVICE_MSC_TEST_UNIT_READY_COMMAND (0x00U)
49 #define USB_DEVICE_MSC_WRITE_10_COMMAND (0x2AU)
50 #define USB_DEVICE_MSC_WRITE_12_COMMAND (0xAAU)
51 #define USB_DEVICE_MSC_PREVENT_ALLOW_MEDIUM_REM_COMMAND (0x1EU)
52 #define USB_DEVICE_MSC_FORMAT_UNIT_COMMAND (0x04U)
53 #define USB_DEVICE_MSC_READ_CAPACITY_10_COMMAND (0x25U)
54 #define USB_DEVICE_MSC_READ_CAPACITY_16_COMMAND (0x9EU)
55 #define USB_DEVICE_MSC_READ_FORMAT_CAPACITIES_COMMAND (0x23U)
56 #define USB_DEVICE_MSC_MODE_SENSE_10_COMMAND (0x5AU)
57 #define USB_DEVICE_MSC_MODE_SENSE_6_COMMAND (0x1AU)
58 #define USB_DEVICE_MSC_MODE_SELECT_10_COMMAND (0x55U)
59 #define USB_DEVICE_MSC_MODE_SELECT_6_COMMAND (0x15U)
60 #define USB_DEVICE_MSC_SEND_DIAGNOSTIC_COMMAND (0x1DU)
61 #define USB_DEVICE_MSC_VERIFY_COMMAND (0x2FU)
62 #define USB_DEVICE_MSC_START_STOP_UNIT_COMMAND (0x1BU)
63 
64 /*Max transfer length */
65 #define USB_DEVICE_MSC_MAX_RECV_TRANSFER_LENGTH (65536U)
66 #define USB_DEVICE_MSC_MAX_SEND_TRANSFER_LENGTH (65536U)
67 
68 #define USB_DEVICE_MSC_MAX_LUN (3U)
69 
70 /*! @brief Command Block Wrapper(CBW) */
71 typedef struct _usb_device_msc_cbw
72 {
73     uint32_t signature;          /*!< Byte 0-3 dCBWSignature*/
74     uint32_t tag;                /*!< Byte 4-7 dCBWTag*/
75     uint32_t dataTransferLength; /*!< Byte 8-11 dCBWDataTransferLength*/
76     uint8_t flags;               /*!< Byte 12 bmCBWFlags*/
77     uint8_t logicalUnitNumber;   /*!< Byte 13 bCBWLUN*/
78     uint8_t cbLength;            /*!< Byte 14 bCBWCBLength*/
79     uint8_t cbwcb[16];           /*!< Byte 15-30 CBWCB, CBWCB is used to store UFI command*/
80 } usb_device_msc_cbw_t;
81 /*! @brief Command Status Wrapper(CSW) */
82 typedef struct _usb_device_msc_csw
83 {
84     uint32_t signature;   /*!< Byte 0-3 dCSWSignature*/
85     uint32_t tag;         /*!< Byte 4-7 dCSWTag*/
86     uint32_t dataResidue; /*!< Byte 8-11 dCSWDataResidue*/
87     uint8_t cswStatus;    /*!< Byte 12 bCSWStatus*/
88 } usb_device_msc_csw_t;
89 /*! @brief Read/write information */
90 typedef struct _usb_lba_transfer_information_struct
91 {
92     uint32_t startingLogicalBlockAddress; /*!< The logical block at which the read/write operation shall begin*/
93     uint32_t transferNumber; /*!< The number of contiguous logical blocks of data that shall be transferred*/
94 } usb_lba_transfer_information_struct_t;
95 /*! @brief device information */
96 typedef struct _usb_device_logical_unit_information_struct
97 {
98     uint32_t totalLbaNumberSupports; /*!< Total blocks number supported*/
99     uint32_t lengthOfEachLba;        /*!< Length of each block*/
100     uint32_t bulkInBufferSize;       /*!< Bulk in buffer size*/
101     uint32_t bulkOutBufferSize;      /*!< Bulk out buffer size*/
102 } usb_device_logical_unit_information_struct_t;
103 /*! @brief device information */
104 typedef struct _usb_device_lba_information_struct
105 {
106     uint32_t logicalUnitNumberSupported; /*!< Number of LUN*/
107     usb_device_logical_unit_information_struct_t logicalUnitInformations[USB_DEVICE_MSC_MAX_LUN];
108 } usb_device_lba_information_struct_t;
109 typedef struct _usb_device_capacity_information_struct
110 {
111     uint32_t totalLbaNumberSupports; /*!< Total blocks number supported*/
112     uint32_t lengthOfEachLba;        /*!< Length of each block*/
113     uint8_t logicalUnitNumber;       /*!< Logical Unit Number*/
114 } usb_device_capacity_information_struct_t;
115 
116 /*! @brief Data transfer information */
117 typedef struct _usb_device_lba_app_struct
118 {
119     uint32_t offset; /*!< Offset of the block need to access*/
120     uint32_t size;   /*!< Size of the transferred data*/
121     uint8_t *buffer; /*!< Buffer address of the transferred data*/
122     uint8_t lun;
123 } usb_device_lba_app_struct_t;
124 /*! @brief command and Data transfer information for UFI command*/
125 typedef struct _usb_device_ufi_app_struct
126 {
127     uint8_t *cbwcb;  /*!< current ufi command block strored in the CBW*/
128     uint32_t size;   /*!< Size of the transferred data if commmand has data flow*/
129     uint8_t *buffer; /*!< Buffer address of the transferred data if commmand has data flow*/
130     usb_device_request_sense_data_struct_t *requestSense; /*!< sense data for the current command*/
131     uint8_t logicalUnitNumber;                            /*!< Logical Unit Number*/
132 } usb_device_ufi_app_struct_t;
133 /*! @brief The thirteen possible use cases of host expectations and device intent in the absence of
134 overriding error conditions. */
135 typedef struct _usb_device_msc_thirteen_case_struct
136 {
137     uint32_t hostExpectedDataLength;   /*!< The number of bytes of data that the host expects to transfer */
138     uint32_t deviceExpectedDataLength; /*!< The number of bytes of data that the device expects to transfer */
139     uint8_t *buffer;                   /*!< Data buffer*/
140     usb_lba_transfer_information_struct_t lbaInformation; /*!< Read/write information*/
141     uint8_t lbaSendRecvSelect;                            /*!< Whether the command is read or write command*/
142     uint8_t hostExpectedDirection;                        /*!< Host expected data direction*/
143     uint8_t deviceExpectedDirection;                      /*!< Device expected data direction*/
144 } usb_device_msc_thirteen_case_struct_t;
145 /*! @brief stall flag */
146 typedef enum
147 {
148     USB_DEVICE_MSC_STALL_IN_CBW = 1U, /*!< Stall in CBW*/
149     USB_DEVICE_MSC_STALL_IN_DATA,     /*!< Stall in data transfer*/
150     USB_DEVICE_MSC_STALL_IN_CSW,      /*!< Stall in CSW*/
151 } usb_device_msc_stall_type;
152 /*! @brief Available common EVENT types in MSC class callback */
153 typedef enum
154 {
155     kUSB_DeviceMscEventReadResponse =
156         0x01U, /*!< host has already read the whole data from device or device send is cancelled etc*/
157     kUSB_DeviceMscEventWriteResponse, /*!< devcie has already received the data from host or device receive is cancelled
158                                          etc. */
159     kUSB_DeviceMscEventWriteRequest,  /*!< Host want to write data to device through write command, devcie need prepare
160                                          one buffer to store the data from host*/
161     kUSB_DeviceMscEventReadRequest,   /*!< Host want to read data from device through read command, device need prepare
162                                          one buffer containing data pending for transfer*/
163     kUSB_DeviceMscEventGetLbaInformation, /*!< Get device information */
164     kUSB_DeviceMscEventFormatComplete,    /*!< Format complete */
165     kUSB_DeviceMscEventTestUnitReady,     /*!<  Test Unit Ready command*/
166     kUSB_DeviceMscEventInquiry,           /*!<  Inquiry Command command*/
167     kUSB_DeviceMscEventModeSense,         /*!<  mode sense command*/
168     kUSB_DeviceMscEventModeSelect, /*!<  mode select command, prepare data buffer and buffer length to store data for
169                                       mode select*/
170     kUSB_DeviceMscEventModeSelectResponse, /*!<  got data of mode select command*/
171     kUSB_DeviceMscEventRemovalRequest,     /*!< Prevent_allow_medium_command */
172     kUSB_DeviceMscEventSendDiagnostic,     /*!< Send Diagnostic command */
173     kUSB_DeviceMscEventStopEjectMedia,     /*!< Start_stop_unit_command */
174     kUSB_DeviceMscEventRequestSense,       /*!< Request Sense command */
175     kUSB_DeviceMscEventReadCapacity,       /*!< ReadCapacity command */
176     kUSB_DeviceMscEventReadFormatCapacity, /*!< Read Format Capacity command */
177 } USB_DeviceMscEvent_t;
178 /*! @brief The MSC device UFI command status structure */
179 typedef struct _usb_device_msc_ufi_struct
180 {
181     usb_device_request_sense_data_struct_t *requestSense;            /*!< Request Sense Standard Data*/
182     usb_device_msc_thirteen_case_struct_t thirteenCase;              /*!< Thirteen possible cases*/
183     usb_device_read_capacity_struct_t *readCapacity;                 /*!< READ CAPACITY Data*/
184     usb_device_read_capacity16_data_struct_t *readCapacity16;        /*!< READ CAPACITY Data*/
185     usb_device_mode_parameters_header_struct_t ModeParametersHeader; /*!< Mode Parameter Header*/
186     uint8_t formattedDisk;                                           /*!< *Formatted or unformatted media*/
187     uint8_t *formatCapacityData;
188     /*!< Capacity List*/
189 } usb_device_msc_ufi_struct_t;
190 /*! @brief The MSC device structure */
191 typedef struct _usb_device_msc_struct
192 {
193     usb_device_handle handle;                              /*!< The device handle */
194     usb_device_class_config_struct_t *configurationStruct; /*!< The configuration of the class*/
195     usb_device_interface_struct_t *interfaceHandle;        /*!< Current interface handle */
196     uint32_t transferRemaining;                            /*!< Transfer remaining data */
197     uint32_t currentOffset;                                /*!< Current address offset */
198     uint32_t implementingDiskDrive;                        /*!< Disk drive*/
199 
200     usb_device_msc_cbw_t *mscCbw; /*!< CBW structure */
201     usb_device_msc_csw_t *mscCsw; /*!< CSW structure */
202 
203     usb_device_msc_ufi_struct_t mscUfi; /*!< UFI command information structure*/
204 
205     usb_device_logical_unit_information_struct_t luInformations[USB_DEVICE_MSC_MAX_LUN];
206 
207     uint8_t dataOutFlag;          /*!< CBW indicating bulk out transfer, clear this flag when data transfer done*/
208     uint8_t dataInFlag;           /*!< CBW indicating bulk in transfer, clear this flag when data transfer done*/
209     uint8_t inEndpointStallFlag;  /*!< In endpoint stall flag*/
210     uint8_t outEndpointStallFlag; /*!< Out endpoint stall flag*/
211     uint8_t cbwValidFlag; /*!< The CBW was received after the device had sent a CSW or after a reset ,or else it is
212                              invalid*/
213     uint8_t performResetRecover;  /*!< Device need reset command from host*/
214     uint8_t performResetDoneFlag; /*!< Device has perform reset command */
215     uint8_t needInStallFlag;      /*!< In endpoint should be stalled*/
216     uint8_t needOutStallFlag;     /*!< Out endpoint should be stalled*/
217     uint8_t cbwPrimeFlag; /*!< CBW prime flag, prime means device MSC has been ready to receive CBW, the bulk out
218                              endpoint has got the prepared buffer*/
219     uint8_t cswPrimeFlag; /*!< CSW prime flag, prime means device MSC has been ready to receive CSW, the bulk in
220                              endpoint has got the prepared buffer*/
221     uint8_t stallStatus;  /*!< Stall status*/
222 
223     uint8_t logicalUnitNumber;       /*!< Supported logical units number of device. See bulk only specification 3.2 Get
224                                         Maximum LUN
225                                         (class-specific request)*/
226     uint8_t bulkInEndpoint;          /*!< Bulk in endpoint number*/
227     uint8_t bulkOutEndpoint;         /*!< Bulk out endpoint number*/
228     uint8_t alternate;               /*!< Current alternate setting of the interface */
229     uint8_t configuration;           /*!< Current configuration */
230     uint8_t interfaceNumber;         /*!< The interface number of the class */
231     uint8_t inEndpointCswCancelFlag; /*!< the state when calcel function happens, and need send the csw after cancel*/
232 } usb_device_msc_struct_t;
233 #ifdef __cplusplus
234 extern "C" {
235 #endif
236 
237 /*!
238  * @name USB device MSC class APIs
239  * @{
240  */
241 /*!
242  * @brief Initializes the MSC class.
243  *
244  * This function is used to initialize the MSC class.
245  *
246  * @param controllerId   The controller ID of the USB IP. See the enumeration usb_controller_index_t.
247  * @param config          The class configuration information.
248  * @param handle          A parameter used to return pointer of the MSC class handle to the caller.
249  *
250  * @return A USB error code or kStatus_USB_Success.
251  */
252 extern usb_status_t USB_DeviceMscInit(uint8_t controllerId,
253                                       usb_device_class_config_struct_t *config,
254                                       class_handle_t *handle);
255 /*!
256  * @brief Deinitializes the device MSC class.
257  *
258  * The function deinitializes the device MSC class.
259  *
260  * @param handle The MSC class handle received from usb_device_class_config_struct_t::classHandle.
261  *
262  * @return A USB error code or kStatus_USB_Success.
263  */
264 extern usb_status_t USB_DeviceMscDeinit(class_handle_t handle);
265 
266 /*! @}*/
267 
268 extern usb_status_t USB_DeviceMscEvent(void *handle, uint32_t event, void *param);
269 extern usb_status_t USB_DeviceMscLbaTransfer(usb_device_msc_struct_t *mscHandle,
270                                              uint8_t direction,
271                                              usb_lba_transfer_information_struct_t *lba_info_ptr);
272 
273 #ifdef __cplusplus
274 }
275 #endif
276 
277 /*! @}*/
278 
279 #endif
280