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 USB_DEVICE_CONFIG_MSC
16 #include "usb_device_msc.h"
17 #include "usb_device_msc_ufi.h"
18 
19 /*******************************************************************************
20  * Definitions
21  ******************************************************************************/
22 
23 /*******************************************************************************
24  * Prototypes
25  ******************************************************************************/
26 /*******************************************************************************
27  * Variables
28  ******************************************************************************/
29 /*******************************************************************************
30  * Code
31  ******************************************************************************/
32 
33 /*!
34  * @brief Thirteen possible case check.
35  *
36  * This function handle the thirteen possible cases of host expectations and device intent in the absence of
37  *overriding error conditions.
38  *
39  * @param handle          The device msc class handle.
40  *
41  *@return A USB error code or kStatus_USB_Success. more information about return value ,refer to
42  *USB_DeviceMscLbaTransfer and USB_DeviceRecvRequest
43  */
44 
USB_DeviceMscUfiThirteenCasesCheck(struct _usb_device_msc_struct * mscHandle)45 usb_status_t USB_DeviceMscUfiThirteenCasesCheck(struct _usb_device_msc_struct *mscHandle)
46 {
47     usb_status_t status = kStatus_USB_Success;
48     usb_device_msc_ufi_struct_t *ufi;
49     usb_device_msc_thirteen_case_struct_t *mscCheckEvent;
50 
51     mscCheckEvent = (usb_device_msc_thirteen_case_struct_t *)&mscHandle->mscUfi.thirteenCase;
52     ufi           = &mscHandle->mscUfi;
53     /* The following code describe the thirteen possible cases of host
54         expectations and device intent in absence of overriding error conditions ,refer to bulk-only spec chapter 6.7
55        The Thirteen Cases*/
56     if (mscCheckEvent->hostExpectedDataLength == 0U)
57     {
58         /*Host expects no data transfers*/
59         mscHandle->mscCsw->dataResidue = 0;
60         if (mscCheckEvent->deviceExpectedDataLength == 0U)
61         { /*case 1, Device intends to transfer no data*/
62             mscHandle->mscCsw->cswStatus = USB_DEVICE_MSC_COMMAND_PASSED;
63         }
64         else
65         { /*case 2 ,Device intends to send data to the host; */
66             /*case 3, Device intends to receive data from the host*/
67             /*set csw status to 02h*/
68             mscHandle->mscCsw->cswStatus = USB_DEVICE_MSC_PHASE_ERROR;
69         }
70     }
71     else if (0U != mscCheckEvent->hostExpectedDirection)
72     {
73         /*Host expects to receive data from the device*/
74         if (mscCheckEvent->deviceExpectedDataLength == 0U)
75         {
76             /*case 4, Device intends to transfer no data*/
77             mscHandle->mscCsw->dataResidue =
78                 mscCheckEvent->hostExpectedDataLength - mscCheckEvent->deviceExpectedDataLength;
79             status = USB_DeviceSendRequest(mscHandle->handle, mscHandle->bulkInEndpoint, mscCheckEvent->buffer,
80                                            mscCheckEvent->deviceExpectedDataLength);
81 
82             if (kStatus_USB_Success == status)
83             {
84                 mscHandle->mscCsw->cswStatus = USB_DEVICE_MSC_COMMAND_PASSED;
85             }
86             else
87             {
88                 mscHandle->mscCsw->cswStatus           = USB_DEVICE_MSC_COMMAND_FAILED;
89                 ufi->requestSense->senseKey            = USB_DEVICE_MSC_UFI_MEDIUM_ERROR;
90                 ufi->requestSense->additionalSenseCode = USB_DEVICE_MSC_UFI_UNRECOVERED_READ_ERROR;
91             }
92             status = kStatus_USB_InvalidRequest;
93         }
94         else if (0U != mscCheckEvent->deviceExpectedDirection)
95         {
96             if (mscCheckEvent->hostExpectedDataLength > mscCheckEvent->deviceExpectedDataLength)
97             {
98                 /*case 5, device intends to send less data than the host indicated*/
99                 mscHandle->mscCsw->dataResidue =
100                     mscCheckEvent->hostExpectedDataLength - mscCheckEvent->deviceExpectedDataLength;
101 
102                 if (ufi->thirteenCase.lbaSendRecvSelect == 1U)
103                 {
104                     status = USB_DeviceMscLbaTransfer(mscHandle, USB_IN, &mscCheckEvent->lbaInformation);
105                 }
106                 else
107                 {
108                     status = USB_DeviceSendRequest(mscHandle->handle, mscHandle->bulkInEndpoint, mscCheckEvent->buffer,
109                                                    mscCheckEvent->deviceExpectedDataLength);
110                 }
111 
112                 if (kStatus_USB_Success == status)
113                 {
114                     mscHandle->mscCsw->cswStatus = USB_DEVICE_MSC_COMMAND_PASSED;
115                 }
116                 else
117                 {
118                     mscHandle->mscCsw->cswStatus           = USB_DEVICE_MSC_COMMAND_FAILED;
119                     ufi->requestSense->senseKey            = USB_DEVICE_MSC_UFI_MEDIUM_ERROR;
120                     ufi->requestSense->additionalSenseCode = USB_DEVICE_MSC_UFI_UNRECOVERED_READ_ERROR;
121                 }
122                 status = kStatus_USB_InvalidRequest;
123             }
124             else if (mscCheckEvent->hostExpectedDataLength == mscCheckEvent->deviceExpectedDataLength)
125             { /*case 6*,device intends to send dCBWDataTransferLength excepted by the host*/
126                 mscHandle->mscCsw->dataResidue = 0;
127                 if (ufi->thirteenCase.lbaSendRecvSelect == 1U)
128                 {
129                     status = USB_DeviceMscLbaTransfer(mscHandle, USB_IN, &mscCheckEvent->lbaInformation);
130                 }
131                 else
132                 {
133                     status = USB_DeviceSendRequest(mscHandle->handle, mscHandle->bulkInEndpoint, mscCheckEvent->buffer,
134                                                    mscCheckEvent->deviceExpectedDataLength);
135                 }
136 
137                 if (kStatus_USB_Success == status)
138                 {
139                     mscHandle->mscCsw->cswStatus = USB_DEVICE_MSC_COMMAND_PASSED;
140                 }
141                 else
142                 {
143                     mscHandle->mscCsw->cswStatus           = USB_DEVICE_MSC_COMMAND_FAILED;
144                     ufi->requestSense->senseKey            = USB_DEVICE_MSC_UFI_MEDIUM_ERROR;
145                     ufi->requestSense->additionalSenseCode = USB_DEVICE_MSC_UFI_UNRECOVERED_READ_ERROR;
146                 }
147             }
148             else
149             { /*case 7, device intends to send more data than the host indicated*/
150                 mscHandle->mscCsw->dataResidue = 0U;
151 
152                 if (ufi->thirteenCase.lbaSendRecvSelect == 1U)
153                 {
154                     mscCheckEvent->lbaInformation.transferNumber =
155                         mscCheckEvent->hostExpectedDataLength /
156                         mscHandle->luInformations[mscHandle->mscCbw->logicalUnitNumber].lengthOfEachLba;
157                     mscHandle->mscCsw->dataResidue =
158                         mscCheckEvent->hostExpectedDataLength -
159                         mscCheckEvent->lbaInformation.transferNumber *
160                             mscHandle->luInformations[mscHandle->mscCbw->logicalUnitNumber].lengthOfEachLba;
161                     status = USB_DeviceMscLbaTransfer(mscHandle, USB_IN, &mscCheckEvent->lbaInformation);
162                 }
163                 else
164                 {
165                     status = USB_DeviceSendRequest(mscHandle->handle, mscHandle->bulkInEndpoint, mscCheckEvent->buffer,
166                                                    mscCheckEvent->hostExpectedDataLength);
167                 }
168 
169                 if (kStatus_USB_Success == status)
170                 {
171                     if (ufi->thirteenCase.lbaSendRecvSelect == 1U)
172                     {
173                         mscHandle->mscCsw->cswStatus = USB_DEVICE_MSC_PHASE_ERROR;
174                     }
175                     else
176                     {
177                         mscHandle->mscCsw->cswStatus = USB_DEVICE_MSC_COMMAND_PASSED;
178                     }
179                 }
180                 else
181                 {
182                     mscHandle->mscCsw->cswStatus           = USB_DEVICE_MSC_COMMAND_FAILED;
183                     ufi->requestSense->senseKey            = USB_DEVICE_MSC_UFI_MEDIUM_ERROR;
184                     ufi->requestSense->additionalSenseCode = USB_DEVICE_MSC_UFI_UNRECOVERED_READ_ERROR;
185                 }
186             }
187         }
188         else
189         {
190             /*case 8, device intends to receive data from the host*/
191             mscHandle->mscCsw->dataResidue = mscCheckEvent->hostExpectedDataLength;
192 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
193             if (kStatus_USB_Success !=
194                 USB_DeviceSendRequest(mscHandle->handle, mscHandle->bulkInEndpoint, mscCheckEvent->buffer, 0))
195             {
196                 return kStatus_USB_Error;
197             }
198 #else
199             (void)USB_DeviceSendRequest(mscHandle->handle, mscHandle->bulkInEndpoint, mscCheckEvent->buffer, 0);
200 #endif
201             mscHandle->mscCsw->cswStatus = USB_DEVICE_MSC_PHASE_ERROR;
202             status                       = kStatus_USB_InvalidRequest;
203         }
204     }
205     else
206     {
207         /*Host expects to send data to the device*/
208         if (0U == mscCheckEvent->deviceExpectedDataLength)
209         { /*case 9,Device intends to transfer no data*/
210 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
211             if (kStatus_USB_Success != USB_DeviceStallEndpoint(mscHandle->handle, mscHandle->bulkOutEndpoint))
212             {
213                 return kStatus_USB_Error;
214             }
215 #else
216             (void)USB_DeviceStallEndpoint(mscHandle->handle, mscHandle->bulkOutEndpoint);
217 #endif
218             mscHandle->mscCsw->dataResidue  = mscCheckEvent->hostExpectedDataLength;
219             mscHandle->mscCsw->cswStatus    = USB_DEVICE_MSC_COMMAND_FAILED;
220             mscHandle->outEndpointStallFlag = 1;
221             status                          = kStatus_USB_InvalidRequest;
222         }
223         else if (0U != mscCheckEvent->deviceExpectedDirection)
224         { /*case 10,Device intends to send data to the host*/
225 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
226             if (kStatus_USB_Success != USB_DeviceStallEndpoint(mscHandle->handle, mscHandle->bulkOutEndpoint))
227             {
228                 return kStatus_USB_Error;
229             }
230 #else
231             (void)USB_DeviceStallEndpoint(mscHandle->handle, mscHandle->bulkOutEndpoint);
232 #endif
233             mscHandle->mscCsw->dataResidue  = mscCheckEvent->hostExpectedDataLength;
234             mscHandle->mscCsw->cswStatus    = USB_DEVICE_MSC_PHASE_ERROR;
235             mscHandle->outEndpointStallFlag = 1U;
236             status                          = kStatus_USB_InvalidRequest;
237         }
238         else
239         {
240             if (mscCheckEvent->hostExpectedDataLength > mscCheckEvent->deviceExpectedDataLength)
241             { /*case 11, device intends to process less than the amount of data that the host indicated*/
242                 mscHandle->mscCsw->dataResidue =
243                     mscCheckEvent->hostExpectedDataLength - mscCheckEvent->deviceExpectedDataLength;
244 
245                 if (ufi->thirteenCase.lbaSendRecvSelect == 1U)
246                 {
247                     status = USB_DeviceMscLbaTransfer(mscHandle, USB_OUT, &mscCheckEvent->lbaInformation);
248                 }
249                 else
250                 {
251                     status = USB_DeviceRecvRequest(mscHandle->handle, mscHandle->bulkOutEndpoint, mscCheckEvent->buffer,
252                                                    mscCheckEvent->deviceExpectedDataLength);
253                 }
254 
255                 if (kStatus_USB_Success == status)
256                 {
257                     mscHandle->mscCsw->cswStatus = USB_DEVICE_MSC_COMMAND_PASSED;
258                 }
259                 else
260                 {
261                     mscHandle->mscCsw->cswStatus           = USB_DEVICE_MSC_COMMAND_FAILED;
262                     ufi->requestSense->senseKey            = USB_DEVICE_MSC_UFI_MEDIUM_ERROR;
263                     ufi->requestSense->additionalSenseCode = USB_DEVICE_MSC_UFI_WRITE_FAULT;
264                 }
265                 status = kStatus_USB_InvalidRequest;
266             }
267             else if (mscCheckEvent->hostExpectedDataLength == mscCheckEvent->deviceExpectedDataLength)
268             { /*case 12,device intends to process equal to the amount of data that the host indicated*/
269                 mscHandle->mscCsw->dataResidue = 0;
270                 if (ufi->thirteenCase.lbaSendRecvSelect == 1U)
271                 {
272                     status = USB_DeviceMscLbaTransfer(mscHandle, USB_OUT, &mscCheckEvent->lbaInformation);
273                 }
274                 else
275                 {
276                     status = USB_DeviceRecvRequest(mscHandle->handle, mscHandle->bulkOutEndpoint, mscCheckEvent->buffer,
277                                                    mscCheckEvent->deviceExpectedDataLength);
278                 }
279                 if (kStatus_USB_Success == status)
280                 {
281                     mscHandle->mscCsw->cswStatus = USB_DEVICE_MSC_COMMAND_PASSED;
282                 }
283                 else
284                 {
285                     mscHandle->mscCsw->cswStatus           = USB_DEVICE_MSC_COMMAND_FAILED;
286                     ufi->requestSense->senseKey            = USB_DEVICE_MSC_UFI_MEDIUM_ERROR;
287                     ufi->requestSense->additionalSenseCode = USB_DEVICE_MSC_UFI_WRITE_FAULT;
288                 }
289             }
290             else
291             { /*case 13,device  intends to process more data than the host indicated*/
292                 mscHandle->mscCsw->dataResidue = 0;
293                 if (ufi->thirteenCase.lbaSendRecvSelect == 1U)
294                 {
295                     mscCheckEvent->lbaInformation.transferNumber =
296                         mscCheckEvent->hostExpectedDataLength /
297                         mscHandle->luInformations[mscHandle->mscCbw->logicalUnitNumber].lengthOfEachLba;
298                     mscHandle->mscCsw->dataResidue =
299                         mscCheckEvent->hostExpectedDataLength -
300                         mscCheckEvent->lbaInformation.transferNumber *
301                             mscHandle->luInformations[mscHandle->mscCbw->logicalUnitNumber].lengthOfEachLba;
302                     status = USB_DeviceMscLbaTransfer(mscHandle, USB_OUT, &mscCheckEvent->lbaInformation);
303                 }
304                 else
305                 {
306                     status = USB_DeviceRecvRequest(mscHandle->handle, mscHandle->bulkOutEndpoint, mscCheckEvent->buffer,
307                                                    mscCheckEvent->hostExpectedDataLength);
308                 }
309 
310                 if (kStatus_USB_Success == status)
311                 {
312                     if (ufi->thirteenCase.lbaSendRecvSelect == 1U)
313                     {
314                         mscHandle->mscCsw->cswStatus = USB_DEVICE_MSC_PHASE_ERROR;
315                     }
316                     else
317                     {
318                         mscHandle->mscCsw->cswStatus = USB_DEVICE_MSC_COMMAND_PASSED;
319                     }
320                 }
321                 else
322                 {
323                     ufi->requestSense->senseKey            = USB_DEVICE_MSC_UFI_MEDIUM_ERROR;
324                     ufi->requestSense->additionalSenseCode = USB_DEVICE_MSC_UFI_WRITE_FAULT;
325                 }
326             }
327         }
328     }
329     return status;
330 }
331 
332 /*!
333  * @brief request sense command.
334  *
335  * The REQUEST SENSE command instructs the UFI device to transfer sense data to the host for the specified  logical
336  *unit.
337  *
338  * @param handle          The device msc class handle.
339  *
340  *@return A USB error code or kStatus_USB_Success.
341  */
USB_DeviceMscUfiRequestSenseCommand(struct _usb_device_msc_struct * mscHandle)342 usb_status_t USB_DeviceMscUfiRequestSenseCommand(struct _usb_device_msc_struct *mscHandle)
343 {
344     usb_device_msc_ufi_struct_t *ufi = NULL;
345     usb_status_t status;
346     usb_device_ufi_app_struct_t temp;
347 
348     ufi                    = &mscHandle->mscUfi;
349     temp.requestSense      = ufi->requestSense;
350     temp.cbwcb             = &mscHandle->mscCbw->cbwcb[0];
351     temp.logicalUnitNumber = mscHandle->mscCbw->logicalUnitNumber;
352     if (mscHandle->configurationStruct->classCallback != NULL)
353     {
354         /* classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
355         it is from the second parameter of classInit */
356 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
357         if (kStatus_USB_Success != mscHandle->configurationStruct->classCallback(
358                                        (class_handle_t)mscHandle, kUSB_DeviceMscEventRequestSense, (void *)&temp))
359         {
360             return kStatus_USB_Error;
361         }
362 #else
363         (void)mscHandle->configurationStruct->classCallback((class_handle_t)mscHandle, kUSB_DeviceMscEventRequestSense,
364                                                             (void *)&temp);
365 #endif
366     }
367 
368     ufi->thirteenCase.deviceExpectedDataLength = USB_DEVICE_MSC_UFI_REQ_SENSE_DATA_LENGTH;
369     ufi->thirteenCase.deviceExpectedDirection  = USB_IN;
370     ufi->thirteenCase.buffer                   = (uint8_t *)ufi->requestSense;
371     ufi->thirteenCase.lbaSendRecvSelect        = 0;
372     status                                     = USB_DeviceMscUfiThirteenCasesCheck(mscHandle);
373 
374     return status;
375 }
376 
377 /*!
378  * @brief inquiry command.
379  *
380  * The INQUIRY command requests that information regarding parameters of the UFI device itself be sent to the host.
381  *
382  * @param handle          The device msc class handle.
383  *
384  *@return A USB error code or kStatus_USB_Success.
385  */
USB_DeviceMscUfiInquiryCommand(struct _usb_device_msc_struct * mscHandle)386 usb_status_t USB_DeviceMscUfiInquiryCommand(struct _usb_device_msc_struct *mscHandle)
387 {
388     usb_device_msc_ufi_struct_t *ufi = NULL;
389     usb_status_t status;
390     usb_device_ufi_app_struct_t temp;
391 
392     ufi                    = &mscHandle->mscUfi;
393     temp.requestSense      = ufi->requestSense;
394     temp.cbwcb             = &mscHandle->mscCbw->cbwcb[0];
395     temp.size              = 0U;
396     temp.buffer            = NULL;
397     temp.logicalUnitNumber = mscHandle->mscCbw->logicalUnitNumber;
398 
399     if (mscHandle->configurationStruct->classCallback != NULL)
400     {
401         /* classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
402         it is from the second parameter of classInit */
403 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
404         if (kStatus_USB_Success != mscHandle->configurationStruct->classCallback(
405                                        (class_handle_t)mscHandle, kUSB_DeviceMscEventInquiry, (void *)&temp))
406         {
407             return kStatus_USB_Error;
408         }
409 #else
410         (void)mscHandle->configurationStruct->classCallback((class_handle_t)mscHandle, kUSB_DeviceMscEventInquiry,
411                                                             (void *)&temp);
412 #endif
413     }
414     ufi->thirteenCase.deviceExpectedDataLength = temp.size;
415     ufi->thirteenCase.deviceExpectedDirection  = USB_IN;
416     ufi->thirteenCase.buffer                   = temp.buffer;
417     ufi->thirteenCase.lbaSendRecvSelect        = 0;
418 
419     status = USB_DeviceMscUfiThirteenCasesCheck(mscHandle);
420     return status;
421 }
422 
423 /*!
424  * @brief read command.
425  *
426  * The READ(10),READ(12) command requests that the UFI device transfer data to the host.
427  *
428  * @param handle          The device msc class handle.
429  *
430  *@return A USB error code or kStatus_USB_Success.
431  */
USB_DeviceMscUfiReadCommand(struct _usb_device_msc_struct * mscHandle)432 usb_status_t USB_DeviceMscUfiReadCommand(struct _usb_device_msc_struct *mscHandle)
433 {
434     usb_device_msc_ufi_struct_t *ufi = NULL;
435     usb_status_t status;
436     uint32_t logicalBlockAddress = 0;
437     uint32_t lbaTransferLength   = 0;
438 
439     ufi = &mscHandle->mscUfi;
440 
441     logicalBlockAddress = ((uint32_t)mscHandle->mscCbw->cbwcb[2] << 24);
442     logicalBlockAddress |= ((uint32_t)mscHandle->mscCbw->cbwcb[3] << 16);
443     logicalBlockAddress |= ((uint32_t)mscHandle->mscCbw->cbwcb[4] << 8);
444     logicalBlockAddress |= ((uint32_t)mscHandle->mscCbw->cbwcb[5]);
445 
446     if (mscHandle->mscCbw->cbwcb[0] == USB_DEVICE_MSC_READ_10_COMMAND)
447     {
448         lbaTransferLength = (uint16_t)((uint16_t)mscHandle->mscCbw->cbwcb[7] << 8);
449         lbaTransferLength |= (uint16_t)mscHandle->mscCbw->cbwcb[8];
450     }
451     else if (mscHandle->mscCbw->cbwcb[0] == USB_DEVICE_MSC_READ_12_COMMAND)
452     {
453         lbaTransferLength = ((uint32_t)mscHandle->mscCbw->cbwcb[6] << 24);
454         lbaTransferLength |= ((uint32_t)mscHandle->mscCbw->cbwcb[7] << 16);
455         lbaTransferLength |= ((uint32_t)mscHandle->mscCbw->cbwcb[8] << 8);
456         lbaTransferLength |= ((uint32_t)mscHandle->mscCbw->cbwcb[9]);
457     }
458     else
459     {
460         /*no action*/
461     }
462 
463     ufi->thirteenCase.deviceExpectedDirection = USB_IN;
464     ufi->thirteenCase.deviceExpectedDataLength =
465         mscHandle->luInformations[mscHandle->mscCbw->logicalUnitNumber].lengthOfEachLba * lbaTransferLength;
466     ufi->thirteenCase.buffer = NULL;
467 
468     ufi->thirteenCase.lbaSendRecvSelect                          = 1U;
469     ufi->thirteenCase.lbaInformation.startingLogicalBlockAddress = logicalBlockAddress;
470     ufi->thirteenCase.lbaInformation.transferNumber              = lbaTransferLength;
471 
472     status = USB_DeviceMscUfiThirteenCasesCheck(mscHandle);
473     return status;
474 }
475 
476 /*!
477  * @brief write command.
478  *
479  * The WRITE(10),WRITE(12) command requests that the UFI device write the data transferred by the host to the medium.
480  *
481  * @param handle          The device msc class handle.
482  *
483  *@return A USB error code or kStatus_USB_Success.
484  */
USB_DeviceMscUfiWriteCommand(struct _usb_device_msc_struct * mscHandle)485 usb_status_t USB_DeviceMscUfiWriteCommand(struct _usb_device_msc_struct *mscHandle)
486 {
487     usb_device_msc_ufi_struct_t *ufi = NULL;
488     usb_status_t status;
489     uint32_t logicalBlockAddress = 0;
490     uint32_t lbaTransferLength   = 0;
491 
492     ufi = &mscHandle->mscUfi;
493 
494     logicalBlockAddress = ((uint32_t)mscHandle->mscCbw->cbwcb[2] << 24);
495     logicalBlockAddress |= ((uint32_t)mscHandle->mscCbw->cbwcb[3] << 16);
496     logicalBlockAddress |= ((uint32_t)mscHandle->mscCbw->cbwcb[4] << 8);
497     logicalBlockAddress |= ((uint32_t)mscHandle->mscCbw->cbwcb[5]);
498 
499     if (mscHandle->mscCbw->cbwcb[0] == USB_DEVICE_MSC_WRITE_10_COMMAND)
500     {
501         lbaTransferLength = (uint16_t)((uint16_t)mscHandle->mscCbw->cbwcb[7] << 8);
502         lbaTransferLength |= (uint16_t)mscHandle->mscCbw->cbwcb[8];
503     }
504     else if (mscHandle->mscCbw->cbwcb[0] == USB_DEVICE_MSC_WRITE_12_COMMAND)
505     {
506         lbaTransferLength = ((uint32_t)mscHandle->mscCbw->cbwcb[6] << 24);
507         lbaTransferLength |= ((uint32_t)mscHandle->mscCbw->cbwcb[7] << 16);
508         lbaTransferLength |= ((uint32_t)mscHandle->mscCbw->cbwcb[8] << 8);
509         lbaTransferLength |= ((uint32_t)mscHandle->mscCbw->cbwcb[9]);
510     }
511     else
512     {
513         /*no action*/
514     }
515     ufi->thirteenCase.deviceExpectedDirection = USB_OUT;
516     ufi->thirteenCase.deviceExpectedDataLength =
517         mscHandle->luInformations[mscHandle->mscCbw->logicalUnitNumber].lengthOfEachLba * lbaTransferLength;
518     ufi->thirteenCase.buffer = NULL;
519 
520     ufi->thirteenCase.lbaSendRecvSelect                          = 1U;
521     ufi->thirteenCase.lbaInformation.startingLogicalBlockAddress = logicalBlockAddress;
522     ufi->thirteenCase.lbaInformation.transferNumber              = lbaTransferLength;
523 
524     status = USB_DeviceMscUfiThirteenCasesCheck(mscHandle);
525     return status;
526 }
527 
528 /*!
529  * @brief test unit ready command.
530  *
531  * The TEST UNIT READY command provides a means to check if the UFI device is ready.
532  *
533  * @param handle          The device msc class handle.
534  *
535  *@return A USB error code or kStatus_USB_Success.
536  */
USB_DeviceMscUfiTestUnitReadyCommand(struct _usb_device_msc_struct * mscHandle)537 usb_status_t USB_DeviceMscUfiTestUnitReadyCommand(struct _usb_device_msc_struct *mscHandle)
538 {
539     usb_device_msc_ufi_struct_t *ufi = NULL;
540     usb_status_t status;
541     usb_device_ufi_app_struct_t temp;
542 
543     ufi                                        = &mscHandle->mscUfi;
544     temp.requestSense                          = ufi->requestSense;
545     temp.cbwcb                                 = &mscHandle->mscCbw->cbwcb[0];
546     temp.logicalUnitNumber                     = mscHandle->mscCbw->logicalUnitNumber;
547     ufi->thirteenCase.deviceExpectedDataLength = 0U;
548     ufi->thirteenCase.deviceExpectedDirection  = USB_IN;
549     ufi->thirteenCase.buffer                   = NULL;
550     ufi->thirteenCase.lbaSendRecvSelect        = 0U;
551 
552     status = USB_DeviceMscUfiThirteenCasesCheck(mscHandle);
553 
554     if (mscHandle->configurationStruct->classCallback != NULL)
555     {
556         /* classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
557         it is from the second parameter of classInit */
558 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
559         if (kStatus_USB_Success != mscHandle->configurationStruct->classCallback(
560                                        (class_handle_t)mscHandle, kUSB_DeviceMscEventTestUnitReady, (void *)&temp))
561         {
562             return kStatus_USB_Error;
563         }
564 #else
565         (void)mscHandle->configurationStruct->classCallback((class_handle_t)mscHandle, kUSB_DeviceMscEventTestUnitReady,
566                                                             (void *)&temp);
567 #endif
568     }
569     return status;
570 }
571 
572 /*!
573  * @brief verify command.
574  *
575  * The VERIFY command requests that the UFI device verify the data on the medium.
576  *
577  * @param handle          The device msc class handle.
578  *
579  *@return A USB error code or kStatus_USB_Success.
580  */
USB_DeviceMscUfiVerifyCommand(struct _usb_device_msc_struct * mscHandle)581 usb_status_t USB_DeviceMscUfiVerifyCommand(struct _usb_device_msc_struct *mscHandle)
582 {
583     usb_device_msc_ufi_struct_t *ufi = NULL;
584     usb_status_t status;
585 
586     ufi = &mscHandle->mscUfi;
587 
588     ufi->thirteenCase.deviceExpectedDataLength = 0;
589     ufi->thirteenCase.deviceExpectedDirection  = USB_IN;
590     ufi->thirteenCase.buffer                   = NULL;
591     ufi->thirteenCase.lbaSendRecvSelect        = 0U;
592 
593     status = USB_DeviceMscUfiThirteenCasesCheck(mscHandle);
594     return status;
595 }
596 
597 /*!
598  * @brief mode sense command.
599  *
600  * The MODE SENSE command allows the UFI device to report medium or device parameters to the host.
601  *
602  * @param handle          The device msc class handle.
603  *
604  *@return A USB error code or kStatus_USB_Success.
605  */
USB_DeviceMscUfiModeSenseCommand(struct _usb_device_msc_struct * mscHandle)606 usb_status_t USB_DeviceMscUfiModeSenseCommand(struct _usb_device_msc_struct *mscHandle)
607 {
608     usb_device_msc_ufi_struct_t *ufi = NULL;
609     usb_status_t status;
610 
611     usb_device_ufi_app_struct_t temp;
612 
613     ufi                    = &mscHandle->mscUfi;
614     temp.requestSense      = ufi->requestSense;
615     temp.cbwcb             = &mscHandle->mscCbw->cbwcb[0];
616     temp.size              = 0U;
617     temp.buffer            = NULL;
618     temp.logicalUnitNumber = mscHandle->mscCbw->logicalUnitNumber;
619 
620     if (mscHandle->configurationStruct->classCallback != NULL)
621     {
622         /* classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
623         it is from the second parameter of classInit */
624 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
625         if (kStatus_USB_Success != mscHandle->configurationStruct->classCallback(
626                                        (class_handle_t)mscHandle, kUSB_DeviceMscEventModeSense, (void *)&temp))
627         {
628             return kStatus_USB_Error;
629         }
630 #else
631         (void)mscHandle->configurationStruct->classCallback((class_handle_t)mscHandle, kUSB_DeviceMscEventModeSense,
632                                                             (void *)&temp);
633 #endif
634     }
635     ufi->thirteenCase.deviceExpectedDataLength = temp.size;
636     ufi->thirteenCase.deviceExpectedDirection  = USB_IN;
637     ufi->thirteenCase.buffer                   = temp.buffer;
638     ufi->thirteenCase.lbaSendRecvSelect        = 0U;
639 
640     status = USB_DeviceMscUfiThirteenCasesCheck(mscHandle);
641     return status;
642 }
643 
644 /*!
645  * @brief mode select command.
646  *
647  * The MODE SELECT command allows the host to specify medium or device parameters to the UFI device.
648  *
649  * @param handle          The device msc class handle.
650  *
651  *@return A USB error code or kStatus_USB_Success.
652  */
USB_DeviceMscUfiModeSelectCommand(struct _usb_device_msc_struct * mscHandle)653 usb_status_t USB_DeviceMscUfiModeSelectCommand(struct _usb_device_msc_struct *mscHandle)
654 {
655     usb_device_msc_ufi_struct_t *ufi = NULL;
656     usb_status_t status;
657 
658     usb_device_ufi_app_struct_t temp;
659 
660     ufi                    = &mscHandle->mscUfi;
661     temp.requestSense      = ufi->requestSense;
662     temp.cbwcb             = &mscHandle->mscCbw->cbwcb[0];
663     temp.buffer            = NULL;
664     temp.size              = 0U;
665     temp.logicalUnitNumber = mscHandle->mscCbw->logicalUnitNumber;
666 
667     if (mscHandle->configurationStruct->classCallback != NULL)
668     {
669         /* classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
670         it is from the second parameter of classInit */
671 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
672         if (kStatus_USB_Success != mscHandle->configurationStruct->classCallback(
673                                        (class_handle_t)mscHandle, kUSB_DeviceMscEventModeSelect, (void *)&temp))
674         {
675             return kStatus_USB_Error;
676         }
677 #else
678         (void)mscHandle->configurationStruct->classCallback((class_handle_t)mscHandle, kUSB_DeviceMscEventModeSelect,
679                                                             (void *)&temp);
680 #endif
681     }
682 
683     ufi->thirteenCase.deviceExpectedDataLength = temp.size;
684     ufi->thirteenCase.deviceExpectedDirection  = USB_OUT;
685     ufi->thirteenCase.buffer                   = temp.buffer;
686     ufi->thirteenCase.lbaSendRecvSelect        = 0;
687 
688     status = USB_DeviceMscUfiThirteenCasesCheck(mscHandle);
689 
690     if (0U != (mscHandle->mscCbw->cbwcb[1] & 0x01U))
691     {
692         ufi->requestSense->senseKey            = USB_DEVICE_MSC_UFI_ILLEGAL_REQUEST;
693         ufi->requestSense->additionalSenseCode = USB_DEVICE_MSC_UFI_INVALID_FIELD_IN_COMMAND_PKT;
694     }
695     return status;
696 }
697 
698 /*!
699  * @brief read capacity command.
700  *
701  * The READ CAPACITIY command allows the host to request capacities of the currently installed medium.
702  *
703  * @param handle          The device msc class handle.
704  *
705  *@return A USB error code or kStatus_USB_Success.
706  */
USB_DeviceMscUfiReadCapacityCommand(struct _usb_device_msc_struct * mscHandle)707 usb_status_t USB_DeviceMscUfiReadCapacityCommand(struct _usb_device_msc_struct *mscHandle)
708 {
709     usb_device_msc_ufi_struct_t *ufi = NULL;
710     usb_status_t status;
711     usb_device_capacity_information_struct_t diskInformation;
712     uint32_t deviceExpectedDataLength;
713     uint8_t logicalUnitNumber;
714 
715     ufi                                    = &mscHandle->mscUfi;
716     logicalUnitNumber                      = mscHandle->mscCbw->logicalUnitNumber;
717     diskInformation.logicalUnitNumber      = logicalUnitNumber;
718     diskInformation.lengthOfEachLba        = 0U;
719     diskInformation.totalLbaNumberSupports = 0U;
720     /* Get device information.*/
721     if (mscHandle->configurationStruct->classCallback != NULL)
722     {
723         /* classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
724         it is from the second parameter of classInit */
725 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
726         if (kStatus_USB_Success != mscHandle->configurationStruct->classCallback((class_handle_t)mscHandle,
727                                                                                  kUSB_DeviceMscEventReadCapacity,
728                                                                                  (void *)&diskInformation))
729         {
730             return kStatus_USB_Error;
731         }
732 #else
733         (void)mscHandle->configurationStruct->classCallback((class_handle_t)mscHandle, kUSB_DeviceMscEventReadCapacity,
734                                                             (void *)&diskInformation);
735 #endif
736     }
737 
738     if (logicalUnitNumber > mscHandle->logicalUnitNumber)
739     {
740         ufi->requestSense->senseKey = USB_DEVICE_MSC_UFI_ILLEGAL_REQUEST;
741         logicalUnitNumber           = 0;
742     }
743     if ((0U != diskInformation.lengthOfEachLba) && (0U != diskInformation.totalLbaNumberSupports))
744     {
745         mscHandle->luInformations[logicalUnitNumber].totalLbaNumberSupports = diskInformation.totalLbaNumberSupports;
746         mscHandle->luInformations[logicalUnitNumber].lengthOfEachLba        = diskInformation.lengthOfEachLba;
747         deviceExpectedDataLength = USB_DEVICE_MSC_UFI_READ_CAPACITY_DATA_LENGTH;
748     }
749     else
750     {
751         deviceExpectedDataLength = 0U;
752     }
753     if (mscHandle->mscCbw->cbwcb[0] == USB_DEVICE_MSC_READ_CAPACITY_10_COMMAND)
754     {
755         ufi->thirteenCase.deviceExpectedDataLength = deviceExpectedDataLength;
756         ufi->readCapacity->lastLogicalBlockAddress = USB_LONG_TO_BIG_ENDIAN(
757             mscHandle->luInformations[mscHandle->mscCbw->logicalUnitNumber].totalLbaNumberSupports - 1U);
758         ufi->readCapacity->blockSize = USB_LONG_TO_BIG_ENDIAN(
759             (uint32_t)mscHandle->luInformations[mscHandle->mscCbw->logicalUnitNumber].lengthOfEachLba);
760         ufi->thirteenCase.buffer = (uint8_t *)(ufi->readCapacity);
761     }
762     else
763     {
764         if (0U != deviceExpectedDataLength)
765         {
766             deviceExpectedDataLength = USB_DEVICE_MSC_UFI_READ_CAPACITY16_DATA_LENGTH;
767         }
768         ufi->thirteenCase.deviceExpectedDataLength    = deviceExpectedDataLength;
769         ufi->readCapacity16->lastLogicalBlockAddress1 = USB_LONG_TO_BIG_ENDIAN(
770             mscHandle->luInformations[mscHandle->mscCbw->logicalUnitNumber].totalLbaNumberSupports - 1U);
771         ufi->readCapacity16->blockSize = USB_LONG_TO_BIG_ENDIAN(
772             (uint32_t)mscHandle->luInformations[mscHandle->mscCbw->logicalUnitNumber].lengthOfEachLba);
773         ufi->thirteenCase.buffer = (uint8_t *)(ufi->readCapacity16);
774     }
775     ufi->thirteenCase.deviceExpectedDirection = USB_IN;
776     ufi->thirteenCase.lbaSendRecvSelect       = 0;
777 
778     status = USB_DeviceMscUfiThirteenCasesCheck(mscHandle);
779     return status;
780 }
781 
782 /*!
783  * @brief read format capacity command.
784  *
785  * The READ FORMAT CAPACITIES command allows the host to request a list of the possible capacities that
786  * can be formatted on the currently installed medium.
787  *
788  * @param handle          The device msc class handle.
789  *
790  *@return A USB error code or kStatus_USB_Success.
791  */
USB_DeviceMscUfiReadFormatCapacityCommand(struct _usb_device_msc_struct * mscHandle)792 usb_status_t USB_DeviceMscUfiReadFormatCapacityCommand(struct _usb_device_msc_struct *mscHandle)
793 {
794     usb_device_msc_ufi_struct_t *ufi = NULL;
795     usb_status_t status              = kStatus_USB_TransferFailed;
796     usb_device_capacity_information_struct_t diskInformation;
797     usb_device_current_max_capacity_descriptor_struct_t current_max_head;
798     usb_device_formattable_capacity_descriptor_struct_t formattable_capacity_head;
799     usb_device_capacity_list_header_struct_t capacityListHead = {{0x00, 0x00, 0x00}, 0x00};
800     uint32_t response_size;
801     uint16_t allocation_length;
802     uint8_t num_formattable_cap_desc;
803     uint8_t descriptor_code;
804     uint8_t count = 0;
805     uint8_t i     = 0;
806     uint8_t j     = 0;
807     uint8_t logicalUnitNumber;
808     uint8_t *ptr;
809 
810     ufi                                    = &mscHandle->mscUfi;
811     logicalUnitNumber                      = mscHandle->mscCbw->logicalUnitNumber;
812     diskInformation.logicalUnitNumber      = logicalUnitNumber;
813     diskInformation.lengthOfEachLba        = 0U;
814     diskInformation.totalLbaNumberSupports = 0U;
815     /* Get device information. */
816     if (mscHandle->configurationStruct->classCallback != NULL)
817     {
818         /* classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
819         it is from the second parameter of classInit */
820         status = mscHandle->configurationStruct->classCallback(
821             (class_handle_t)mscHandle, kUSB_DeviceMscEventReadFormatCapacity, (void *)&diskInformation);
822         if (kStatus_USB_Success != status)
823         {
824             return status;
825         }
826     }
827 
828     if (logicalUnitNumber > mscHandle->logicalUnitNumber)
829     {
830         ufi->requestSense->senseKey = USB_DEVICE_MSC_UFI_ILLEGAL_REQUEST;
831         logicalUnitNumber           = 0;
832     }
833     if ((0U != diskInformation.lengthOfEachLba) && (0U != diskInformation.totalLbaNumberSupports))
834     {
835         mscHandle->luInformations[logicalUnitNumber].totalLbaNumberSupports = diskInformation.totalLbaNumberSupports;
836         mscHandle->luInformations[logicalUnitNumber].lengthOfEachLba        = diskInformation.lengthOfEachLba;
837     }
838 
839     allocation_length = (uint16_t)((((uint16_t)mscHandle->mscCbw->cbwcb[7]) << 8) | mscHandle->mscCbw->cbwcb[8]);
840     /*reference ufi command spec table-33 Descriptor Code definition*/
841     num_formattable_cap_desc =
842         (uint8_t)((0U != ufi->formattedDisk) ? ((0U != mscHandle->implementingDiskDrive) ? 0x02U : 0x03U) : 0x00U);
843 
844     formattable_capacity_head.blockNumber =
845         USB_LONG_TO_BIG_ENDIAN(mscHandle->luInformations[mscHandle->mscCbw->logicalUnitNumber].totalLbaNumberSupports);
846     formattable_capacity_head.blockLength =
847         USB_LONG_TO_BIG_ENDIAN(mscHandle->luInformations[mscHandle->mscCbw->logicalUnitNumber].lengthOfEachLba);
848 
849     descriptor_code                     = (uint8_t)((0U != ufi->formattedDisk) ? USB_DEVICE_MSC_UFI_FORMATTED_MEDIA :
850                                                              USB_DEVICE_MSC_UFI_UNFORMATTED_MEDIA);
851     capacityListHead.capacityListLength = num_formattable_cap_desc * 8U;
852     current_max_head.blockNumber =
853         USB_LONG_TO_BIG_ENDIAN(mscHandle->luInformations[mscHandle->mscCbw->logicalUnitNumber].totalLbaNumberSupports);
854     current_max_head.descriptorCodeBlockLength =
855         USB_LONG_TO_BIG_ENDIAN(((((uint32_t)descriptor_code) << 24) |
856                                 mscHandle->luInformations[mscHandle->mscCbw->logicalUnitNumber].lengthOfEachLba));
857 
858     response_size = (uint32_t)sizeof(usb_device_capacity_list_header_struct_t) +
859                     sizeof(usb_device_current_max_capacity_descriptor_struct_t) +
860                     sizeof(usb_device_formattable_capacity_descriptor_struct_t) * ((uint32_t)num_formattable_cap_desc);
861 
862     if (response_size > allocation_length)
863     {
864         response_size = allocation_length;
865     }
866 
867     ptr = (uint8_t *)&capacityListHead;
868     for (count = 0U; count < sizeof(capacityListHead); count++)
869     {
870         ufi->formatCapacityData[count] = ptr[i++];
871     }
872     ptr = (uint8_t *)&current_max_head;
873 
874     for (i = 0U; i < sizeof(current_max_head); i++)
875     {
876         ufi->formatCapacityData[count] = ptr[i];
877         count++;
878     }
879 
880     if (0U != ufi->formattedDisk)
881     {
882         for (i = 0U; i < num_formattable_cap_desc; i++)
883         {
884             ptr = (uint8_t *)&formattable_capacity_head;
885 
886             for (; count < sizeof(formattable_capacity_head); count++)
887             {
888                 ufi->formatCapacityData[count] = ptr[j++];
889             }
890         }
891     }
892 
893     ufi->thirteenCase.deviceExpectedDataLength = response_size;
894     ufi->thirteenCase.deviceExpectedDirection  = USB_IN;
895     ufi->thirteenCase.buffer                   = (uint8_t *)ufi->formatCapacityData;
896     ufi->thirteenCase.lbaSendRecvSelect        = 0U;
897 
898     status = USB_DeviceMscUfiThirteenCasesCheck(mscHandle);
899 
900     return status;
901 }
902 
903 /*!
904  * @brief format unit command.
905  *
906  * The Host sends the FORMAT UNIT command to physically format one track of a diskette according to the selected
907  *options.
908  *
909  * @param handle          The device msc class handle.
910  *
911  *@return A USB error code or kStatus_USB_Success.
912  */
USB_DeviceMscUfiFormatUnitCommand(struct _usb_device_msc_struct * mscHandle)913 usb_status_t USB_DeviceMscUfiFormatUnitCommand(struct _usb_device_msc_struct *mscHandle)
914 {
915     usb_device_msc_ufi_struct_t *ufi = NULL;
916     usb_status_t status;
917 
918     ufi = &mscHandle->mscUfi;
919 
920     ufi->thirteenCase.deviceExpectedDataLength = 0U;
921     ufi->thirteenCase.deviceExpectedDirection  = USB_IN;
922     ufi->thirteenCase.buffer                   = NULL;
923     ufi->thirteenCase.lbaSendRecvSelect        = 0U;
924 
925     status = USB_DeviceMscUfiThirteenCasesCheck(mscHandle);
926 
927     if (mscHandle->mscCsw->cswStatus != USB_DEVICE_MSC_PHASE_ERROR)
928     {
929         if ((mscHandle->mscCbw->cbwcb[1] & 0x1fU) == 0x17U)
930         {
931             mscHandle->mscCsw->cswStatus = USB_DEVICE_MSC_COMMAND_PASSED;
932         }
933         else
934         {
935             mscHandle->mscCsw->cswStatus           = USB_DEVICE_MSC_COMMAND_FAILED;
936             ufi->requestSense->senseKey            = USB_DEVICE_MSC_UFI_ILLEGAL_REQUEST;
937             ufi->requestSense->additionalSenseCode = USB_DEVICE_MSC_UFI_INVALID_FIELD_IN_COMMAND_PKT;
938         }
939     }
940     return status;
941 }
942 
943 /*!
944  * @brief prevent allow medium command.
945  *
946  * This command tells the UFI device to enable or disable the removal of the medium in the logical unit.
947  *
948  * @param handle          The device msc class handle.
949  *
950  *@return A USB error code or kStatus_USB_Success.
951  */
USB_DeviceMscUfiPreventAllowMediumCommand(struct _usb_device_msc_struct * mscHandle)952 usb_status_t USB_DeviceMscUfiPreventAllowMediumCommand(struct _usb_device_msc_struct *mscHandle)
953 {
954     usb_device_msc_ufi_struct_t *ufi = NULL;
955     usb_status_t status;
956     usb_device_ufi_app_struct_t temp;
957 
958     ufi                    = &mscHandle->mscUfi;
959     temp.requestSense      = ufi->requestSense;
960     temp.cbwcb             = &mscHandle->mscCbw->cbwcb[0];
961     temp.logicalUnitNumber = mscHandle->mscCbw->logicalUnitNumber;
962 
963     ufi->thirteenCase.deviceExpectedDataLength = 0U;
964     ufi->thirteenCase.deviceExpectedDirection  = USB_IN;
965     ufi->thirteenCase.buffer                   = NULL;
966     ufi->thirteenCase.lbaSendRecvSelect        = 0U;
967 
968     status = USB_DeviceMscUfiThirteenCasesCheck(mscHandle);
969 
970     if (mscHandle->configurationStruct->classCallback != NULL)
971     {
972         /* classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
973         it is from the second parameter of classInit */
974 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
975         if (kStatus_USB_Success != mscHandle->configurationStruct->classCallback(
976                                        (class_handle_t)mscHandle, kUSB_DeviceMscEventRemovalRequest, (void *)&temp))
977         {
978             return kStatus_USB_Error;
979         }
980 #else
981         (void)mscHandle->configurationStruct->classCallback((class_handle_t)mscHandle,
982                                                             kUSB_DeviceMscEventRemovalRequest, (void *)&temp);
983 #endif
984     }
985 
986     return status;
987 }
988 
989 /*!
990  * @brief send diagnostic command.
991  *
992  * The SEND DIAGNOSTIC command requests the UFI device to do a reset or perform a self-test.
993  *
994  * @param handle          The device msc class handle.
995  *
996  *@return A USB error code or kStatus_USB_Success.
997  */
USB_DeviceMscUfiSendDiagnosticCommand(struct _usb_device_msc_struct * mscHandle)998 usb_status_t USB_DeviceMscUfiSendDiagnosticCommand(struct _usb_device_msc_struct *mscHandle)
999 {
1000     usb_device_msc_ufi_struct_t *ufi = NULL;
1001     usb_status_t status;
1002     usb_device_ufi_app_struct_t temp;
1003 
1004     ufi                    = &mscHandle->mscUfi;
1005     temp.requestSense      = ufi->requestSense;
1006     temp.cbwcb             = &mscHandle->mscCbw->cbwcb[0];
1007     temp.logicalUnitNumber = mscHandle->mscCbw->logicalUnitNumber;
1008 
1009     ufi->thirteenCase.deviceExpectedDataLength = 0;
1010     ufi->thirteenCase.deviceExpectedDirection  = USB_IN;
1011     ufi->thirteenCase.buffer                   = NULL;
1012     ufi->thirteenCase.lbaSendRecvSelect        = 0;
1013 
1014     status = USB_DeviceMscUfiThirteenCasesCheck(mscHandle);
1015     if (mscHandle->configurationStruct->classCallback != NULL)
1016     {
1017         /* classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
1018         it is from the second parameter of classInit */
1019 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
1020         if (kStatus_USB_Success != mscHandle->configurationStruct->classCallback(
1021                                        (class_handle_t)mscHandle, kUSB_DeviceMscEventSendDiagnostic, (void *)&temp))
1022         {
1023             return kStatus_USB_Error;
1024         }
1025 #else
1026         (void)mscHandle->configurationStruct->classCallback((class_handle_t)mscHandle,
1027                                                             kUSB_DeviceMscEventSendDiagnostic, (void *)&temp);
1028 #endif
1029     }
1030     return status;
1031 }
1032 
1033 /*!
1034  * @brief start stop unit command.
1035  *
1036  * The START-STOP UNIT command instructs the UFI device to enable or disable media access operations.
1037  *
1038  * @param handle          The device msc class handle.
1039  *
1040  *@return A USB error code or kStatus_USB_Success.
1041  */
USB_DeviceMscUfiStartStopUnitCommand(struct _usb_device_msc_struct * mscHandle)1042 usb_status_t USB_DeviceMscUfiStartStopUnitCommand(struct _usb_device_msc_struct *mscHandle)
1043 {
1044     usb_device_msc_ufi_struct_t *ufi = NULL;
1045     usb_status_t status;
1046     usb_device_ufi_app_struct_t temp;
1047 
1048     ufi                    = &mscHandle->mscUfi;
1049     temp.requestSense      = ufi->requestSense;
1050     temp.cbwcb             = &mscHandle->mscCbw->cbwcb[0];
1051     temp.logicalUnitNumber = mscHandle->mscCbw->logicalUnitNumber;
1052 
1053     ufi->thirteenCase.deviceExpectedDataLength = 0U;
1054     ufi->thirteenCase.deviceExpectedDirection  = USB_IN;
1055     ufi->thirteenCase.buffer                   = NULL;
1056     ufi->thirteenCase.lbaSendRecvSelect        = 0U;
1057 
1058     status = USB_DeviceMscUfiThirteenCasesCheck(mscHandle);
1059 
1060     if (mscHandle->mscCsw->cswStatus != USB_DEVICE_MSC_PHASE_ERROR)
1061     {
1062         if (mscHandle->configurationStruct->classCallback != NULL)
1063         {
1064             /* classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
1065             it is from the second parameter of classInit */
1066 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
1067             if (kStatus_USB_Success != mscHandle->configurationStruct->classCallback(
1068                                            (class_handle_t)mscHandle, kUSB_DeviceMscEventStopEjectMedia, (void *)&temp))
1069             {
1070                 return kStatus_USB_Error;
1071             }
1072 #else
1073             (void)mscHandle->configurationStruct->classCallback((class_handle_t)mscHandle,
1074                                                                 kUSB_DeviceMscEventStopEjectMedia, (void *)&temp);
1075 #endif
1076         }
1077     }
1078 
1079     return status;
1080 }
1081 
1082 /*!
1083  * @brief  un-support command.
1084  *
1085  * Handle unsupported command .
1086  *
1087  * @param handle          The device msc class handle.
1088  *
1089  *@return A USB error code or kStatus_USB_Success.
1090  */
USB_DeviceMscUfiUnsupportCommand(struct _usb_device_msc_struct * mscHandle)1091 usb_status_t USB_DeviceMscUfiUnsupportCommand(struct _usb_device_msc_struct *mscHandle)
1092 {
1093     usb_device_msc_ufi_struct_t *ufi = NULL;
1094     usb_status_t status;
1095     ufi = &mscHandle->mscUfi;
1096 
1097     mscHandle->mscCsw->dataResidue = 0;
1098     mscHandle->mscCsw->cswStatus   = USB_DEVICE_MSC_COMMAND_FAILED;
1099 
1100     ufi->thirteenCase.deviceExpectedDataLength = 0;
1101     ufi->requestSense->senseKey                = USB_DEVICE_MSC_UFI_ILLEGAL_REQUEST;
1102     ufi->requestSense->additionalSenseCode     = USB_DEVICE_MSC_UFI_INVALID_COMMAND_OPCODE;
1103     ufi->requestSense->additionalSenseQualifer = USB_DEVICE_MSC_UFI_NO_SENSE;
1104 
1105     status = USB_DeviceMscUfiThirteenCasesCheck(mscHandle);
1106 
1107     return status;
1108 }
1109 
1110 #endif
1111