1 /*
2  * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016 - 2017,2019 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "usb_device_config.h"
10 #include "usb.h"
11 #include "usb_device.h"
12 
13 #include "usb_device_class.h"
14 
15 #if ((defined(USB_DEVICE_CONFIG_MSC)) && (USB_DEVICE_CONFIG_MSC > 0U))
16 #include "usb_device_msc.h"
17 /*******************************************************************************
18  * Definitions
19  ******************************************************************************/
20 
21 /*******************************************************************************
22  * Prototypes
23  ******************************************************************************/
24 usb_status_t USB_DeviceMscRecv(usb_device_msc_struct_t *mscHandle);
25 usb_status_t USB_DeviceMscSend(usb_device_msc_struct_t *mscHandle);
26 usb_status_t USB_DeviceMscEndpointsInit(usb_device_msc_struct_t *mscHandle);
27 usb_status_t USB_DeviceMscEndpointsDeinit(usb_device_msc_struct_t *mscHandle);
28 
29 /*******************************************************************************
30  * Variables
31  ******************************************************************************/
32 
33 #if (USB_DEVICE_CONFIG_MSC == 1U)
34 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static usb_device_msc_cbw_t s_MscCbw1;
35 #define MSCCBW_ARRAY \
36     {                \
37         &s_MscCbw1   \
38     }
39 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static usb_device_msc_csw_t s_MscCsw1;
40 #define MSCCSW_ARRAY \
41     {                \
42         &s_MscCsw1   \
43     }
44 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static usb_device_request_sense_data_struct_t requestSense1;
45 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static usb_device_read_capacity_struct_t readCapacity1;
46 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static usb_device_read_capacity16_data_struct_t
47     readCapacity161;
48 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static uint8_t
49     formatCapacityData1[sizeof(usb_device_capacity_list_header_struct_t) +
50                         sizeof(usb_device_current_max_capacity_descriptor_struct_t) +
51                         sizeof(usb_device_formattable_capacity_descriptor_struct_t) * 3];
52 #define MSCSENSE_ARRAY \
53     {                  \
54         &requestSense1 \
55     }
56 #define MSCCPAP_ARRAY  \
57     {                  \
58         &readCapacity1 \
59     }
60 #define MSCCAPA16_ARRAY  \
61     {                    \
62         &readCapacity161 \
63     }
64 #define MSCFORMAT_ARRAY         \
65     {                           \
66         &formatCapacityData1[0] \
67     }
68 #elif (USB_DEVICE_CONFIG_MSC == 2U)
69 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static usb_device_msc_cbw_t s_MscCbw1;
70 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static usb_device_msc_cbw_t s_MscCbw2;
71 #define MSCCBW_ARRAY           \
72     {                          \
73         &s_MscCbw1, &s_MscCbw2 \
74     }
75 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static usb_device_msc_csw_t s_MscCsw1;
76 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static usb_device_msc_csw_t s_MscCsw2;
77 #define MSCCSW_ARRAY           \
78     {                          \
79         &s_MscCsw1, &s_MscCsw2 \
80     }
81 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static usb_device_request_sense_data_struct_t requestSense1;
82 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static usb_device_read_capacity_struct_t readCapacity1;
83 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static usb_device_read_capacity16_data_struct_t
84     readCapacity161;
85 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static uint8_t
86     formatCapacityData1[sizeof(usb_device_capacity_list_header_struct_t) +
87                         sizeof(usb_device_current_max_capacity_descriptor_struct_t) +
88                         sizeof(usb_device_formattable_capacity_descriptor_struct_t) * 3];
89 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) usb_device_request_sense_data_struct_t requestSense2;
90 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) usb_device_read_capacity_struct_t readCapacity2;
91 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) usb_device_read_capacity16_data_struct_t readCapacity162;
92 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) uint8_t
93     formatCapacityData2[sizeof(usb_device_capacity_list_header_struct_t) +
94                         sizeof(usb_device_current_max_capacity_descriptor_struct_t) +
95                         sizeof(usb_device_formattable_capacity_descriptor_struct_t) * 3];
96 #define MSCSENSE_ARRAY                 \
97     {                                  \
98         &requestSense1, &requestSense2 \
99     }
100 #define MSCCPAP_ARRAY                  \
101     {                                  \
102         &readCapacity1, &readCapacity2 \
103     }
104 #define MSCCAPA16_ARRAY                    \
105     {                                      \
106         &readCapacity161, &readCapacity162 \
107     }
108 #define MSCFORMAT_ARRAY                                  \
109     {                                                    \
110         &formatCapacityData1[0], &formatCapacityData2[0] \
111     }
112 #elif (USB_DEVICE_CONFIG_MSC == 3U)
113 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static usb_device_msc_cbw_t s_MscCbw1;
114 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static usb_device_msc_cbw_t s_MscCbw2;
115 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static usb_device_msc_cbw_t s_MscCbw3;
116 #define MSCCBW_ARRAY                       \
117     {                                      \
118         &s_MscCbw1, &s_MscCbw2, &s_MscCbw3 \
119     }
120 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static usb_device_msc_csw_t s_MscCsw1;
121 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static usb_device_msc_csw_t s_MscCsw2;
122 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static usb_device_msc_csw_t s_MscCsw3;
123 #define MSCCSW_ARRAY                       \
124     {                                      \
125         &s_MscCsw1, &s_MscCsw2, &s_MscCsw3 \
126     }
127 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static usb_device_request_sense_data_struct_t requestSense1;
128 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static usb_device_read_capacity_struct_t readCapacity1;
129 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static usb_device_read_capacity16_data_struct_t
130     readCapacity161;
131 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static uint8_t
132     formatCapacityData1[sizeof(usb_device_capacity_list_header_struct_t) +
133                         sizeof(usb_device_current_max_capacity_descriptor_struct_t) +
134                         sizeof(usb_device_formattable_capacity_descriptor_struct_t) * 3];
135 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static usb_device_request_sense_data_struct_t requestSense2;
136 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static usb_device_read_capacity_struct_t readCapacity2;
137 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static usb_device_read_capacity16_data_struct_t
138     readCapacity162;
139 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static uint8_t
140     formatCapacityData2[sizeof(usb_device_capacity_list_header_struct_t) +
141                         sizeof(usb_device_current_max_capacity_descriptor_struct_t) +
142                         sizeof(usb_device_formattable_capacity_descriptor_struct_t) * 3];
143 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static usb_device_request_sense_data_struct_t requestSense3;
144 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static usb_device_read_capacity_struct_t readCapacity3;
145 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static usb_device_read_capacity16_data_struct_t
146     readCapacity163;
147 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static uint8_t
148     formatCapacityData3[sizeof(usb_device_capacity_list_header_struct_t) +
149                         sizeof(usb_device_current_max_capacity_descriptor_struct_t) +
150                         sizeof(usb_device_formattable_capacity_descriptor_struct_t) * 3];
151 #define MSCSENSE_ARRAY                                 \
152     {                                                  \
153         &requestSense1, &requestSense2, &requestSense3 \
154     }
155 #define MSCCPAP_ARRAY                                  \
156     {                                                  \
157         &readCapacity1, &readCapacity2, &readCapacity3 \
158     }
159 #define MSCCAPA16_ARRAY                                      \
160     {                                                        \
161         &readCapacity161, &readCapacity162, &readCapacity163 \
162     }
163 #define MSCFORMAT_ARRAY                                                           \
164     {                                                                             \
165         &formatCapacityData1[0], &formatCapacityData2[0], &formatCapacityData3[0] \
166     }
167 #else
168 #error "the max support USB_DEVICE_CONFIG_MSC is 3"
169 #endif
170 
USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE)171 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static usb_device_msc_struct_t
172     g_msc_handle[USB_DEVICE_CONFIG_MSC];
173 /*******************************************************************************
174  * Code
175  ******************************************************************************/
176 
177 /*!
178  * @brief Allocate a device msc class handle.
179  *
180  * This function allocates a device msc class handle.
181  *
182  * @param handle          It is out parameter, is used to return pointer of the device msc class handle to the caller.
183  *
184  * @retval kStatus_USB_Success              Get a device msc class handle successfully.
185  * @retval kStatus_USB_Busy                 Cannot allocate a device msc class handle.
186  */
187 
188 static usb_status_t USB_DeviceMscAllocateHandle(usb_device_msc_struct_t **handle)
189 {
190     uint32_t count;
191     usb_device_msc_cbw_t *cbw_array[]                            = MSCCBW_ARRAY;
192     usb_device_msc_csw_t *csw_array[]                            = MSCCSW_ARRAY;
193     usb_device_request_sense_data_struct_t *sense[]              = MSCSENSE_ARRAY;
194     usb_device_read_capacity_struct_t *capacity_array[]          = MSCCPAP_ARRAY;
195     usb_device_read_capacity16_data_struct_t *capacity16_array[] = MSCCAPA16_ARRAY;
196     uint8_t *formatCapacityData[]                                = MSCFORMAT_ARRAY;
197 
198     for (count = 0; count < USB_DEVICE_CONFIG_MSC; count++)
199     {
200         if (NULL == g_msc_handle[count].handle)
201         {
202             g_msc_handle[count].mscCbw                    = (cbw_array[count]);
203             g_msc_handle[count].mscCsw                    = (csw_array[count]);
204             g_msc_handle[count].mscUfi.requestSense       = (sense[count]);
205             g_msc_handle[count].mscUfi.readCapacity       = (capacity_array[count]);
206             g_msc_handle[count].mscUfi.readCapacity16     = (capacity16_array[count]);
207             g_msc_handle[count].mscUfi.formatCapacityData = (formatCapacityData[count]);
208             *handle                                       = &g_msc_handle[count];
209             return kStatus_USB_Success;
210         }
211     }
212 
213     return kStatus_USB_Busy;
214 }
215 
216 /*!
217  * @brief Free a device msc class handle.
218  *
219  * This function frees a device msc class handle.
220  *
221  * @param handle          The device msc class handle.
222  *
223  * @retval kStatus_USB_Success              Free device msc class handle successfully.
224  */
USB_DeviceMscFreeHandle(usb_device_msc_struct_t * handle)225 static usb_status_t USB_DeviceMscFreeHandle(usb_device_msc_struct_t *handle)
226 {
227     handle->handle              = NULL;
228     handle->configurationStruct = (usb_device_class_config_struct_t *)NULL;
229     handle->configuration       = 0;
230     handle->alternate           = 0;
231     return kStatus_USB_Success;
232 }
233 
234 /*!
235  * @brief Process usb msc ufi command.
236  *
237  * This function analyse the cbw , get the command code.
238  *
239  * @param handle          The device msc class handle.
240  *
241  * @retval kStatus_USB_Success              Free device msc class handle successfully.
242  */
USB_DeviceMscProcessUfiCommand(usb_device_msc_struct_t * mscHandle)243 static usb_status_t USB_DeviceMscProcessUfiCommand(usb_device_msc_struct_t *mscHandle)
244 {
245     usb_status_t status;
246     usb_device_msc_ufi_struct_t *ufi = NULL;
247 
248     ufi = &mscHandle->mscUfi;
249     if (USB_DEVICE_MSC_REQUEST_SENSE_COMMAND != mscHandle->mscCbw->cbwcb[0])
250     {
251         ufi->requestSense->senseKey                = USB_DEVICE_MSC_UFI_NO_SENSE;
252         ufi->requestSense->additionalSenseCode     = USB_DEVICE_MSC_UFI_NO_SENSE;
253         ufi->requestSense->additionalSenseQualifer = USB_DEVICE_MSC_UFI_NO_SENSE;
254     }
255     ufi->thirteenCase.hostExpectedDataLength = mscHandle->mscCbw->dataTransferLength;
256     ufi->thirteenCase.hostExpectedDirection = (uint8_t)(mscHandle->mscCbw->flags >> USB_DEVICE_MSC_CBW_DIRECTION_SHIFT);
257     /*The first byte of all ufi command blocks shall contain an Operation Code, refer to ufi spec*/
258     switch (mscHandle->mscCbw->cbwcb[0])
259     {
260         /* ufi command operation code*/
261         case USB_DEVICE_MSC_INQUIRY_COMMAND: /*operation code : 0x12*/
262             status = USB_DeviceMscUfiInquiryCommand(mscHandle);
263             break;
264         case USB_DEVICE_MSC_READ_10_COMMAND: /*operation code : 0x28 */
265         case USB_DEVICE_MSC_READ_12_COMMAND: /*operation code : 0xA8 */
266             status = USB_DeviceMscUfiReadCommand(mscHandle);
267             break;
268         case USB_DEVICE_MSC_REQUEST_SENSE_COMMAND: /*operation code : 0x03*/
269             status = USB_DeviceMscUfiRequestSenseCommand(mscHandle);
270             break;
271         case USB_DEVICE_MSC_TEST_UNIT_READY_COMMAND: /*operation code : 0x00 */
272             status = USB_DeviceMscUfiTestUnitReadyCommand(mscHandle);
273             break;
274         case USB_DEVICE_MSC_WRITE_10_COMMAND: /*operation code : 0x2A */
275         case USB_DEVICE_MSC_WRITE_12_COMMAND: /*operation code : 0xAA */
276             status = USB_DeviceMscUfiWriteCommand(mscHandle);
277             break;
278         case USB_DEVICE_MSC_PREVENT_ALLOW_MEDIUM_REM_COMMAND: /*operation code :0x1E */
279             status = USB_DeviceMscUfiPreventAllowMediumCommand(mscHandle);
280             break;
281         case USB_DEVICE_MSC_FORMAT_UNIT_COMMAND: /*operation code : 0x04*/
282             status = USB_DeviceMscUfiFormatUnitCommand(mscHandle);
283             break;
284         case USB_DEVICE_MSC_READ_CAPACITY_10_COMMAND: /*operation code : 0x25*/
285         case USB_DEVICE_MSC_READ_CAPACITY_16_COMMAND: /*operation code : 0x9E*/
286             status = USB_DeviceMscUfiReadCapacityCommand(mscHandle);
287             break;
288         case USB_DEVICE_MSC_MODE_SENSE_10_COMMAND: /* operation code :0x5A*/
289         case USB_DEVICE_MSC_MODE_SENSE_6_COMMAND:  /* operation code : 0x1A */
290             status = USB_DeviceMscUfiModeSenseCommand(mscHandle);
291             break;
292         case USB_DEVICE_MSC_MODE_SELECT_10_COMMAND: /*operation code : 0x55 */
293         case USB_DEVICE_MSC_MODE_SELECT_6_COMMAND:  /*operation code : 0x15 */
294             status = USB_DeviceMscUfiModeSelectCommand(mscHandle);
295             break;
296         case USB_DEVICE_MSC_READ_FORMAT_CAPACITIES_COMMAND: /*operation code : 0x23 */
297             status = USB_DeviceMscUfiReadFormatCapacityCommand(mscHandle);
298             break;
299         case USB_DEVICE_MSC_SEND_DIAGNOSTIC_COMMAND: /*operation code : 0x1D*/
300             status = USB_DeviceMscUfiSendDiagnosticCommand(mscHandle);
301             break;
302         case USB_DEVICE_MSC_VERIFY_COMMAND: /*operation code : 0x2F*/
303             status = USB_DeviceMscUfiVerifyCommand(mscHandle);
304             break;
305         case USB_DEVICE_MSC_START_STOP_UNIT_COMMAND: /*operation code : 0x1B*/
306             status = USB_DeviceMscUfiStartStopUnitCommand(mscHandle);
307             break;
308         default:
309             status = USB_DeviceMscUfiUnsupportCommand(mscHandle);
310             break;
311     }
312     if ((USB_DEVICE_MSC_UFI_NO_SENSE != ufi->requestSense->senseKey) &&
313         (USB_DEVICE_MSC_COMMAND_PASSED == mscHandle->mscCsw->cswStatus) &&
314         (USB_DEVICE_MSC_REQUEST_SENSE_COMMAND != mscHandle->mscCbw->cbwcb[0]))
315     {
316         mscHandle->mscCsw->cswStatus = USB_DEVICE_MSC_COMMAND_FAILED;
317     }
318     return status;
319 }
320 
321 /*!
322  * @brief Bulk IN endpoint callback function.
323  *
324  * This callback function is used to notify upper layer the transfer result of a transfer.
325  * This callback pointer is passed when the Bulk IN pipe initialized.
326  *
327  * @param handle          The device handle. It equals the value returned from USB_DeviceInit.
328  * @param message         The result of the Bulk IN pipe transfer.
329  * @param callbackParam  The parameter for this callback. It is same with
330  * usb_device_endpoint_callback_struct_t::callbackParam. In the class, the value is the MSC class handle.
331  *
332  * @return A USB error code or kStatus_USB_Success.
333  */
USB_DeviceMscBulkIn(usb_device_handle handle,usb_device_endpoint_callback_message_struct_t * message,void * callbackParam)334 static usb_status_t USB_DeviceMscBulkIn(usb_device_handle handle,
335                                         usb_device_endpoint_callback_message_struct_t *message,
336                                         void *callbackParam)
337 {
338     usb_device_msc_struct_t *mscHandle = (usb_device_msc_struct_t *)callbackParam;
339     usb_device_msc_csw_t *csw          = NULL;
340     void *temp;
341     usb_status_t error = kStatus_USB_Error;
342     /* endpoint callback length is USB_CANCELLED_TRANSFER_LENGTH (0xFFFFFFFFU) when transfer is canceled */
343     if (message->length == USB_CANCELLED_TRANSFER_LENGTH)
344     {
345         /*this code is called when stack cancel the transfer, app should release the buffer it use */
346         if ((0U != mscHandle->dataInFlag) && (mscHandle->configurationStruct->classCallback != NULL) &&
347             ((USB_DEVICE_MSC_READ_10_COMMAND == mscHandle->mscCbw->cbwcb[0]) ||
348              (USB_DEVICE_MSC_READ_12_COMMAND == mscHandle->mscCbw->cbwcb[0])))
349         {
350             usb_device_lba_app_struct_t lbaData;
351 
352             lbaData.size   = 0;
353             lbaData.buffer = message->buffer;
354             lbaData.offset = 0;
355             lbaData.lun    = mscHandle->mscCbw->logicalUnitNumber;
356             /*classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
357             it is from the second parameter of classInit */
358 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
359             if (kStatus_USB_Success != mscHandle->configurationStruct->classCallback((class_handle_t)mscHandle,
360                                                                                      kUSB_DeviceMscEventReadResponse,
361                                                                                      (void *)&lbaData))
362             {
363                 return kStatus_USB_Error;
364             }
365 #else
366             (void)mscHandle->configurationStruct->classCallback((class_handle_t)mscHandle,
367                                                                 kUSB_DeviceMscEventReadResponse, (void *)&lbaData);
368 #endif
369         }
370         if (mscHandle->inEndpointCswCancelFlag == 1U)
371         {
372             mscHandle->inEndpointCswCancelFlag = 0U;
373             /*cancel the transfer and wait for the calcel to be complete in bulk in callback*/
374             /*send csw*/
375             mscHandle->mscCsw->dataResidue = USB_LONG_TO_LITTLE_ENDIAN(mscHandle->mscCsw->dataResidue);
376 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
377             if (kStatus_USB_Success != USB_DeviceSendRequest(mscHandle->handle, mscHandle->bulkInEndpoint,
378                                                              (uint8_t *)mscHandle->mscCsw, USB_DEVICE_MSC_CSW_LENGTH))
379             {
380                 return kStatus_USB_Error;
381             }
382 #else
383             (void)USB_DeviceSendRequest(mscHandle->handle, mscHandle->bulkInEndpoint, (uint8_t *)mscHandle->mscCsw,
384                                         USB_DEVICE_MSC_CSW_LENGTH);
385 #endif
386             mscHandle->cswPrimeFlag = 1;
387             mscHandle->stallStatus  = 0;
388         }
389         return error;
390     }
391     if (mscHandle->transferRemaining >= message->length)
392     {
393         mscHandle->transferRemaining -= message->length;
394     }
395 
396     if (mscHandle->needInStallFlag == 1U)
397     {
398         mscHandle->needInStallFlag     = 0U;
399         mscHandle->inEndpointStallFlag = 1U;
400         mscHandle->dataInFlag          = 0U;
401 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
402         if (kStatus_USB_Success != USB_DeviceStallEndpoint(mscHandle->handle, mscHandle->bulkInEndpoint))
403         {
404             return kStatus_USB_Error;
405         }
406 #else
407         (void)USB_DeviceStallEndpoint(mscHandle->handle, mscHandle->bulkInEndpoint);
408 #endif
409         return error;
410     }
411     if ((0U == mscHandle->dataInFlag) && (message->length == USB_DEVICE_MSC_CSW_LENGTH))
412     {
413         temp = (void *)(message->buffer);
414         csw  = (usb_device_msc_csw_t *)temp;
415     }
416 
417     if (0U != mscHandle->dataInFlag)
418     {
419         if ((mscHandle->configurationStruct->classCallback != NULL))
420         {
421             usb_device_lba_app_struct_t lbaData;
422 
423             lbaData.size   = message->length;
424             lbaData.buffer = message->buffer;
425             lbaData.offset = mscHandle->currentOffset;
426             lbaData.lun    = mscHandle->mscCbw->logicalUnitNumber;
427 
428             if ((USB_DEVICE_MSC_READ_10_COMMAND == mscHandle->mscCbw->cbwcb[0]) ||
429                 (USB_DEVICE_MSC_READ_12_COMMAND == mscHandle->mscCbw->cbwcb[0]))
430             {
431                 /* classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
432                 it is from the second parameter of classInit */
433 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
434                 if (kStatus_USB_Success !=
435                     mscHandle->configurationStruct->classCallback((class_handle_t)mscHandle,
436                                                                   kUSB_DeviceMscEventReadResponse, (void *)&lbaData))
437                 {
438                     return kStatus_USB_Error;
439                 }
440 #else
441                 (void)mscHandle->configurationStruct->classCallback((class_handle_t)mscHandle,
442                                                                     kUSB_DeviceMscEventReadResponse, (void *)&lbaData);
443 #endif
444             }
445 
446             if (0U != mscHandle->transferRemaining)
447             {
448                 mscHandle->currentOffset +=
449                     (message->length / mscHandle->luInformations[mscHandle->mscCbw->logicalUnitNumber].lengthOfEachLba);
450                 error = USB_DeviceMscSend(mscHandle);
451             }
452             if (0U == mscHandle->transferRemaining)
453             {
454                 mscHandle->dataInFlag = 0U;
455                 /*data transfer has been done, send the csw to host */
456                 mscHandle->cswPrimeFlag        = 1U;
457                 mscHandle->mscCsw->dataResidue = USB_LONG_TO_LITTLE_ENDIAN(mscHandle->mscCsw->dataResidue);
458 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
459                 if (kStatus_USB_Success != USB_DeviceSendRequest(mscHandle->handle, mscHandle->bulkInEndpoint,
460                                                                  (uint8_t *)mscHandle->mscCsw,
461                                                                  USB_DEVICE_MSC_CSW_LENGTH))
462                 {
463                     return kStatus_USB_Error;
464                 }
465 #else
466                 (void)USB_DeviceSendRequest(mscHandle->handle, mscHandle->bulkInEndpoint, (uint8_t *)mscHandle->mscCsw,
467                                             USB_DEVICE_MSC_CSW_LENGTH);
468 #endif
469             }
470         }
471     }
472     else if ((message->length == USB_DEVICE_MSC_CSW_LENGTH) && (USB_DEVICE_MSC_DCSWSIGNATURE == csw->signature))
473     {
474         mscHandle->cbwValidFlag = 1U;
475         mscHandle->cswPrimeFlag = 0U;
476 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
477         if (kStatus_USB_Success != USB_DeviceRecvRequest(mscHandle->handle, mscHandle->bulkOutEndpoint,
478                                                          (uint8_t *)mscHandle->mscCbw, USB_DEVICE_MSC_CBW_LENGTH))
479         {
480             return kStatus_USB_Error;
481         }
482 #else
483         (void)USB_DeviceRecvRequest(mscHandle->handle, mscHandle->bulkOutEndpoint, (uint8_t *)mscHandle->mscCbw,
484                                     USB_DEVICE_MSC_CBW_LENGTH);
485 #endif
486         mscHandle->cbwPrimeFlag = 1U;
487     }
488     else
489     {
490         /*no action*/
491     }
492     return error;
493 }
494 
495 /*!
496  * @brief Bulk OUT endpoint callback function.
497  *
498  * This callback function is used to notify upper layer the transfer result of a transfer.
499  * This callback pointer is passed when the Bulk OUT pipe initialized.
500  *
501  * @param handle          The device handle. It equals the value returned from USB_DeviceInit.
502  * @param message         The result of the Bulk OUT pipe transfer.
503  * @param callbackParam  The parameter for this callback. It is same with
504  * usb_device_endpoint_callback_struct_t::callbackParam. In the class, the value is the MSC class handle.
505  *
506  * @return A USB error code or kStatus_USB_Success.
507  */
USB_DeviceMscBulkOut(usb_device_handle handle,usb_device_endpoint_callback_message_struct_t * message,void * callbackParam)508 static usb_status_t USB_DeviceMscBulkOut(usb_device_handle handle,
509                                          usb_device_endpoint_callback_message_struct_t *message,
510                                          void *callbackParam)
511 {
512     usb_device_msc_struct_t *mscHandle = (usb_device_msc_struct_t *)callbackParam;
513     usb_status_t error                 = kStatus_USB_Success;
514 
515     /* endpoint callback length is USB_CANCELLED_TRANSFER_LENGTH (0xFFFFFFFFU) when transfer is canceled */
516     if (message->length == USB_CANCELLED_TRANSFER_LENGTH)
517     {
518         /*this code is called when stack cancel the transfer, app should release the buffer it use*/
519         if ((0U != mscHandle->dataOutFlag) && (mscHandle->configurationStruct->classCallback != NULL) &&
520             ((USB_DEVICE_MSC_WRITE_10_COMMAND == mscHandle->mscCbw->cbwcb[0]) ||
521              (USB_DEVICE_MSC_WRITE_12_COMMAND == mscHandle->mscCbw->cbwcb[0])))
522         {
523             usb_device_lba_app_struct_t lbaData;
524 
525             lbaData.size   = 0;
526             lbaData.buffer = message->buffer;
527             lbaData.offset = 0;
528             lbaData.lun    = mscHandle->mscCbw->logicalUnitNumber;
529             /* classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
530             it is from the second parameter of classInit */
531 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
532             if (kStatus_USB_Success != mscHandle->configurationStruct->classCallback((class_handle_t)mscHandle,
533                                                                                      kUSB_DeviceMscEventWriteResponse,
534                                                                                      (void *)&lbaData))
535             {
536                 return kStatus_USB_Error;
537             }
538 #else
539             (void)mscHandle->configurationStruct->classCallback((class_handle_t)mscHandle,
540                                                                 kUSB_DeviceMscEventWriteResponse, (void *)&lbaData);
541 #endif
542         }
543         if ((mscHandle->cbwPrimeFlag == 0U) && (mscHandle->inEndpointStallFlag == 0U) &&
544             (mscHandle->outEndpointStallFlag == 0U))
545         {
546             /*prime cbw*/
547 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
548             if (kStatus_USB_Success != USB_DeviceRecvRequest(mscHandle->handle, mscHandle->bulkOutEndpoint,
549                                                              (uint8_t *)mscHandle->mscCbw, USB_DEVICE_MSC_CBW_LENGTH))
550             {
551                 return kStatus_USB_Error;
552             }
553 #else
554             (void)USB_DeviceRecvRequest(mscHandle->handle, mscHandle->bulkOutEndpoint, (uint8_t *)mscHandle->mscCbw,
555                                         USB_DEVICE_MSC_CBW_LENGTH);
556 #endif
557             mscHandle->cbwPrimeFlag = 1U;
558         }
559         return error;
560     }
561 
562     if (mscHandle->transferRemaining >= message->length)
563     {
564         mscHandle->transferRemaining -= message->length;
565     }
566 
567     if ((USB_DEVICE_MSC_MODE_SELECT_10_COMMAND == mscHandle->mscCbw->cbwcb[0]) ||
568         (USB_DEVICE_MSC_MODE_SELECT_6_COMMAND == mscHandle->mscCbw->cbwcb[0]))
569     {
570         if ((mscHandle->configurationStruct->classCallback != NULL))
571         {
572             /* classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
573             it is from the second parameter of classInit */
574 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
575             if (kStatus_USB_Success !=
576                 mscHandle->configurationStruct->classCallback((class_handle_t)mscHandle,
577                                                               kUSB_DeviceMscEventModeSelectResponse, (void *)NULL))
578             {
579                 return kStatus_USB_Error;
580             }
581 #else
582             (void)mscHandle->configurationStruct->classCallback((class_handle_t)mscHandle,
583                                                                 kUSB_DeviceMscEventModeSelectResponse, (void *)NULL);
584 #endif
585         }
586     }
587     if (mscHandle->needOutStallFlag == 1U)
588     {
589         mscHandle->needOutStallFlag     = 0U;
590         mscHandle->outEndpointStallFlag = 1U;
591         mscHandle->dataOutFlag          = 0U;
592         mscHandle->cbwPrimeFlag         = 0U;
593 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
594         if (kStatus_USB_Success != USB_DeviceStallEndpoint(mscHandle->handle, mscHandle->bulkOutEndpoint))
595         {
596             return kStatus_USB_Error;
597         }
598 #else
599         (void)USB_DeviceStallEndpoint(mscHandle->handle, mscHandle->bulkOutEndpoint);
600 #endif
601         return error;
602     }
603 
604     if (0U != mscHandle->dataOutFlag)
605     {
606         usb_device_lba_app_struct_t lbaData;
607 
608         lbaData.size   = message->length;
609         lbaData.buffer = message->buffer;
610         lbaData.offset = mscHandle->currentOffset;
611         lbaData.lun    = mscHandle->mscCbw->logicalUnitNumber;
612 
613         if ((mscHandle->configurationStruct->classCallback != NULL))
614         {
615             if ((USB_DEVICE_MSC_WRITE_10_COMMAND == mscHandle->mscCbw->cbwcb[0]) ||
616                 (USB_DEVICE_MSC_WRITE_12_COMMAND == mscHandle->mscCbw->cbwcb[0]))
617             {
618                 /* classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
619                    it is from the second parameter of classInit */
620 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
621                 if (kStatus_USB_Success !=
622                     mscHandle->configurationStruct->classCallback((class_handle_t)mscHandle,
623                                                                   kUSB_DeviceMscEventWriteResponse, (void *)&lbaData))
624                 {
625                     return kStatus_USB_Error;
626                 }
627 #else
628                 (void)mscHandle->configurationStruct->classCallback((class_handle_t)mscHandle,
629                                                                     kUSB_DeviceMscEventWriteResponse, (void *)&lbaData);
630 #endif
631             }
632 
633             if (0U != mscHandle->transferRemaining)
634             {
635                 mscHandle->currentOffset +=
636                     (message->length / mscHandle->luInformations[mscHandle->mscCbw->logicalUnitNumber].lengthOfEachLba);
637                 error = USB_DeviceMscRecv(mscHandle);
638             }
639         }
640 
641         if (0U == mscHandle->transferRemaining)
642         {
643             mscHandle->dataOutFlag = 0U;
644             {
645                 mscHandle->mscCsw->dataResidue = USB_LONG_TO_LITTLE_ENDIAN(mscHandle->mscCsw->dataResidue);
646 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
647                 if (kStatus_USB_Success != USB_DeviceSendRequest(mscHandle->handle, mscHandle->bulkInEndpoint,
648                                                                  (uint8_t *)mscHandle->mscCsw,
649                                                                  USB_DEVICE_MSC_CSW_LENGTH))
650                 {
651                     return kStatus_USB_Error;
652                 }
653 #else
654                 (void)USB_DeviceSendRequest(mscHandle->handle, mscHandle->bulkInEndpoint, (uint8_t *)mscHandle->mscCsw,
655                                             USB_DEVICE_MSC_CSW_LENGTH);
656 #endif
657                 mscHandle->cswPrimeFlag = 1U;
658             }
659         }
660     }
661     else if ((0U != mscHandle->cbwValidFlag) && (message->length == USB_DEVICE_MSC_CBW_LENGTH) &&
662              (USB_DEVICE_MSC_DCBWSIGNATURE == mscHandle->mscCbw->signature) &&
663              (!((0U != (mscHandle->mscCbw->logicalUnitNumber & 0xF0U)) ||
664                 (0U != (mscHandle->mscCbw->cbLength & 0xE0U)))) &&
665              (mscHandle->mscCbw->logicalUnitNumber < (mscHandle->logicalUnitNumber + 1U)) &&
666              ((mscHandle->mscCbw->cbLength >= 0x01U) && (mscHandle->mscCbw->cbLength <= 0x10U)))
667     {
668         mscHandle->cbwPrimeFlag      = 0U;
669         mscHandle->transferRemaining = 0U;
670 
671         mscHandle->mscCsw->signature   = USB_DEVICE_MSC_DCSWSIGNATURE;
672         mscHandle->mscCsw->dataResidue = 0U;
673         mscHandle->mscCsw->tag         = mscHandle->mscCbw->tag;
674 
675         mscHandle->cbwValidFlag = 0U;
676 
677         mscHandle->mscCbw->dataTransferLength = USB_LONG_FROM_LITTLE_ENDIAN(mscHandle->mscCbw->dataTransferLength);
678 
679         mscHandle->dataOutFlag = (uint8_t)(((0U == (mscHandle->mscCbw->flags & USB_DEVICE_MSC_CBW_DIRECTION_BIT)) &&
680                                             (0U != mscHandle->mscCbw->dataTransferLength)) ?
681                                                1U :
682                                                0U);
683 
684         mscHandle->dataInFlag = (uint8_t)(((0U != (mscHandle->mscCbw->flags & USB_DEVICE_MSC_CBW_DIRECTION_BIT)) &&
685                                            (0U != mscHandle->mscCbw->dataTransferLength)) ?
686                                               1U :
687                                               0U);
688 
689         if ((0U != mscHandle->dataInFlag) && (0U != mscHandle->inEndpointStallFlag))
690         {
691             error = kStatus_USB_Error;
692             return error;
693         }
694         error = USB_DeviceMscProcessUfiCommand(mscHandle);
695         if (error == kStatus_USB_InvalidRequest)
696         {
697             if (mscHandle->dataOutFlag == 1U)
698             {
699                 if (mscHandle->outEndpointStallFlag == 0U)
700                 {
701                     mscHandle->needOutStallFlag = 1U;
702                 }
703                 mscHandle->dataOutFlag = 0U;
704             }
705             else if (mscHandle->dataInFlag == 1U)
706             {
707                 if (mscHandle->inEndpointStallFlag == 0U)
708                 {
709                     mscHandle->needInStallFlag = 1U;
710                 }
711                 mscHandle->dataInFlag = 0U;
712             }
713             else
714             {
715                 /*no action*/
716             }
717             mscHandle->stallStatus = (uint8_t)USB_DEVICE_MSC_STALL_IN_DATA;
718         }
719 
720         if (!((0U != mscHandle->dataOutFlag) || ((0U != mscHandle->dataInFlag) || (0U != mscHandle->needInStallFlag))))
721         {
722             mscHandle->mscCsw->dataResidue = USB_LONG_TO_LITTLE_ENDIAN(mscHandle->mscCsw->dataResidue);
723 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
724             if (kStatus_USB_Success != USB_DeviceSendRequest(mscHandle->handle, mscHandle->bulkInEndpoint,
725                                                              (uint8_t *)mscHandle->mscCsw, USB_DEVICE_MSC_CSW_LENGTH))
726             {
727                 return kStatus_USB_Error;
728             }
729 #else
730             (void)USB_DeviceSendRequest(mscHandle->handle, mscHandle->bulkInEndpoint, (uint8_t *)mscHandle->mscCsw,
731                                         USB_DEVICE_MSC_CSW_LENGTH);
732 #endif
733             mscHandle->cswPrimeFlag = 1U;
734         }
735     }
736     else
737     {
738 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
739         if ((kStatus_USB_Success != USB_DeviceStallEndpoint(mscHandle->handle, mscHandle->bulkOutEndpoint)) ||
740             (kStatus_USB_Success != USB_DeviceStallEndpoint(mscHandle->handle, mscHandle->bulkInEndpoint)))
741         {
742             return kStatus_USB_Error;
743         }
744 #else
745         (void)USB_DeviceStallEndpoint(mscHandle->handle, mscHandle->bulkOutEndpoint);
746         (void)USB_DeviceStallEndpoint(mscHandle->handle, mscHandle->bulkInEndpoint);
747 #endif
748         mscHandle->cbwPrimeFlag         = 0U;
749         mscHandle->cbwValidFlag         = 0U;
750         mscHandle->outEndpointStallFlag = 1U;
751         mscHandle->inEndpointStallFlag  = 1U;
752         mscHandle->stallStatus          = (uint8_t)USB_DEVICE_MSC_STALL_IN_CBW;
753         mscHandle->performResetRecover  = 1;
754     }
755     return error;
756 }
757 
758 /*!
759  * @brief Initialize the endpoints of the msc class.
760  *
761  * This callback function is used to initialize the endpoints of the msc class.
762  *
763  * @param mscHandle          The device msc class handle. It equals the value returned from
764  * usb_device_class_config_struct_t::classHandle.
765  *
766  * @return A USB error code or kStatus_USB_Success.
767  */
USB_DeviceMscEndpointsInit(usb_device_msc_struct_t * mscHandle)768 usb_status_t USB_DeviceMscEndpointsInit(usb_device_msc_struct_t *mscHandle)
769 {
770     usb_device_interface_list_t *interfaceList;
771     usb_device_interface_struct_t *interface = (usb_device_interface_struct_t *)NULL;
772     usb_status_t error                       = kStatus_USB_Error;
773     uint32_t count;
774     uint32_t index;
775 
776     /* Check the configuration is valid or not. */
777     if ((0U == mscHandle->configuration) ||
778         (mscHandle->configuration > mscHandle->configurationStruct->classInfomation->configurations))
779     {
780         return error;
781     }
782 
783     /* Get the interface list of the new configuration. */
784     /* Check the interface list is valid or not. */
785     if (NULL == mscHandle->configurationStruct->classInfomation->interfaceList)
786     {
787         return error;
788     }
789     interfaceList = &mscHandle->configurationStruct->classInfomation->interfaceList[mscHandle->configuration - 1U];
790 
791     /* Find interface by using the alternate setting of the interface. */
792     for (count = 0; count < interfaceList->count; count++)
793     {
794         if (USB_DEVICE_CONFIG_MSC_CLASS_CODE == interfaceList->interfaces[count].classCode)
795         {
796             for (index = 0; index < interfaceList->interfaces[count].count; index++)
797             {
798                 if (interfaceList->interfaces[count].interface[index].alternateSetting == mscHandle->alternate)
799                 {
800                     interface = &interfaceList->interfaces[count].interface[index];
801                     break;
802                 }
803             }
804             mscHandle->interfaceNumber = interfaceList->interfaces[count].interfaceNumber;
805             break;
806         }
807     }
808     if (NULL == interface)
809     {
810         /* Return error if the interface is not found. */
811         return error;
812     }
813 
814     /* Keep new interface handle. */
815     mscHandle->interfaceHandle = interface;
816     /* Initialize the endpoints of the new interface. */
817     for (count = 0; count < interface->endpointList.count; count++)
818     {
819         usb_device_endpoint_init_struct_t epInitStruct;
820         usb_device_endpoint_callback_struct_t epCallback;
821         epInitStruct.zlt             = 0U;
822         epInitStruct.interval        = interface->endpointList.endpoint[count].interval;
823         epInitStruct.endpointAddress = interface->endpointList.endpoint[count].endpointAddress;
824         epInitStruct.maxPacketSize   = interface->endpointList.endpoint[count].maxPacketSize;
825         epInitStruct.transferType    = interface->endpointList.endpoint[count].transferType;
826 
827         if (USB_IN == ((epInitStruct.endpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >>
828                        USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT))
829         {
830             mscHandle->bulkInEndpoint = epInitStruct.endpointAddress;
831             epCallback.callbackFn     = USB_DeviceMscBulkIn;
832         }
833         else
834         {
835             mscHandle->bulkOutEndpoint = epInitStruct.endpointAddress;
836             epCallback.callbackFn      = USB_DeviceMscBulkOut;
837         }
838         epCallback.callbackParam = mscHandle;
839 
840         error = USB_DeviceInitEndpoint(mscHandle->handle, &epInitStruct, &epCallback);
841     }
842 
843     mscHandle->dataOutFlag             = 0U;
844     mscHandle->dataInFlag              = 0U;
845     mscHandle->outEndpointStallFlag    = 0U;
846     mscHandle->inEndpointStallFlag     = 0U;
847     mscHandle->needOutStallFlag        = 0U;
848     mscHandle->needInStallFlag         = 0U;
849     mscHandle->cbwValidFlag            = 1U;
850     mscHandle->transferRemaining       = 0U;
851     mscHandle->performResetRecover     = 0U;
852     mscHandle->performResetDoneFlag    = 0U;
853     mscHandle->stallStatus             = 0U;
854     mscHandle->inEndpointCswCancelFlag = 0U;
855     return error;
856 }
857 
858 /*!
859  * @brief De-initialize the endpoints of the msc class.
860  *
861  * This callback function is used to de-initialize the endpoints of the msc class.
862  *
863  * @param mscHandle          The device msc class handle. It equals the value returned from
864  * usb_device_class_config_struct_t::classHandle.
865  *
866  * @return A USB error code or kStatus_USB_Success.
867  */
USB_DeviceMscEndpointsDeinit(usb_device_msc_struct_t * mscHandle)868 usb_status_t USB_DeviceMscEndpointsDeinit(usb_device_msc_struct_t *mscHandle)
869 {
870     usb_status_t status = kStatus_USB_Error;
871     uint32_t count;
872 
873     if (NULL == mscHandle->interfaceHandle)
874     {
875         return status;
876     }
877     /* De-initialize all endpoints of the interface */
878     for (count = 0; count < mscHandle->interfaceHandle->endpointList.count; count++)
879     {
880         status = USB_DeviceDeinitEndpoint(mscHandle->handle,
881                                           mscHandle->interfaceHandle->endpointList.endpoint[count].endpointAddress);
882     }
883     mscHandle->interfaceHandle = NULL;
884     return status;
885 }
886 
887 /*!
888  * @brief Initialize the msc class.
889  *
890  * This function is used to initialize the msc class.
891  *
892  * @param controllerId   The controller id of the USB IP. Please refer to the enumeration usb_controller_index_t.
893  * @param config          The class configuration information.
894  * @param handle          It is out parameter, is used to return pointer of the msc class handle to the caller.
895  *
896  * @return A USB error code or kStatus_USB_Success.
897  */
USB_DeviceMscInit(uint8_t controllerId,usb_device_class_config_struct_t * config,class_handle_t * handle)898 usb_status_t USB_DeviceMscInit(uint8_t controllerId, usb_device_class_config_struct_t *config, class_handle_t *handle)
899 {
900     usb_device_msc_struct_t *mscHandle;
901     usb_status_t error;
902     uint32_t implementingDiskDrive   = USB_DEVICE_CONFIG_MSC_IMPLEMENTING_DISK_DRIVE;
903     usb_device_msc_ufi_struct_t *ufi = NULL;
904 
905     /* Allocate a msc class handle. */
906     error = USB_DeviceMscAllocateHandle(&mscHandle);
907 
908     if (kStatus_USB_Success != error)
909     {
910         return error;
911     }
912 
913     /* Get the device handle according to the controller id. */
914     error = USB_DeviceClassGetDeviceHandle(controllerId, &mscHandle->handle);
915 
916     if (kStatus_USB_Success != error)
917     {
918 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
919         if (kStatus_USB_Success != USB_DeviceMscFreeHandle(mscHandle))
920         {
921             return kStatus_USB_Error;
922         }
923 #else
924         (void)USB_DeviceMscFreeHandle(mscHandle);
925 #endif
926         return error;
927     }
928     if (NULL == mscHandle->handle)
929     {
930 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
931         if (kStatus_USB_Success != USB_DeviceMscFreeHandle(mscHandle))
932         {
933             return kStatus_USB_Error;
934         }
935 #else
936         (void)USB_DeviceMscFreeHandle(mscHandle);
937 #endif
938         return kStatus_USB_InvalidHandle;
939     }
940     /* Save the configuration of the class. */
941     mscHandle->configurationStruct = config;
942     /* Clear the configuration value. */
943     mscHandle->configuration = 0U;
944     mscHandle->alternate     = 0xffU;
945 
946     ufi = &mscHandle->mscUfi;
947 
948     mscHandle->implementingDiskDrive = implementingDiskDrive;
949 
950     ufi->requestSense->validErrorCode          = USB_DEVICE_MSC_UFI_REQ_SENSE_VALID_ERROR_CODE;
951     ufi->requestSense->additionalSenseLength   = USB_DEVICE_MSC_UFI_REQ_SENSE_ADDITIONAL_SENSE_LEN;
952     ufi->requestSense->senseKey                = USB_DEVICE_MSC_UFI_NO_SENSE;
953     ufi->requestSense->additionalSenseCode     = USB_DEVICE_MSC_UFI_NO_SENSE;
954     ufi->requestSense->additionalSenseQualifer = USB_DEVICE_MSC_UFI_NO_SENSE;
955 
956     mscHandle->cbwPrimeFlag = 0U;
957     mscHandle->cswPrimeFlag = 0U;
958 
959     *handle = (class_handle_t)mscHandle;
960     return error;
961 }
962 
963 /*!
964  * @brief De-initialize the device msc class.
965  *
966  * The function de-initializes the device msc class.
967  *
968  * @param handle The msc class handle got from usb_device_class_config_struct_t::classHandle.
969  *
970  * @return A USB error code or kStatus_USB_Success.
971  */
USB_DeviceMscDeinit(class_handle_t handle)972 usb_status_t USB_DeviceMscDeinit(class_handle_t handle)
973 {
974     usb_device_msc_struct_t *mscHandle;
975     usb_status_t status = kStatus_USB_Error;
976 
977     mscHandle = (usb_device_msc_struct_t *)handle;
978 
979     if (NULL == mscHandle)
980     {
981         return kStatus_USB_InvalidHandle;
982     }
983     status = USB_DeviceMscEndpointsDeinit(mscHandle);
984 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
985     if (kStatus_USB_Success != USB_DeviceMscFreeHandle(mscHandle))
986     {
987         return kStatus_USB_Error;
988     }
989 #else
990     (void)USB_DeviceMscFreeHandle(mscHandle);
991 #endif
992     return status;
993 }
994 
995 /*!
996  * @brief Handle the event passed to the msc class.
997  *
998  * This function handles the event passed to the msc class.
999  *
1000  * @param handle          The msc class handle, got from the usb_device_class_config_struct_t::classHandle.
1001  * @param event           The event codes. Please refer to the enumeration usb_device_class_event_t.
1002  * @param param           The param type is determined by the event code.
1003  *
1004  * @return A USB error code or kStatus_USB_Success.
1005  * @retval kStatus_USB_Success              Free device handle successfully.
1006  * @retval kStatus_USB_InvalidParameter     The device handle not be found.
1007  * @retval kStatus_USB_InvalidRequest       The request is invalid, and the control pipe will be stalled by the caller.
1008  */
USB_DeviceMscEvent(void * handle,uint32_t event,void * param)1009 usb_status_t USB_DeviceMscEvent(void *handle, uint32_t event, void *param)
1010 {
1011     usb_status_t error               = kStatus_USB_Error;
1012     usb_device_msc_ufi_struct_t *ufi = NULL;
1013     usb_device_msc_struct_t *mscHandle;
1014     usb_device_lba_information_struct_t diskInformation;
1015     uint16_t interfaceAlternate;
1016     uint8_t *temp8;
1017     uint8_t alternate;
1018     uint8_t index;
1019     usb_device_class_event_t eventCode = (usb_device_class_event_t)event;
1020     if ((NULL == param) || (NULL == handle))
1021     {
1022         return kStatus_USB_InvalidHandle;
1023     }
1024 
1025     /* Get the msc class handle. */
1026     mscHandle = (usb_device_msc_struct_t *)handle;
1027     switch (eventCode)
1028     {
1029         case kUSB_DeviceClassEventDeviceReset:
1030             /* Bus reset, clear the configuration. */
1031             mscHandle->configuration = 0U;
1032             /* Get device information. classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
1033             it is from the second parameter of classInit */
1034             error = mscHandle->configurationStruct->classCallback(
1035                 (class_handle_t)mscHandle, kUSB_DeviceMscEventGetLbaInformation, (void *)&diskInformation);
1036             if (0U >= diskInformation.logicalUnitNumberSupported)
1037             {
1038                 diskInformation.logicalUnitNumberSupported = 0U;
1039             }
1040             else
1041             {
1042                 mscHandle->logicalUnitNumber = (uint8_t)diskInformation.logicalUnitNumberSupported - 1U;
1043             }
1044             /*add for misra2.2*/
1045             if (0U == diskInformation.logicalUnitNumberSupported)
1046             {
1047                 error = kStatus_USB_InvalidParameter;
1048                 break;
1049             }
1050             /*initialize the basic device information*/
1051             for (index = 0U; (index <= mscHandle->logicalUnitNumber) && (index < USB_DEVICE_MSC_MAX_LUN); ++index)
1052             {
1053                 if (((0U == diskInformation.logicalUnitInformations[index].lengthOfEachLba) ||
1054                      (0U == diskInformation.logicalUnitInformations[index].totalLbaNumberSupports)))
1055                 {
1056                     error = kStatus_USB_Error;
1057                 }
1058                 else
1059                 {
1060                     mscHandle->luInformations[index] = diskInformation.logicalUnitInformations[index];
1061                 }
1062             }
1063             ufi                                        = &mscHandle->mscUfi;
1064             ufi->requestSense->validErrorCode          = USB_DEVICE_MSC_UFI_REQ_SENSE_VALID_ERROR_CODE;
1065             ufi->requestSense->additionalSenseLength   = USB_DEVICE_MSC_UFI_REQ_SENSE_ADDITIONAL_SENSE_LEN;
1066             ufi->requestSense->senseKey                = USB_DEVICE_MSC_UFI_NO_SENSE;
1067             ufi->requestSense->additionalSenseCode     = USB_DEVICE_MSC_UFI_NO_SENSE;
1068             ufi->requestSense->additionalSenseQualifer = USB_DEVICE_MSC_UFI_NO_SENSE;
1069 
1070             mscHandle->cbwPrimeFlag = 0U;
1071             mscHandle->cswPrimeFlag = 0U;
1072             break;
1073         case kUSB_DeviceClassEventSetConfiguration:
1074             /* Get the new configuration. */
1075             temp8 = ((uint8_t *)param);
1076             if (NULL == mscHandle->configurationStruct)
1077             {
1078                 break;
1079             }
1080             if (*temp8 == mscHandle->configuration)
1081             {
1082                 error = kStatus_USB_Success;
1083                 break;
1084             }
1085 
1086             if (0U != mscHandle->configuration)
1087             {
1088                 /* De-initialize the endpoints when current configuration is none zero. */
1089                 error = USB_DeviceMscEndpointsDeinit(mscHandle);
1090             }
1091             /* Save new configuration. */
1092             mscHandle->configuration = *temp8;
1093             /* Clear the alternate setting value. */
1094             mscHandle->alternate = 0;
1095             /* Initialize the endpoints of the new current configuration by using the alternate setting 0. */
1096             error = USB_DeviceMscEndpointsInit(mscHandle);
1097             if (kStatus_USB_Success == error)
1098             {
1099 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
1100                 if (kStatus_USB_Success != USB_DeviceRecvRequest(mscHandle->handle, mscHandle->bulkOutEndpoint,
1101                                                                  (uint8_t *)mscHandle->mscCbw,
1102                                                                  USB_DEVICE_MSC_CBW_LENGTH))
1103                 {
1104                     return kStatus_USB_Error;
1105                 }
1106 #else
1107                 (void)USB_DeviceRecvRequest(mscHandle->handle, mscHandle->bulkOutEndpoint, (uint8_t *)mscHandle->mscCbw,
1108                                             USB_DEVICE_MSC_CBW_LENGTH);
1109 #endif
1110                 mscHandle->cbwPrimeFlag = 1U;
1111             }
1112             break;
1113         case kUSB_DeviceClassEventSetInterface:
1114 
1115             if (NULL == mscHandle->configurationStruct)
1116             {
1117                 break;
1118             }
1119             /* Get the new alternate setting of the interface */
1120             interfaceAlternate = *((uint16_t *)param);
1121             /* Get the alternate setting value */
1122             alternate = (uint8_t)(interfaceAlternate & 0xFFU);
1123 
1124             /* Whether the interface belongs to the class. */
1125             if (mscHandle->interfaceNumber != ((uint8_t)(interfaceAlternate >> 8)))
1126             {
1127                 break;
1128             }
1129             /* Only handle new alternate setting. */
1130             if (alternate == mscHandle->alternate)
1131             {
1132                 error = kStatus_USB_Success;
1133                 break;
1134             }
1135             error = USB_DeviceMscEndpointsDeinit(mscHandle);
1136             /* Initialize new endpoints */
1137             error = USB_DeviceMscEndpointsInit(mscHandle);
1138             if (kStatus_USB_Success == error)
1139             {
1140 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
1141                 if (kStatus_USB_Success != USB_DeviceRecvRequest(mscHandle->handle, mscHandle->bulkOutEndpoint,
1142                                                                  (uint8_t *)mscHandle->mscCbw,
1143                                                                  USB_DEVICE_MSC_CBW_LENGTH))
1144                 {
1145                     return kStatus_USB_Error;
1146                 }
1147 #else
1148                 (void)USB_DeviceRecvRequest(mscHandle->handle, mscHandle->bulkOutEndpoint, (uint8_t *)mscHandle->mscCbw,
1149                                             USB_DEVICE_MSC_CBW_LENGTH);
1150 #endif
1151                 mscHandle->cbwPrimeFlag = 1U;
1152             }
1153             mscHandle->alternate = alternate;
1154 
1155             break;
1156         case kUSB_DeviceClassEventSetEndpointHalt:
1157             if ((NULL == mscHandle->configurationStruct) || (NULL == mscHandle->interfaceHandle))
1158             {
1159                 break;
1160             }
1161             /* Get the endpoint address */
1162             temp8 = ((uint8_t *)param);
1163 
1164             if ((mscHandle->inEndpointStallFlag == 0U) && (*temp8 == mscHandle->bulkInEndpoint))
1165             {
1166                 /* Only stall the endpoint belongs to the class */
1167                 mscHandle->inEndpointStallFlag = 1U;
1168                 mscHandle->cswPrimeFlag        = 0U;
1169                 error                          = USB_DeviceStallEndpoint(mscHandle->handle, *temp8);
1170             }
1171             if ((mscHandle->outEndpointStallFlag == 0U) && (*temp8 == mscHandle->bulkOutEndpoint))
1172             {
1173                 mscHandle->outEndpointStallFlag = 1U;
1174                 mscHandle->cbwPrimeFlag         = 0U;
1175                 error                           = USB_DeviceStallEndpoint(mscHandle->handle, *temp8);
1176             }
1177 
1178             break;
1179         case kUSB_DeviceClassEventClearEndpointHalt:
1180             if ((NULL == mscHandle->configurationStruct) || (NULL == mscHandle->interfaceHandle) ||
1181                 (mscHandle->performResetRecover == 1U))
1182             {
1183                 break;
1184             }
1185             /* Get the endpoint address */
1186             temp8 = ((uint8_t *)param);
1187             /* Only un-stall the endpoint belongs to the class , If the endpoint is in stall status ,then
1188              * un-stall it*/
1189             if ((mscHandle->inEndpointStallFlag == 1U) && (*temp8 == mscHandle->bulkInEndpoint))
1190             {
1191                 mscHandle->inEndpointStallFlag = 0;
1192                 mscHandle->cswPrimeFlag        = 0;
1193                 error                          = USB_DeviceUnstallEndpoint(mscHandle->handle, *temp8);
1194             }
1195             if ((mscHandle->outEndpointStallFlag == 1U) && (*temp8 == mscHandle->bulkOutEndpoint))
1196             {
1197                 mscHandle->outEndpointStallFlag = 0U;
1198                 mscHandle->cbwPrimeFlag         = 0U;
1199                 error                           = USB_DeviceUnstallEndpoint(mscHandle->handle, *temp8);
1200             }
1201             if (((mscHandle->stallStatus == (uint8_t)USB_DEVICE_MSC_STALL_IN_CSW) ||
1202                  (mscHandle->stallStatus == (uint8_t)USB_DEVICE_MSC_STALL_IN_DATA)) &&
1203                 (mscHandle->performResetDoneFlag != 1U))
1204             {
1205                 if (mscHandle->cswPrimeFlag == 1U)
1206                 {
1207                     /*cancel the transfer , after the cancel to be complete, and then prime csw in bulk in callback,  */
1208                     mscHandle->inEndpointCswCancelFlag = 1U;
1209 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
1210                     if (kStatus_USB_Success != USB_DeviceCancel(mscHandle->handle, mscHandle->bulkInEndpoint))
1211                     {
1212                         return kStatus_USB_Error;
1213                     }
1214 #else
1215                     (void)USB_DeviceCancel(mscHandle->handle, mscHandle->bulkInEndpoint);
1216 #endif
1217                 }
1218                 else
1219                 {
1220                     /*send csw*/
1221                     mscHandle->mscCsw->dataResidue = USB_LONG_TO_LITTLE_ENDIAN(mscHandle->mscCsw->dataResidue);
1222 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
1223                     if (kStatus_USB_Success != USB_DeviceSendRequest(mscHandle->handle, mscHandle->bulkInEndpoint,
1224                                                                      (uint8_t *)mscHandle->mscCsw,
1225                                                                      USB_DEVICE_MSC_CSW_LENGTH))
1226                     {
1227                         return kStatus_USB_Error;
1228                     }
1229 #else
1230                     (void)USB_DeviceSendRequest(mscHandle->handle, mscHandle->bulkInEndpoint,
1231                                                 (uint8_t *)mscHandle->mscCsw, USB_DEVICE_MSC_CSW_LENGTH);
1232 #endif
1233                     mscHandle->cswPrimeFlag = 1U;
1234                 }
1235                 mscHandle->stallStatus = 0U;
1236             }
1237             if ((mscHandle->performResetDoneFlag == 1U) && (mscHandle->inEndpointStallFlag == 0U) &&
1238                 (mscHandle->outEndpointStallFlag == 0U))
1239             {
1240                 mscHandle->performResetDoneFlag = 0U;
1241                 if (mscHandle->cbwPrimeFlag == 1U)
1242                 {
1243                     mscHandle->cbwPrimeFlag = 0U;
1244 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
1245                     if (kStatus_USB_Success != USB_DeviceCancel(mscHandle->handle, mscHandle->bulkOutEndpoint))
1246                     {
1247                         return kStatus_USB_Error;
1248                     }
1249 #else
1250                     (void)USB_DeviceCancel(mscHandle->handle, mscHandle->bulkOutEndpoint);
1251 #endif
1252                 }
1253                 else
1254                 {
1255                     /*prime cbw for new transfer*/
1256 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
1257                     if (kStatus_USB_Success != USB_DeviceRecvRequest(mscHandle->handle, mscHandle->bulkOutEndpoint,
1258                                                                      (uint8_t *)mscHandle->mscCbw,
1259                                                                      USB_DEVICE_MSC_CBW_LENGTH))
1260                     {
1261                         return kStatus_USB_Error;
1262                     }
1263 #else
1264                     (void)USB_DeviceRecvRequest(mscHandle->handle, mscHandle->bulkOutEndpoint,
1265                                                 (uint8_t *)mscHandle->mscCbw, USB_DEVICE_MSC_CBW_LENGTH);
1266 #endif
1267                     mscHandle->cbwPrimeFlag = 1U;
1268                 }
1269                 mscHandle->stallStatus = 0;
1270             }
1271             break;
1272         case kUSB_DeviceClassEventClassRequest:
1273         {
1274             /* Handle the msc class specific request. */
1275             usb_device_control_request_struct_t *control_request = (usb_device_control_request_struct_t *)param;
1276 
1277             if ((control_request->setup->bmRequestType & USB_REQUEST_TYPE_RECIPIENT_MASK) !=
1278                 USB_REQUEST_TYPE_RECIPIENT_INTERFACE)
1279             {
1280                 break;
1281             }
1282 
1283             if ((control_request->setup->wIndex & 0xFFU) != mscHandle->interfaceNumber)
1284             {
1285                 break;
1286             }
1287 
1288             error = kStatus_USB_InvalidRequest;
1289             switch (control_request->setup->bRequest)
1290             {
1291                 case USB_DEVICE_MSC_GET_MAX_LUN:
1292                     /*Get Max LUN */
1293                     if ((0U == control_request->setup->wValue) && (control_request->setup->wLength == 0x0001U) &&
1294                         ((control_request->setup->bmRequestType & USB_REQUEST_TYPE_DIR_MASK) ==
1295                          USB_REQUEST_TYPE_DIR_IN))
1296                     {
1297                         control_request->buffer = &mscHandle->logicalUnitNumber;
1298                         control_request->length = sizeof(mscHandle->logicalUnitNumber);
1299                         error                   = kStatus_USB_Success;
1300                     }
1301 
1302                     break;
1303                 case USB_DEVICE_MSC_BULK_ONLY_MASS_STORAGE_RESET:
1304                     /*Bulk-Only Mass Storage Reset (class-specific request)*/
1305                     if ((0U == control_request->setup->wValue) && (0U == control_request->setup->wLength) &&
1306                         ((control_request->setup->bmRequestType & USB_REQUEST_TYPE_DIR_MASK) ==
1307                          USB_REQUEST_TYPE_DIR_OUT))
1308                     {
1309                         /*Need to go to stall process, because reset recovery contains reset command and clare
1310                          * feature command*/
1311                         mscHandle->outEndpointStallFlag = 1U;
1312                         mscHandle->inEndpointStallFlag  = 1U;
1313 
1314                         mscHandle->cbwValidFlag         = 1U;
1315                         mscHandle->performResetRecover  = 0U;
1316                         mscHandle->performResetDoneFlag = 1U;
1317                         error                           = kStatus_USB_Success;
1318                     }
1319 
1320                     break;
1321                 default:
1322                     /* no action, return kStatus_USB_InvalidRequest */
1323                     break;
1324             }
1325         }
1326         break;
1327         default:
1328             /*no action*/
1329             break;
1330     }
1331 
1332     return error;
1333 }
1334 
1335 /*!
1336  * @brief Send data through a specified endpoint.
1337  *
1338  * The function is used to send data through a specified endpoint.
1339  * The function calls USB_DeviceSendRequest internally.
1340  *
1341  * @param handle The msc class handle got from usb_device_class_config_struct_t::classHandle.
1342  *
1343  * @return A USB error code or kStatus_USB_Success.
1344  *
1345  * @note The return value just means if the sending request is successful or not; the transfer done is notified by
1346  * USB_DeviceMscBulkIn.
1347  * Currently, only one transfer request can be supported for one specific endpoint.
1348  * If there is a specific requirement to support multiple transfer requests for one specific endpoint, the application
1349  * should implement a queue in the application level.
1350  * The subsequent transfer could begin only when the previous transfer is done (get notification through the endpoint
1351  * callback).
1352  */
USB_DeviceMscSend(usb_device_msc_struct_t * mscHandle)1353 usb_status_t USB_DeviceMscSend(usb_device_msc_struct_t *mscHandle)
1354 {
1355     usb_status_t status = kStatus_USB_Success;
1356     usb_device_lba_app_struct_t lba;
1357 
1358     lba.offset = mscHandle->currentOffset;
1359     /*bulkInBufferSize is the application buffer size, USB_DEVICE_MSC_MAX_SEND_TRANSFER_LENGTH is the max transfer
1360        length by the hardware,
1361         lba.size is the data pending  for transfer ,select the minimum size to transfer ,the remaining will be transfer
1362        next time*/
1363     lba.size = (mscHandle->luInformations[mscHandle->mscCbw->logicalUnitNumber].bulkInBufferSize >
1364                 USB_DEVICE_MSC_MAX_SEND_TRANSFER_LENGTH) ?
1365                    USB_DEVICE_MSC_MAX_SEND_TRANSFER_LENGTH :
1366                    mscHandle->luInformations[mscHandle->mscCbw->logicalUnitNumber].bulkInBufferSize;
1367     lba.size =
1368         (mscHandle->transferRemaining > lba.size) ? lba.size : mscHandle->transferRemaining; /* which one is smaller */
1369 
1370     lba.buffer = NULL;
1371     lba.lun    = mscHandle->mscCbw->logicalUnitNumber;
1372     /*classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
1373     it is from the second parameter of classInit*/
1374 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
1375     if (kStatus_USB_Success !=
1376         mscHandle->configurationStruct->classCallback((class_handle_t)mscHandle, kUSB_DeviceMscEventReadRequest, &lba))
1377     {
1378         return kStatus_USB_Error;
1379     }
1380 #else
1381     (void)mscHandle->configurationStruct->classCallback((class_handle_t)mscHandle, kUSB_DeviceMscEventReadRequest,
1382                                                         &lba);
1383 #endif
1384 
1385     if (mscHandle->currentOffset <
1386         mscHandle->luInformations[mscHandle->mscCbw->logicalUnitNumber].totalLbaNumberSupports)
1387     {
1388         status = USB_DeviceSendRequest(mscHandle->handle, mscHandle->bulkInEndpoint, lba.buffer, lba.size);
1389     }
1390     else
1391     {
1392         mscHandle->needInStallFlag     = 0U;
1393         mscHandle->inEndpointStallFlag = 1U;
1394         mscHandle->dataInFlag          = 0U;
1395         mscHandle->stallStatus         = (uint8_t)USB_DEVICE_MSC_STALL_IN_DATA;
1396 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
1397         if (kStatus_USB_Success != USB_DeviceStallEndpoint(mscHandle->handle, mscHandle->bulkInEndpoint))
1398         {
1399             return kStatus_USB_Error;
1400         }
1401 #else
1402         (void)USB_DeviceStallEndpoint(mscHandle->handle, mscHandle->bulkInEndpoint);
1403 #endif
1404     }
1405     return status;
1406 }
1407 
1408 /*!
1409  * @brief Receive data through a specified endpoint.
1410  *
1411  * The function is used to receive data through a specified endpoint.
1412  * The function calls USB_DeviceRecvRequest internally.
1413  *
1414  * @param handle The msc class handle got from usb_device_class_config_struct_t::classHandle.
1415  *
1416  * @return A USB error code or kStatus_USB_Success.
1417  *
1418  * @note The return value just means if the receiving request is successful or not; the transfer done is notified by
1419  * USB_DeviceMscBulkOut.
1420  * Currently, only one transfer request can be supported for one specific endpoint.
1421  * If there is a specific requirement to support multiple transfer requests for one specific endpoint, the application
1422  * should implement a queue in the application level.
1423  * The subsequent transfer could begin only when the previous transfer is done (get notification through the endpoint
1424  * callback).
1425  */
USB_DeviceMscRecv(usb_device_msc_struct_t * mscHandle)1426 usb_status_t USB_DeviceMscRecv(usb_device_msc_struct_t *mscHandle)
1427 {
1428     usb_status_t status = kStatus_USB_Success;
1429     usb_device_lba_app_struct_t lba;
1430 
1431     lba.offset = mscHandle->currentOffset;
1432     /*bulkOutBufferSize is the application buffer size, USB_DEVICE_MSC_MAX_RECV_TRANSFER_LENGTH is the max transfer
1433        length by the hardware,
1434        lba.size is the data pending  for transfer ,select the minimum size to transfer ,the remaining will be transfer
1435        next time*/
1436     lba.size = (mscHandle->luInformations[mscHandle->mscCbw->logicalUnitNumber].bulkOutBufferSize >
1437                 USB_DEVICE_MSC_MAX_RECV_TRANSFER_LENGTH) ?
1438                    USB_DEVICE_MSC_MAX_RECV_TRANSFER_LENGTH :
1439                    mscHandle->luInformations[mscHandle->mscCbw->logicalUnitNumber].bulkOutBufferSize;
1440     lba.size =
1441         (mscHandle->transferRemaining > lba.size) ? lba.size : mscHandle->transferRemaining; /* whichever is smaller */
1442 
1443     lba.buffer = NULL;
1444     lba.lun    = mscHandle->mscCbw->logicalUnitNumber;
1445     /*classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
1446     it is from the second parameter of classInit*/
1447 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
1448     if (kStatus_USB_Success !=
1449         mscHandle->configurationStruct->classCallback((class_handle_t)mscHandle, kUSB_DeviceMscEventWriteRequest, &lba))
1450     {
1451         return kStatus_USB_Error;
1452     }
1453 #else
1454     (void)mscHandle->configurationStruct->classCallback((class_handle_t)mscHandle, kUSB_DeviceMscEventWriteRequest,
1455                                                         &lba);
1456 #endif
1457 
1458     if (mscHandle->currentOffset <
1459         mscHandle->luInformations[mscHandle->mscCbw->logicalUnitNumber].totalLbaNumberSupports)
1460     {
1461         status = USB_DeviceRecvRequest(mscHandle->handle, mscHandle->bulkOutEndpoint, lba.buffer, lba.size);
1462     }
1463     else
1464     {
1465         mscHandle->needOutStallFlag     = 0U;
1466         mscHandle->outEndpointStallFlag = 1U;
1467         mscHandle->dataOutFlag          = 0U;
1468         mscHandle->stallStatus          = (uint8_t)USB_DEVICE_MSC_STALL_IN_DATA;
1469 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
1470         if (kStatus_USB_Success != USB_DeviceStallEndpoint(mscHandle->handle, mscHandle->bulkOutEndpoint))
1471         {
1472             return kStatus_USB_Error;
1473         }
1474 #else
1475         (void)USB_DeviceStallEndpoint(mscHandle->handle, mscHandle->bulkOutEndpoint);
1476 #endif
1477     }
1478     return status;
1479 }
1480 
1481 /*!
1482  * @brief Recv Send data through a specified endpoint.
1483  *
1484  * The function is used when ufi process read/write command .
1485  * The function calls USB_DeviceMscRecv or  usb_device_send_recv as the direction internally.
1486  *
1487  * @param handle The msc class handle got from usb_device_class_config_struct_t::classHandle.
1488  * @param direction     Data direction: 0 = Data-Out from host to the device, 1 = Data-In from the device to the host.
1489  * @param buffer The memory address to hold the data need to be sent.
1490  * @return A USB error code or kStatus_USB_Success.
1491  *
1492  * @note The return value just means if the sending or receiving request is successful or not.
1493  */
USB_DeviceMscLbaTransfer(usb_device_msc_struct_t * mscHandle,uint8_t direction,usb_lba_transfer_information_struct_t * lba_info_ptr)1494 usb_status_t USB_DeviceMscLbaTransfer(usb_device_msc_struct_t *mscHandle,
1495                                       uint8_t direction,
1496                                       usb_lba_transfer_information_struct_t *lba_info_ptr)
1497 {
1498     usb_status_t error = kStatus_USB_Success;
1499 
1500     mscHandle->transferRemaining =
1501         lba_info_ptr->transferNumber * mscHandle->luInformations[mscHandle->mscCbw->logicalUnitNumber].lengthOfEachLba;
1502     mscHandle->currentOffset = lba_info_ptr->startingLogicalBlockAddress;
1503 
1504     if (direction == USB_IN)
1505     {
1506         error = USB_DeviceMscSend(mscHandle);
1507     }
1508     else
1509     {
1510         error = USB_DeviceMscRecv(mscHandle);
1511     }
1512     return error;
1513 }
1514 #endif
1515