1 /*
2  * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016, 2019 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "usb_host_config.h"
10 #if ((defined USB_HOST_CONFIG_MSD) && (USB_HOST_CONFIG_MSD))
11 #include "usb_host.h"
12 #include "usb_host_msd.h"
13 #include "usb_host_hci.h"
14 
15 /*******************************************************************************
16  * Definitions
17  ******************************************************************************/
18 
19 /*******************************************************************************
20  * Prototypes
21  ******************************************************************************/
22 
23 /*!
24  * @brief clear stall transfer callback.
25  *
26  * @param param    callback parameter.
27  * @param transfer transfer.
28  * @param status   transfer result status.
29  */
30 static void USB_HostMsdClearHaltCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
31 
32 /*!
33  * @brief send clear stall transfer.
34  *
35  * @param msdInstance     msd instance pointer.
36  * @param callbackFn  callback function.
37  * @param endpoint    endpoint address.
38  *
39  * @return An error code or kStatus_USB_Success.
40  */
41 static usb_status_t USB_HostMsdClearHalt(usb_host_msd_instance_t *msdInstance,
42                                          host_inner_transfer_callback_t callbackFn,
43                                          uint8_t endpoint);
44 
45 /*!
46  * @brief mass storage reset three step processes are done.
47  *
48  * @param msdInstance     msd instance pointer.
49  * @param status      result status.
50  */
51 static void USB_HostMsdResetDone(usb_host_msd_instance_t *msdInstance, usb_status_t status);
52 
53 /*!
54  * @brief mass storage reset process step 3 callback.
55  *
56  * @param msdInstance msd instance pointer.
57  * @param transfer     transfer
58  * @param status       result status.
59  */
60 static void USB_HostMsdMassResetClearOutCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
61 
62 /*!
63  * @brief mass storage reset process step 2 callback.
64  *
65  * @param msdInstance msd instance pointer.
66  * @transfer           transfer
67  * @param status       result status.
68  */
69 static void USB_HostMsdMassResetClearInCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
70 
71 /*!
72  * @brief mass storage reset process step 1 callback.
73  *
74  * @param msdInstance   msd instance pointer.
75  * @param transfer       transfer
76  * @param status         result status.
77  */
78 static void USB_HostMsdMassResetCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
79 
80 /*!
81  * @brief mass storage control transfer callback function.
82  *
83  * @param msdInstance   msd instance pointer.
84  * @param transfer       transfer
85  * @param status         result status.
86  */
87 static void USB_HostMsdControlCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
88 
89 /*!
90  * @brief this function is called when ufi command is done.
91  *
92  * @param msdInstance     msd instance pointer.
93  */
94 static void USB_HostMsdCommandDone(usb_host_msd_instance_t *msdInstance, usb_status_t status);
95 
96 /*!
97  * @brief csw transfer callback.
98  *
99  * @param msdInstance   msd instance pointer.
100  * @param transfer       transfer
101  * @param status         result status.
102  */
103 static void USB_HostMsdCswCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
104 
105 /*!
106  * @brief cbw transfer callback.
107  *
108  * @param msdInstance   msd instance pointer.
109  * @param transfer       transfer
110  * @param status         result status.
111  */
112 static void USB_HostMsdCbwCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
113 
114 /*!
115  * @brief data transfer callback.
116  *
117  * @param msdInstance   sd instance pointer.
118  * @param transfer       transfer
119  * @param status         result status.
120  */
121 static void USB_HostMsdDataCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
122 
123 /*!
124  * @brief msd open interface.
125  *
126  * @param msdInstance     msd instance pointer.
127  *
128  * @return kStatus_USB_Success or error codes.
129  */
130 static usb_status_t USB_HostMsdOpenInterface(usb_host_msd_instance_t *msdInstance);
131 
132 /*!
133  * @brief msd set interface callback, open pipes.
134  *
135  * @param param       callback parameter.
136  * @param transfer    callback transfer.
137  * @param status      transfer status.
138  */
139 static void USB_HostMsdSetInterfaceCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
140 
141 /*!
142  * @brief msd control transfer common code.
143  *
144  * This function allocate the resource for msd instance.
145  *
146  * @param msdInstance          the msd class instance.
147  * @param pipeCallbackFn       inner callback function.
148  * @param callbackFn           callback function.
149  * @param callbackParam        callback parameter.
150  * @param buffer               buffer pointer.
151  * @param bufferLength         buffer length.
152  * @param requestType          request type.
153  * @param requestValue         request value.
154  *
155  * @return An error code or kStatus_USB_Success.
156  */
157 static usb_status_t USB_HostMsdControl(usb_host_msd_instance_t *msdInstance,
158                                        host_inner_transfer_callback_t pipeCallbackFn,
159                                        transfer_callback_t callbackFn,
160                                        void *callbackParam,
161                                        uint8_t *buffer,
162                                        uint16_t bufferLength,
163                                        uint8_t requestType,
164                                        uint8_t requestValue);
165 
166 /*!
167  * @brief command process function, this function is called many time for one command's different state.
168  *
169  * @param msdInstance          the msd class instance.
170  *
171  * @return An error code or kStatus_USB_Success.
172  */
173 static usb_status_t USB_HostMsdProcessCommand(usb_host_msd_instance_t *msdInstance);
174 
175 /*******************************************************************************
176  * Variables
177  ******************************************************************************/
178 
179 /*******************************************************************************
180  * Code
181  ******************************************************************************/
182 
USB_HostMsdClearHaltCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)183 static void USB_HostMsdClearHaltCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
184 {
185     usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)param;
186 
187     if (status != kStatus_USB_Success)
188     {
189         USB_HostMsdCommandDone(msdInstance, kStatus_USB_TransferCancel);
190     }
191 
192     if (msdInstance->commandStatus == (uint8_t)kMSD_CommandErrorDone)
193     {
194         USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error); /* command fail */
195     }
196     else
197     {
198         (void)USB_HostMsdProcessCommand(msdInstance); /* continue to process ufi command */
199     }
200 }
201 
USB_HostMsdClearHalt(usb_host_msd_instance_t * msdInstance,host_inner_transfer_callback_t callbackFn,uint8_t endpoint)202 static usb_status_t USB_HostMsdClearHalt(usb_host_msd_instance_t *msdInstance,
203                                          host_inner_transfer_callback_t callbackFn,
204                                          uint8_t endpoint)
205 {
206     usb_status_t status;
207     usb_host_transfer_t *transfer;
208 
209     /* malloc one transfer */
210     status = USB_HostMallocTransfer(msdInstance->hostHandle, &transfer);
211     if (status != kStatus_USB_Success)
212     {
213 #ifdef HOST_ECHO
214         usb_echo("allocate transfer error\r\n");
215 #endif
216         return status;
217     }
218 
219     /* initialize transfer */
220     transfer->callbackFn                 = callbackFn;
221     transfer->callbackParam              = msdInstance;
222     transfer->transferBuffer             = NULL;
223     transfer->transferLength             = 0;
224     transfer->setupPacket->bRequest      = USB_REQUEST_STANDARD_CLEAR_FEATURE;
225     transfer->setupPacket->bmRequestType = USB_REQUEST_TYPE_RECIPIENT_ENDPOINT;
226     transfer->setupPacket->wValue  = USB_SHORT_TO_LITTLE_ENDIAN(USB_REQUEST_STANDARD_FEATURE_SELECTOR_ENDPOINT_HALT);
227     transfer->setupPacket->wIndex  = USB_SHORT_TO_LITTLE_ENDIAN(endpoint);
228     transfer->setupPacket->wLength = 0;
229     status                         = USB_HostSendSetup(msdInstance->hostHandle, msdInstance->controlPipe, transfer);
230 
231     if (status != kStatus_USB_Success)
232     {
233         (void)USB_HostFreeTransfer(msdInstance->hostHandle, transfer);
234     }
235     msdInstance->controlTransfer = transfer;
236 
237     return status;
238 }
239 
USB_HostMsdResetDone(usb_host_msd_instance_t * msdInstance,usb_status_t status)240 static void USB_HostMsdResetDone(usb_host_msd_instance_t *msdInstance, usb_status_t status)
241 {
242     if (msdInstance->internalResetRecovery == 1U) /* internal mass reset recovery */
243     {
244         msdInstance->internalResetRecovery = 0U;
245 
246         if ((status != kStatus_USB_Success) || (msdInstance->commandStatus == (uint8_t)kMSD_CommandErrorDone))
247         {
248             USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error); /* command fail */
249         }
250         else
251         {
252             (void)USB_HostMsdProcessCommand(msdInstance); /* continue to process ufi command */
253         }
254     }
255     else /* user call mass storage reset recovery */
256     {
257         if (msdInstance->controlCallbackFn != NULL)
258         {
259             /* callback to application, callback function is initialized in the USB_HostMsdControl,
260             or USB_HostMsdSetInterface, but is the same function */
261             msdInstance->controlCallbackFn(msdInstance->controlCallbackParam, NULL, 0,
262                                            status); /* callback to application */
263         }
264     }
265 }
266 
USB_HostMsdMassResetClearOutCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)267 static void USB_HostMsdMassResetClearOutCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
268 {
269     usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)param;
270 
271     msdInstance->controlTransfer = NULL;
272     (void)USB_HostFreeTransfer(msdInstance->hostHandle, transfer);
273     USB_HostMsdResetDone(msdInstance, status); /* mass storage reset done */
274 }
275 
USB_HostMsdMassResetClearInCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)276 static void USB_HostMsdMassResetClearInCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
277 {
278     usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)param;
279 
280     msdInstance->controlTransfer = NULL;
281     (void)USB_HostFreeTransfer(msdInstance->hostHandle, transfer);
282 
283     if (status == kStatus_USB_Success)
284     {
285         if (msdInstance->outPipe != NULL)
286         {
287             /* continue to process mass storage reset */
288             (void)USB_HostMsdClearHalt(
289                 msdInstance, USB_HostMsdMassResetClearOutCallback,
290                 (USB_REQUEST_TYPE_DIR_OUT | ((usb_host_pipe_t *)msdInstance->outPipe)->endpointAddress));
291         }
292     }
293     else
294     {
295         USB_HostMsdResetDone(msdInstance, status); /* mass storage reset done */
296     }
297 }
298 
USB_HostMsdMassResetCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)299 static void USB_HostMsdMassResetCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
300 {
301     usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)param;
302 
303     msdInstance->controlTransfer = NULL;
304     (void)USB_HostFreeTransfer(msdInstance->hostHandle, transfer);
305     if (status == kStatus_USB_Success)
306     {
307         if (msdInstance->inPipe != NULL)
308         {
309             /* continue to process mass storage reset */
310             (void)USB_HostMsdClearHalt(
311                 msdInstance, USB_HostMsdMassResetClearInCallback,
312                 (USB_REQUEST_TYPE_DIR_IN | ((usb_host_pipe_t *)msdInstance->inPipe)->endpointAddress));
313         }
314     }
315     else
316     {
317         USB_HostMsdResetDone(msdInstance, status); /* mass storage reset done */
318     }
319 }
320 
USB_HostMsdControlCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)321 static void USB_HostMsdControlCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
322 {
323     usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)param;
324 
325     msdInstance->controlTransfer = NULL;
326     if (msdInstance->controlCallbackFn != NULL)
327     {
328         /* callback to application, callback function is initialized in the USB_HostMsdControl,
329         or USB_HostMsdSetInterface, but is the same function */
330         msdInstance->controlCallbackFn(msdInstance->controlCallbackParam, transfer->transferBuffer,
331                                        transfer->transferSofar, status); /* callback to application */
332     }
333     (void)USB_HostFreeTransfer(msdInstance->hostHandle, transfer);
334 }
335 
USB_HostMsdCommandDone(usb_host_msd_instance_t * msdInstance,usb_status_t status)336 static void USB_HostMsdCommandDone(usb_host_msd_instance_t *msdInstance, usb_status_t status)
337 {
338     msdInstance->commandStatus = (uint8_t)kMSD_CommandIdle;
339     if (msdInstance->commandCallbackFn != NULL)
340     {
341         /* callback to application, the callback function is initialized in USB_HostMsdCommand */
342         msdInstance->commandCallbackFn(msdInstance->commandCallbackParam, msdInstance->msdCommand.dataBuffer,
343                                        msdInstance->msdCommand.dataSofar, status);
344     }
345 }
346 
USB_HostMsdCswCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)347 static void USB_HostMsdCswCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
348 {
349     usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)param;
350 
351     if (status == kStatus_USB_Success)
352     {
353         /* kStatus_USB_Success */
354         if ((transfer->transferSofar == USB_HOST_UFI_CSW_LENGTH) &&
355             (msdInstance->msdCommand.cswBlock->CSWSignature == USB_LONG_TO_LITTLE_ENDIAN(USB_HOST_MSD_CSW_SIGNATURE)))
356         {
357             switch (msdInstance->msdCommand.cswBlock->CSWStatus)
358             {
359                 case 0:
360                     USB_HostMsdCommandDone(msdInstance, kStatus_USB_Success);
361                     break;
362 
363                 case 1:
364                     USB_HostMsdCommandDone(msdInstance, kStatus_USB_MSDStatusFail);
365                     break;
366 
367                 case 2:
368                     msdInstance->internalResetRecovery = 1U;
369                     msdInstance->commandStatus         = (uint8_t)kMSD_CommandErrorDone;
370                     if (USB_HostMsdMassStorageReset(msdInstance, NULL, NULL) != kStatus_USB_Success)
371                     {
372                         USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error);
373                     }
374                     break;
375 
376                 default:
377                     USB_HostMsdCommandDone(msdInstance, kStatus_USB_MSDStatusFail);
378                     break;
379             }
380         }
381         else
382         {
383             /* mass reset recovery to end ufi command */
384             msdInstance->internalResetRecovery = 1U;
385             msdInstance->commandStatus         = (uint8_t)kMSD_CommandErrorDone;
386             if (USB_HostMsdMassStorageReset(msdInstance, NULL, NULL) != kStatus_USB_Success)
387             {
388                 USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error);
389             }
390         }
391     }
392     else
393     {
394         if (status == kStatus_USB_TransferStall) /* case 1: stall */
395         {
396             if (msdInstance->msdCommand.retryTime > 0U)
397             {
398                 msdInstance->msdCommand.retryTime--; /* retry reduce when error */
399             }
400             if (msdInstance->msdCommand.retryTime > 0U)
401             {
402                 /* clear stall to continue the ufi command */
403                 if (USB_HostMsdClearHalt(
404                         msdInstance, USB_HostMsdClearHaltCallback,
405                         (USB_REQUEST_TYPE_DIR_IN | ((usb_host_pipe_t *)msdInstance->inPipe)->endpointAddress)) !=
406                     kStatus_USB_Success)
407                 {
408                     USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error);
409                 }
410             }
411             else
412             {
413                 /* mass reset recovery to continue ufi command */
414                 msdInstance->internalResetRecovery = 1U;
415                 msdInstance->commandStatus         = (uint8_t)kMSD_CommandErrorDone;
416                 if (USB_HostMsdMassStorageReset(msdInstance, NULL, NULL) != kStatus_USB_Success)
417                 {
418                     USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error);
419                 }
420             }
421         }
422         else if (status == kStatus_USB_TransferCancel) /* case 2: cancel */
423         {
424             USB_HostMsdCommandDone(msdInstance, status); /* command cancel */
425         }
426         else /* case 3: error */
427         {
428             if (msdInstance->msdCommand.retryTime > 0U)
429             {
430                 msdInstance->msdCommand.retryTime--; /* retry reduce when error */
431             }
432             if (msdInstance->msdCommand.retryTime > 0U)
433             {
434                 (void)USB_HostMsdProcessCommand(msdInstance); /* retry the last step transaction */
435             }
436             else
437             {
438                 /* mass reset recovery to continue ufi command */
439                 msdInstance->internalResetRecovery = 1U;
440                 msdInstance->commandStatus         = (uint8_t)kMSD_CommandErrorDone;
441                 if (USB_HostMsdMassStorageReset(msdInstance, NULL, NULL) != kStatus_USB_Success)
442                 {
443                     USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error);
444                 }
445             }
446         }
447     }
448 }
449 
USB_HostMsdCbwCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)450 static void USB_HostMsdCbwCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
451 {
452     usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)param;
453 
454     if (status == kStatus_USB_Success)
455     {
456         /* kStatus_USB_Success */
457         if (transfer->transferSofar == USB_HOST_UFI_CBW_LENGTH)
458         {
459             if (NULL != msdInstance->msdCommand.dataBuffer)
460             {
461                 msdInstance->commandStatus = (uint8_t)kMSD_CommandTransferData;
462             }
463             else
464             {
465                 msdInstance->commandStatus = (uint8_t)kMSD_CommandTransferCSW;
466             }
467 
468             (void)USB_HostMsdProcessCommand(msdInstance); /* continue to process ufi command */
469         }
470         else
471         {
472             if (msdInstance->msdCommand.retryTime > 0U)
473             {
474                 msdInstance->msdCommand.retryTime--;
475             }
476             if (msdInstance->msdCommand.retryTime > 0U)
477             {
478                 (void)USB_HostMsdProcessCommand(msdInstance); /* retry the last step transaction */
479             }
480             else
481             {
482                 /* mass reset recovery to continue ufi command */
483                 msdInstance->internalResetRecovery = 1U;
484                 msdInstance->commandStatus         = (uint8_t)kMSD_CommandErrorDone;
485                 if (USB_HostMsdMassStorageReset(msdInstance, NULL, NULL) != kStatus_USB_Success)
486                 {
487                     (void)USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error);
488                 }
489             }
490         }
491     }
492     else
493     {
494         if (status == kStatus_USB_TransferStall) /* case 1: stall */
495         {
496             if (msdInstance->msdCommand.retryTime > 0U)
497             {
498                 msdInstance->msdCommand.retryTime--; /* retry reduce when error */
499             }
500             if (msdInstance->msdCommand.retryTime > 0U)
501             {
502                 /* clear stall to continue the ufi command */
503                 if (USB_HostMsdClearHalt(
504                         msdInstance, USB_HostMsdClearHaltCallback,
505                         (USB_REQUEST_TYPE_DIR_OUT | ((usb_host_pipe_t *)msdInstance->inPipe)->endpointAddress)) !=
506                     kStatus_USB_Success)
507                 {
508                     (void)USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error);
509                 }
510             }
511             else
512             {
513                 /* mass reset recovery to continue ufi command */
514                 msdInstance->internalResetRecovery = 1U;
515                 msdInstance->commandStatus         = (uint8_t)kMSD_CommandErrorDone;
516                 if (USB_HostMsdMassStorageReset(msdInstance, NULL, NULL) != kStatus_USB_Success)
517                 {
518                     USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error);
519                 }
520             }
521         }
522         else if (status == kStatus_USB_TransferCancel) /* case 2: cancel */
523         {
524             USB_HostMsdCommandDone(msdInstance, status); /* command cancel */
525         }
526         else /* case 3: error */
527         {
528             if (msdInstance->msdCommand.retryTime > 0U)
529             {
530                 msdInstance->msdCommand.retryTime--;
531             }
532             if (msdInstance->msdCommand.retryTime > 0U)
533             {
534                 (void)USB_HostMsdProcessCommand(msdInstance); /* retry the last step transaction */
535             }
536             else
537             {
538                 /* mass reset recovery to continue ufi command */
539                 msdInstance->internalResetRecovery = 1U;
540                 msdInstance->commandStatus         = (uint8_t)kMSD_CommandErrorDone;
541                 if (USB_HostMsdMassStorageReset(msdInstance, NULL, NULL) != kStatus_USB_Success)
542                 {
543                     USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error);
544                 }
545             }
546         }
547         return;
548     }
549 }
550 
USB_HostMsdDataCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)551 static void USB_HostMsdDataCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
552 {
553     usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)param;
554     uint8_t direction;
555 
556     if (status == kStatus_USB_Success)
557     {
558         /* kStatus_USB_Success */
559         msdInstance->msdCommand.dataSofar += transfer->transferSofar;
560         if (msdInstance->msdCommand.dataSofar >= msdInstance->msdCommand.dataLength)
561         {
562             msdInstance->commandStatus = (uint8_t)kMSD_CommandTransferCSW; /* next step */
563         }
564 
565         (void)USB_HostMsdProcessCommand(msdInstance); /* continue to process ufi command */
566     }
567     else
568     {
569         if (status == kStatus_USB_TransferStall) /* case 1: stall */
570         {
571             if (msdInstance->msdCommand.retryTime > 0U)
572             {
573                 msdInstance->msdCommand.retryTime--; /* retry reduce when error */
574             }
575             if (transfer->direction == USB_IN)
576             {
577                 direction = USB_REQUEST_TYPE_DIR_IN;
578             }
579             else
580             {
581                 direction = USB_REQUEST_TYPE_DIR_OUT;
582             }
583 
584             if (msdInstance->msdCommand.retryTime == 0U)
585             {
586                 msdInstance->commandStatus = (uint8_t)kMSD_CommandTransferCSW; /* next step */
587             }
588             /* clear stall to continue the ufi command */
589             if (USB_HostMsdClearHalt(msdInstance, USB_HostMsdClearHaltCallback,
590                                      (direction | ((usb_host_pipe_t *)msdInstance->inPipe)->endpointAddress)) !=
591                 kStatus_USB_Success)
592             {
593                 USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error);
594             }
595         }
596         else if (status == kStatus_USB_TransferCancel) /* case 2: cancel */
597         {
598             USB_HostMsdCommandDone(msdInstance, status); /* command cancel */
599         }
600         else /* case 3: error */
601         {
602             /* mass reset recovery to finish ufi command */
603             msdInstance->internalResetRecovery = 1U;
604             msdInstance->commandStatus         = (uint8_t)kMSD_CommandErrorDone;
605             if (USB_HostMsdMassStorageReset(msdInstance, NULL, NULL) != kStatus_USB_Success)
606             {
607                 USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error);
608             }
609         }
610     }
611 }
612 
USB_HostMsdProcessCommand(usb_host_msd_instance_t * msdInstance)613 static usb_status_t USB_HostMsdProcessCommand(usb_host_msd_instance_t *msdInstance)
614 {
615     usb_status_t status = kStatus_USB_Success;
616     usb_host_transfer_t *transfer;
617     usb_host_msd_command_status_t commandStatus;
618     if (msdInstance->msdCommand.transfer == NULL)
619     {
620         /* malloc one transfer */
621         status = USB_HostMallocTransfer(msdInstance->hostHandle, &(msdInstance->msdCommand.transfer));
622         if (status != kStatus_USB_Success)
623         {
624             msdInstance->msdCommand.transfer = NULL;
625 #ifdef HOST_ECHO
626             usb_echo("allocate transfer error\r\n");
627 #endif
628             return kStatus_USB_Busy;
629         }
630     }
631     transfer = msdInstance->msdCommand.transfer;
632 
633     commandStatus = (usb_host_msd_command_status_t)msdInstance->commandStatus;
634     switch (commandStatus)
635     {
636         case kMSD_CommandTransferCBW: /* ufi CBW phase */
637             transfer->direction      = USB_OUT;
638             transfer->transferBuffer = (uint8_t *)msdInstance->msdCommand.cbwBlock;
639             transfer->transferLength = USB_HOST_UFI_CBW_LENGTH;
640             transfer->callbackFn     = USB_HostMsdCbwCallback;
641             transfer->callbackParam  = msdInstance;
642             status                   = USB_HostSend(msdInstance->hostHandle, msdInstance->outPipe, transfer);
643             if (status != kStatus_USB_Success)
644             {
645 #ifdef HOST_ECHO
646                 usb_echo("host send error\r\n");
647 #endif
648             }
649             break;
650 
651         case kMSD_CommandTransferData: /* ufi DATA phase */
652             if (msdInstance->msdCommand.dataBuffer != NULL)
653             {
654                 transfer->direction      = msdInstance->msdCommand.dataDirection;
655                 transfer->transferBuffer = (msdInstance->msdCommand.dataBuffer + msdInstance->msdCommand.dataSofar);
656                 transfer->transferLength = (msdInstance->msdCommand.dataLength - msdInstance->msdCommand.dataSofar);
657                 transfer->callbackParam  = msdInstance;
658                 if (msdInstance->msdCommand.dataSofar != msdInstance->msdCommand.dataLength)
659                 {
660                     if (transfer->direction == USB_OUT)
661                     {
662                         transfer->callbackFn = USB_HostMsdDataCallback;
663                         status               = USB_HostSend(msdInstance->hostHandle, msdInstance->outPipe, transfer);
664                         if (status != kStatus_USB_Success)
665                         {
666 #ifdef HOST_ECHO
667                             usb_echo("host send error\r\n");
668 #endif
669                         }
670                     }
671                     else
672                     {
673                         transfer->callbackFn = USB_HostMsdDataCallback;
674                         status               = USB_HostRecv(msdInstance->hostHandle, msdInstance->inPipe, transfer);
675                         if (status != kStatus_USB_Success)
676                         {
677 #ifdef HOST_ECHO
678                             usb_echo("host recv error\r\n");
679 #endif
680                         }
681                     }
682                 }
683                 else
684                 {
685                     /* for misra check */
686                 }
687             }
688             break;
689         case kMSD_CommandTransferCSW: /* ufi CSW phase */
690             transfer->direction      = USB_IN;
691             transfer->transferBuffer = (uint8_t *)msdInstance->msdCommand.cswBlock;
692             transfer->transferLength = USB_HOST_UFI_CSW_LENGTH;
693             transfer->callbackFn     = USB_HostMsdCswCallback;
694             transfer->callbackParam  = msdInstance;
695             status                   = USB_HostRecv(msdInstance->hostHandle, msdInstance->inPipe, transfer);
696             if (status != kStatus_USB_Success)
697             {
698 #ifdef HOST_ECHO
699                 usb_echo("host recv error\r\n");
700 #endif
701             }
702             break;
703 
704         case kMSD_CommandDone:
705             USB_HostMsdCommandDone(msdInstance, kStatus_USB_Success);
706             break;
707 
708         default:
709             /*no action*/
710             break;
711     }
712     return status;
713 }
714 
715 /*!
716  * @brief all ufi function calls this api.
717  *
718  * This function implements the common ufi commands.
719  *
720  * @param classHandle   the class msd handle.
721  * @param buffer         buffer pointer.
722  * @param bufferLength     buffer length.
723  * @param callbackFn    callback function.
724  * @param callbackParam callback parameter.
725  * @param direction      command direction.
726  * @param byteValues    ufi command fields value.
727  *
728  * @return An error code or kStatus_USB_Success.
729  */
USB_HostMsdCommand(usb_host_class_handle classHandle,uint8_t * buffer,uint32_t bufferLength,transfer_callback_t callbackFn,void * callbackParam,uint8_t direction,uint8_t byteValues[10])730 usb_status_t USB_HostMsdCommand(usb_host_class_handle classHandle,
731                                 uint8_t *buffer,
732                                 uint32_t bufferLength,
733                                 transfer_callback_t callbackFn,
734                                 void *callbackParam,
735                                 uint8_t direction,
736                                 uint8_t byteValues[10])
737 {
738     usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)classHandle;
739     usb_host_cbw_t *cbwPointer           = msdInstance->msdCommand.cbwBlock;
740     uint8_t index                        = 0;
741 
742     if (classHandle == NULL)
743     {
744         return kStatus_USB_InvalidHandle;
745     }
746 
747     if (msdInstance->commandStatus != (uint8_t)kMSD_CommandIdle)
748     {
749         return kStatus_USB_Busy;
750     }
751 
752     /* save the application callback function */
753     msdInstance->commandCallbackFn    = callbackFn;
754     msdInstance->commandCallbackParam = callbackParam;
755 
756     /* initialize CBWCB fields */
757     for (index = 0; index < USB_HOST_UFI_BLOCK_DATA_VALID_LENGTH; ++index)
758     {
759         cbwPointer->CBWCB[index] = byteValues[index];
760     }
761 
762     /* initialize CBW fields */
763     cbwPointer->CBWDataTransferLength = USB_LONG_TO_LITTLE_ENDIAN(bufferLength);
764     cbwPointer->CBWFlags              = direction;
765     cbwPointer->CBWLun                = (byteValues[1] >> USB_HOST_UFI_LOGICAL_UNIT_POSITION);
766     cbwPointer->CBWCBLength           = USB_HOST_UFI_BLOCK_DATA_VALID_LENGTH;
767 
768     msdInstance->commandStatus = (uint8_t)kMSD_CommandTransferCBW;
769     if (direction == USB_HOST_MSD_CBW_FLAGS_DIRECTION_IN)
770     {
771         msdInstance->msdCommand.dataDirection = USB_IN;
772     }
773     else
774     {
775         msdInstance->msdCommand.dataDirection = USB_OUT;
776     }
777     msdInstance->msdCommand.dataBuffer = buffer;
778 
779     msdInstance->msdCommand.dataLength = bufferLength;
780     msdInstance->msdCommand.dataSofar  = 0;
781     msdInstance->msdCommand.retryTime  = USB_HOST_MSD_RETRY_MAX_TIME;
782 
783     return USB_HostMsdProcessCommand(msdInstance); /* start to process ufi command */
784 }
785 
USB_HostMsdOpenInterface(usb_host_msd_instance_t * msdInstance)786 static usb_status_t USB_HostMsdOpenInterface(usb_host_msd_instance_t *msdInstance)
787 {
788     usb_status_t status;
789     uint8_t epIndex = 0;
790     usb_host_pipe_init_t pipeInit;
791     usb_descriptor_endpoint_t *epDesc = NULL;
792     usb_host_interface_t *interfacePointer;
793 
794     if (msdInstance->inPipe != NULL) /* close bulk in pipe if the pipe is open */
795     {
796         status = USB_HostClosePipe(msdInstance->hostHandle, msdInstance->inPipe);
797         if (status != kStatus_USB_Success)
798         {
799 #ifdef HOST_ECHO
800             usb_echo("error when close pipe\r\n");
801 #endif
802         }
803         msdInstance->inPipe = NULL;
804     }
805     if (msdInstance->outPipe != NULL) /* close bulk out pipe if the pipe is open */
806     {
807         status = USB_HostClosePipe(msdInstance->hostHandle, msdInstance->outPipe);
808         if (status != kStatus_USB_Success)
809         {
810 #ifdef HOST_ECHO
811             usb_echo("error when close pipe\r\n");
812 #endif
813         }
814         msdInstance->outPipe = NULL;
815     }
816 
817     /* open interface pipes */
818     interfacePointer = (usb_host_interface_t *)msdInstance->interfaceHandle;
819     for (epIndex = 0; epIndex < interfacePointer->epCount; ++epIndex)
820     {
821         epDesc = interfacePointer->epList[epIndex].epDesc;
822         if (((epDesc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) ==
823              USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_IN) &&
824             ((epDesc->bmAttributes & USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_TYPE_MASK) == USB_ENDPOINT_BULK))
825         {
826             pipeInit.devInstance     = msdInstance->deviceHandle;
827             pipeInit.pipeType        = USB_ENDPOINT_BULK;
828             pipeInit.direction       = USB_IN;
829             pipeInit.endpointAddress = (epDesc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK);
830             pipeInit.interval        = epDesc->bInterval;
831             pipeInit.maxPacketSize   = (uint16_t)((USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(epDesc->wMaxPacketSize) &
832                                                  USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK));
833             pipeInit.numberPerUframe = (uint8_t)((USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(epDesc->wMaxPacketSize) &
834                                                   USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_MASK));
835             pipeInit.nakCount        = USB_HOST_CONFIG_MAX_NAK;
836 
837             status = USB_HostOpenPipe(msdInstance->hostHandle, &msdInstance->inPipe, &pipeInit);
838             if (status != kStatus_USB_Success)
839             {
840 #ifdef HOST_ECHO
841                 usb_echo("usb_host_hid_set_interface fail to open pipe\r\n");
842 #endif
843                 return status;
844             }
845         }
846         else if (((epDesc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) ==
847                   USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_OUT) &&
848                  ((epDesc->bmAttributes & USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_TYPE_MASK) == USB_ENDPOINT_BULK))
849         {
850             pipeInit.devInstance     = msdInstance->deviceHandle;
851             pipeInit.pipeType        = USB_ENDPOINT_BULK;
852             pipeInit.direction       = USB_OUT;
853             pipeInit.endpointAddress = (epDesc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK);
854             pipeInit.interval        = epDesc->bInterval;
855             pipeInit.maxPacketSize   = (uint16_t)((USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(epDesc->wMaxPacketSize) &
856                                                  USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK));
857             pipeInit.numberPerUframe = (uint8_t)((USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(epDesc->wMaxPacketSize) &
858                                                   USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_MASK));
859             pipeInit.nakCount        = USB_HOST_CONFIG_MAX_NAK;
860 
861             status = USB_HostOpenPipe(msdInstance->hostHandle, &msdInstance->outPipe, &pipeInit);
862             if (status != kStatus_USB_Success)
863             {
864 #ifdef HOST_ECHO
865                 usb_echo("usb_host_hid_set_interface fail to open pipe\r\n");
866 #endif
867                 return status;
868             }
869         }
870         else
871         {
872         }
873     }
874 
875     return kStatus_USB_Success;
876 }
877 
USB_HostMsdSetInterfaceCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)878 static void USB_HostMsdSetInterfaceCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
879 {
880     usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)param;
881 
882     msdInstance->controlTransfer = NULL;
883     if (status == kStatus_USB_Success)
884     {
885         status = USB_HostMsdOpenInterface(msdInstance); /* msd open interface */
886     }
887 
888     if (msdInstance->controlCallbackFn != NULL)
889     {
890         /* callback to application, callback function is initialized in the USB_HostMsdControl,
891         or USB_HostMsdSetInterface, but is the same function */
892         msdInstance->controlCallbackFn(msdInstance->controlCallbackParam, NULL, 0,
893                                        status); /* callback to application */
894     }
895     (void)USB_HostFreeTransfer(msdInstance->hostHandle, transfer);
896 }
897 
USB_HostMsdInit(usb_device_handle deviceHandle,usb_host_class_handle * classHandle)898 usb_status_t USB_HostMsdInit(usb_device_handle deviceHandle, usb_host_class_handle *classHandle)
899 {
900     uint32_t infoValue = 0U;
901     usb_status_t status;
902     uint32_t *temp;
903     usb_host_msd_instance_t *msdInstance =
904         (usb_host_msd_instance_t *)OSA_MemoryAllocate(sizeof(usb_host_msd_instance_t)); /* malloc msd class instance */
905 
906     if (msdInstance == NULL)
907     {
908         return kStatus_USB_AllocFail;
909     }
910 
911 #if ((defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE)) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U))
912     msdInstance->msdCommand.cbwBlock =
913         (usb_host_cbw_t *)OSA_MemoryAllocateAlign(sizeof(usb_host_cbw_t), USB_CACHE_LINESIZE);
914     msdInstance->msdCommand.cswBlock =
915         (usb_host_csw_t *)OSA_MemoryAllocateAlign(sizeof(usb_host_csw_t), USB_CACHE_LINESIZE);
916 #else
917     msdInstance->msdCommand.cbwBlock = (usb_host_cbw_t *)OSA_MemoryAllocate(sizeof(usb_host_cbw_t));
918     msdInstance->msdCommand.cswBlock = (usb_host_csw_t *)OSA_MemoryAllocate(sizeof(usb_host_csw_t));
919 #endif
920 
921     /* initialize msd instance */
922     msdInstance->deviceHandle    = deviceHandle;
923     msdInstance->interfaceHandle = NULL;
924     (void)USB_HostHelperGetPeripheralInformation(deviceHandle, (uint32_t)kUSB_HostGetHostHandle, &infoValue);
925     temp                    = (uint32_t *)infoValue;
926     msdInstance->hostHandle = (usb_host_handle)temp;
927     (void)USB_HostHelperGetPeripheralInformation(deviceHandle, (uint32_t)kUSB_HostGetDeviceControlPipe, &infoValue);
928     temp                                          = (uint32_t *)infoValue;
929     msdInstance->controlPipe                      = (usb_host_pipe_handle)temp;
930     msdInstance->msdCommand.cbwBlock->CBWSignature = USB_LONG_TO_LITTLE_ENDIAN(USB_HOST_MSD_CBW_SIGNATURE);
931     status = USB_HostMallocTransfer(msdInstance->hostHandle, &(msdInstance->msdCommand.transfer));
932     if (status != kStatus_USB_Success)
933     {
934         msdInstance->msdCommand.transfer = NULL;
935 #ifdef HOST_ECHO
936         usb_echo("allocate transfer error\r\n");
937 #endif
938     }
939 
940     *classHandle = msdInstance;
941     return kStatus_USB_Success;
942 }
943 
USB_HostMsdSetInterface(usb_host_class_handle classHandle,usb_host_interface_handle interfaceHandle,uint8_t alternateSetting,transfer_callback_t callbackFn,void * callbackParam)944 usb_status_t USB_HostMsdSetInterface(usb_host_class_handle classHandle,
945                                      usb_host_interface_handle interfaceHandle,
946                                      uint8_t alternateSetting,
947                                      transfer_callback_t callbackFn,
948                                      void *callbackParam)
949 {
950     usb_status_t status;
951     usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)classHandle;
952     usb_host_transfer_t *transfer;
953 
954     if (classHandle == NULL)
955     {
956         return kStatus_USB_InvalidHandle;
957     }
958 
959     status = USB_HostOpenDeviceInterface(msdInstance->deviceHandle,
960                                          interfaceHandle); /* notify host driver the interface is open */
961     if (status != kStatus_USB_Success)
962     {
963         return status;
964     }
965     msdInstance->interfaceHandle = interfaceHandle;
966 
967     /* cancel transfers */
968     if (msdInstance->inPipe != NULL)
969     {
970         status = USB_HostCancelTransfer(msdInstance->hostHandle, msdInstance->inPipe, NULL);
971         if (status != kStatus_USB_Success)
972         {
973 #ifdef HOST_ECHO
974             usb_echo("error when cancel pipe\r\n");
975 #endif
976         }
977     }
978     if (msdInstance->outPipe != NULL)
979     {
980         status = USB_HostCancelTransfer(msdInstance->hostHandle, msdInstance->outPipe, NULL);
981         if (status != kStatus_USB_Success)
982         {
983 #ifdef HOST_ECHO
984             usb_echo("error when cancel pipe\r\n");
985 #endif
986         }
987     }
988 
989     if (alternateSetting == 0U) /* open interface directly */
990     {
991         if (callbackFn != NULL)
992         {
993             status = USB_HostMsdOpenInterface(msdInstance);
994             callbackFn(callbackParam, NULL, 0, status);
995         }
996     }
997     else /* send setup transfer */
998     {
999         /* malloc one transfer */
1000         if (USB_HostMallocTransfer(msdInstance->hostHandle, &transfer) != kStatus_USB_Success)
1001         {
1002 #ifdef HOST_ECHO
1003             usb_echo("error to get transfer\r\n");
1004 #endif
1005             return kStatus_USB_Busy;
1006         }
1007         /* save the application callback function */
1008         msdInstance->controlCallbackFn    = callbackFn;
1009         msdInstance->controlCallbackParam = callbackParam;
1010         /* initialize transfer */
1011         transfer->callbackFn                 = USB_HostMsdSetInterfaceCallback;
1012         transfer->callbackParam              = msdInstance;
1013         transfer->setupPacket->bRequest      = USB_REQUEST_STANDARD_SET_INTERFACE;
1014         transfer->setupPacket->bmRequestType = USB_REQUEST_TYPE_RECIPIENT_INTERFACE;
1015         transfer->setupPacket->wIndex        = USB_SHORT_TO_LITTLE_ENDIAN(
1016             ((usb_host_interface_t *)msdInstance->interfaceHandle)->interfaceDesc->bInterfaceNumber);
1017         transfer->setupPacket->wValue  = USB_SHORT_TO_LITTLE_ENDIAN(alternateSetting);
1018         transfer->setupPacket->wLength = 0;
1019         transfer->transferBuffer       = NULL;
1020         transfer->transferLength       = 0;
1021         status                         = USB_HostSendSetup(msdInstance->hostHandle, msdInstance->controlPipe, transfer);
1022 
1023         if (status == kStatus_USB_Success)
1024         {
1025             msdInstance->controlTransfer = transfer;
1026         }
1027         else
1028         {
1029             (void)USB_HostFreeTransfer(msdInstance->hostHandle, transfer);
1030         }
1031     }
1032 
1033     return status;
1034 }
1035 
USB_HostMsdDeinit(usb_device_handle deviceHandle,usb_host_class_handle classHandle)1036 usb_status_t USB_HostMsdDeinit(usb_device_handle deviceHandle, usb_host_class_handle classHandle)
1037 {
1038     usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)classHandle;
1039     usb_status_t status;
1040 
1041     if (classHandle != NULL)
1042     {
1043         if (msdInstance->inPipe != NULL)
1044         {
1045             status = USB_HostCancelTransfer(msdInstance->hostHandle, msdInstance->inPipe, NULL); /* cancel pipe */
1046             if (status != kStatus_USB_Success)
1047             {
1048 #ifdef HOST_ECHO
1049                 usb_echo("error when cancel pipe\r\n");
1050 #endif
1051             }
1052             status = USB_HostClosePipe(msdInstance->hostHandle, msdInstance->inPipe); /* close pipe */
1053             if (status != kStatus_USB_Success)
1054             {
1055 #ifdef HOST_ECHO
1056                 usb_echo("error when close pipe\r\n");
1057 #endif
1058             }
1059         }
1060         if (msdInstance->outPipe != NULL)
1061         {
1062             status = USB_HostCancelTransfer(msdInstance->hostHandle, msdInstance->outPipe, NULL); /* cancel pipe */
1063             if (status != kStatus_USB_Success)
1064             {
1065 #ifdef HOST_ECHO
1066                 usb_echo("error when cancel pipe\r\n");
1067 #endif
1068             }
1069             status = USB_HostClosePipe(msdInstance->hostHandle, msdInstance->outPipe); /* close pipe */
1070             if (status != kStatus_USB_Success)
1071             {
1072 #ifdef HOST_ECHO
1073                 usb_echo("error when close pipe\r\n");
1074 #endif
1075             }
1076         }
1077         if ((msdInstance->controlPipe != NULL) &&
1078             (msdInstance->controlTransfer != NULL)) /* cancel control transfer if there is on-going control transfer */
1079         {
1080             status =
1081                 USB_HostCancelTransfer(msdInstance->hostHandle, msdInstance->controlPipe, msdInstance->controlTransfer);
1082             if (status != kStatus_USB_Success)
1083             {
1084 #ifdef HOST_ECHO
1085                 usb_echo("error when cancel pipe\r\n");
1086 #endif
1087             }
1088         }
1089         if (NULL != msdInstance->msdCommand.transfer)
1090         {
1091             (void)USB_HostFreeTransfer(msdInstance->hostHandle, msdInstance->msdCommand.transfer);
1092         }
1093         (void)USB_HostCloseDeviceInterface(
1094             deviceHandle, msdInstance->interfaceHandle); /* notify host driver the interface is closed */
1095 #if ((defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE)) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U))
1096         OSA_MemoryFreeAlign(msdInstance->msdCommand.cbwBlock);
1097         OSA_MemoryFreeAlign(msdInstance->msdCommand.cswBlock);
1098 #else
1099         OSA_MemoryFree(msdInstance->msdCommand.cbwBlock);
1100         OSA_MemoryFree(msdInstance->msdCommand.cswBlock);
1101 #endif
1102         OSA_MemoryFree(msdInstance);
1103     }
1104     else
1105     {
1106         (void)USB_HostCloseDeviceInterface(deviceHandle, NULL);
1107     }
1108 
1109     return kStatus_USB_Success;
1110 }
1111 
USB_HostMsdControl(usb_host_msd_instance_t * msdInstance,host_inner_transfer_callback_t pipeCallbackFn,transfer_callback_t callbackFn,void * callbackParam,uint8_t * buffer,uint16_t bufferLength,uint8_t requestType,uint8_t requestValue)1112 static usb_status_t USB_HostMsdControl(usb_host_msd_instance_t *msdInstance,
1113                                        host_inner_transfer_callback_t pipeCallbackFn,
1114                                        transfer_callback_t callbackFn,
1115                                        void *callbackParam,
1116                                        uint8_t *buffer,
1117                                        uint16_t bufferLength,
1118                                        uint8_t requestType,
1119                                        uint8_t requestValue)
1120 {
1121     usb_host_transfer_t *transfer;
1122 
1123     if (msdInstance == NULL)
1124     {
1125         return kStatus_USB_InvalidHandle;
1126     }
1127 
1128     /* malloc one transfer */
1129     if (USB_HostMallocTransfer(msdInstance->hostHandle, &transfer) != kStatus_USB_Success)
1130     {
1131 #ifdef HOST_ECHO
1132         usb_echo("allocate transfer error\r\n");
1133 #endif
1134         return kStatus_USB_Busy;
1135     }
1136     /* save the application callback function */
1137     msdInstance->controlCallbackFn    = callbackFn;
1138     msdInstance->controlCallbackParam = callbackParam;
1139     /* initialize transfer */
1140     transfer->transferBuffer = buffer;
1141     transfer->transferLength = bufferLength;
1142     transfer->callbackFn     = pipeCallbackFn;
1143     transfer->callbackParam  = msdInstance;
1144 
1145     transfer->setupPacket->bmRequestType = requestType;
1146     transfer->setupPacket->bRequest      = requestValue;
1147     transfer->setupPacket->wValue        = 0x0000;
1148     transfer->setupPacket->wIndex =
1149         ((usb_host_interface_t *)msdInstance->interfaceHandle)->interfaceDesc->bInterfaceNumber;
1150     transfer->setupPacket->wLength = bufferLength;
1151 
1152     if (USB_HostSendSetup(msdInstance->hostHandle, msdInstance->controlPipe, transfer) !=
1153         kStatus_USB_Success) /* call host driver api */
1154     {
1155         (void)USB_HostFreeTransfer(msdInstance->hostHandle, transfer);
1156         return kStatus_USB_Error;
1157     }
1158     msdInstance->controlTransfer = transfer;
1159 
1160     return kStatus_USB_Success;
1161 }
1162 
USB_HostMsdMassStorageReset(usb_host_class_handle classHandle,transfer_callback_t callbackFn,void * callbackParam)1163 usb_status_t USB_HostMsdMassStorageReset(usb_host_class_handle classHandle,
1164                                          transfer_callback_t callbackFn,
1165                                          void *callbackParam)
1166 {
1167     usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)classHandle;
1168 
1169     return USB_HostMsdControl(msdInstance, USB_HostMsdMassResetCallback, callbackFn, callbackParam, NULL, 0,
1170                               (USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE),
1171                               USB_HOST_HID_MASS_STORAGE_RESET);
1172 }
1173 
USB_HostMsdGetMaxLun(usb_host_class_handle classHandle,uint8_t * logicalUnitNumber,transfer_callback_t callbackFn,void * callbackParam)1174 usb_status_t USB_HostMsdGetMaxLun(usb_host_class_handle classHandle,
1175                                   uint8_t *logicalUnitNumber,
1176                                   transfer_callback_t callbackFn,
1177                                   void *callbackParam)
1178 {
1179     usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)classHandle;
1180 
1181     return USB_HostMsdControl(
1182         msdInstance, USB_HostMsdControlCallback, callbackFn, callbackParam, logicalUnitNumber, 1,
1183         (USB_REQUEST_TYPE_DIR_IN | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE),
1184         USB_HOST_HID_GET_MAX_LUN);
1185 }
1186 
1187 #endif /* USB_HOST_CONFIG_MSD */
1188