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