1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016 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 
14 /*******************************************************************************
15  * Definitions
16  ******************************************************************************/
17 
18 /* UFI command code */
19 #define UFI_FORMAT_UNIT (0x04U)
20 #define UFI_INQUIRY (0x12U)
21 #define UFI_START_STOP (0x1BU)
22 #define UFI_MODE_SELECT (0x55U)
23 #define UFI_MODE_SENSE (0x5AU)
24 #define UFI_MEDIUM_REMOVAL (0x1EU)
25 #define UFI_READ10 (0x28U)
26 #define UFI_READ12 (0xA8U)
27 #define UFI_READ_CAPACITY (0x25U)
28 #define UFI_READ_FORMAT_CAPACITY (0x23U)
29 #define UFI_REQUEST_SENSE (0x03U)
30 #define UFI_REZERO_UINT (0x01U)
31 #define UFI_SEEK (0x2BU)
32 #define UFI_SEND_DIAGNOSTIC (0x1DU)
33 #define UFI_TEST_UNIT_READY (0x00U)
34 #define UFI_VERIFY (0x2FU)
35 #define UFI_WRITE10 (0x2AU)
36 #define UFI_WRITE12 (0xAAU)
37 #define UFI_WRITE_VERIFY (0x2EU)
38 
39 #define GET_BYTE_FROM_LE_LONG(b, n) \
40     ((uint8_t)((USB_LONG_TO_LITTLE_ENDIAN(b)) >> ((n)*8))) /* get the byte from the long value */
41 
42 /*******************************************************************************
43  * Prototypes
44  ******************************************************************************/
45 
46 /*******************************************************************************
47  * Variables
48  ******************************************************************************/
49 
50 /*******************************************************************************
51  * Code
52  ******************************************************************************/
53 
USB_HostMsdRead10(usb_host_class_handle classHandle,uint8_t logicalUnit,uint32_t blockAddress,uint8_t * buffer,uint32_t bufferLength,uint32_t blockNumber,transfer_callback_t callbackFn,void * callbackParam)54 usb_status_t USB_HostMsdRead10(usb_host_class_handle classHandle,
55                                uint8_t logicalUnit,
56                                uint32_t blockAddress,
57                                uint8_t *buffer,
58                                uint32_t bufferLength,
59                                uint32_t blockNumber,
60                                transfer_callback_t callbackFn,
61                                void *callbackParam)
62 {
63     uint8_t ufiBytes[] = {UFI_READ10,
64                           (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
65                           GET_BYTE_FROM_LE_LONG(blockAddress, 3),
66                           GET_BYTE_FROM_LE_LONG(blockAddress, 2),
67                           GET_BYTE_FROM_LE_LONG(blockAddress, 1),
68                           GET_BYTE_FROM_LE_LONG(blockAddress, 0),
69                           0x00,
70                           GET_BYTE_FROM_LE_LONG(blockNumber, 1),
71                           GET_BYTE_FROM_LE_LONG(blockNumber, 0),
72                           0x00};
73     return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam,
74                               USB_HOST_MSD_CBW_FLAGS_DIRECTION_IN, ufiBytes);
75 }
76 
USB_HostMsdRead12(usb_host_class_handle classHandle,uint8_t logicalUnit,uint32_t blockAddress,uint8_t * buffer,uint32_t bufferLength,uint32_t blockNumber,transfer_callback_t callbackFn,void * callbackParam)77 usb_status_t USB_HostMsdRead12(usb_host_class_handle classHandle,
78                                uint8_t logicalUnit,
79                                uint32_t blockAddress,
80                                uint8_t *buffer,
81                                uint32_t bufferLength,
82                                uint32_t blockNumber,
83                                transfer_callback_t callbackFn,
84                                void *callbackParam)
85 {
86     uint8_t ufiBytes[] = {UFI_READ12,
87                           (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
88                           GET_BYTE_FROM_LE_LONG(blockAddress, 3),
89                           GET_BYTE_FROM_LE_LONG(blockAddress, 2),
90                           GET_BYTE_FROM_LE_LONG(blockAddress, 1),
91                           GET_BYTE_FROM_LE_LONG(blockAddress, 0),
92                           GET_BYTE_FROM_LE_LONG(blockNumber, 3),
93                           GET_BYTE_FROM_LE_LONG(blockNumber, 2),
94                           GET_BYTE_FROM_LE_LONG(blockNumber, 1),
95                           GET_BYTE_FROM_LE_LONG(blockNumber, 0)};
96     return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam,
97                               USB_HOST_MSD_CBW_FLAGS_DIRECTION_IN, ufiBytes);
98 }
99 
USB_HostMsdWrite10(usb_host_class_handle classHandle,uint8_t logicalUnit,uint32_t blockAddress,uint8_t * buffer,uint32_t bufferLength,uint32_t blockNumber,transfer_callback_t callbackFn,void * callbackParam)100 usb_status_t USB_HostMsdWrite10(usb_host_class_handle classHandle,
101                                 uint8_t logicalUnit,
102                                 uint32_t blockAddress,
103                                 uint8_t *buffer,
104                                 uint32_t bufferLength,
105                                 uint32_t blockNumber,
106                                 transfer_callback_t callbackFn,
107                                 void *callbackParam)
108 {
109     uint8_t ufiBytes[] = {UFI_WRITE10,
110                           (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
111                           GET_BYTE_FROM_LE_LONG(blockAddress, 3),
112                           GET_BYTE_FROM_LE_LONG(blockAddress, 2),
113                           GET_BYTE_FROM_LE_LONG(blockAddress, 1),
114                           GET_BYTE_FROM_LE_LONG(blockAddress, 0),
115                           0x00,
116                           GET_BYTE_FROM_LE_LONG(blockNumber, 1),
117                           GET_BYTE_FROM_LE_LONG(blockNumber, 0),
118                           0x00};
119     return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam,
120                               USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT, ufiBytes);
121 }
122 
USB_HostMsdWrite12(usb_host_class_handle classHandle,uint8_t logicalUnit,uint32_t blockAddress,uint8_t * buffer,uint32_t bufferLength,uint32_t blockNumber,transfer_callback_t callbackFn,void * callbackParam)123 usb_status_t USB_HostMsdWrite12(usb_host_class_handle classHandle,
124                                 uint8_t logicalUnit,
125                                 uint32_t blockAddress,
126                                 uint8_t *buffer,
127                                 uint32_t bufferLength,
128                                 uint32_t blockNumber,
129                                 transfer_callback_t callbackFn,
130                                 void *callbackParam)
131 {
132     uint8_t ufiBytes[] = {UFI_WRITE12,
133                           (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
134                           GET_BYTE_FROM_LE_LONG(blockAddress, 3),
135                           GET_BYTE_FROM_LE_LONG(blockAddress, 2),
136                           GET_BYTE_FROM_LE_LONG(blockAddress, 1),
137                           GET_BYTE_FROM_LE_LONG(blockAddress, 0),
138                           GET_BYTE_FROM_LE_LONG(blockNumber, 3),
139                           GET_BYTE_FROM_LE_LONG(blockNumber, 2),
140                           GET_BYTE_FROM_LE_LONG(blockNumber, 1),
141                           GET_BYTE_FROM_LE_LONG(blockNumber, 0)};
142     return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam,
143                               USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT, ufiBytes);
144 }
145 
USB_HostMsdReadCapacity(usb_host_class_handle classHandle,uint8_t logicalUnit,uint8_t * buffer,uint32_t bufferLength,transfer_callback_t callbackFn,void * callbackParam)146 usb_status_t USB_HostMsdReadCapacity(usb_host_class_handle classHandle,
147                                      uint8_t logicalUnit,
148                                      uint8_t *buffer,
149                                      uint32_t bufferLength,
150                                      transfer_callback_t callbackFn,
151                                      void *callbackParam)
152 {
153     uint8_t ufiBytes[] = {UFI_READ_CAPACITY,
154                           (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
155                           0x00,
156                           0x00,
157                           0x00,
158                           0x00,
159                           0x00,
160                           0x00,
161                           0x00,
162                           0x00};
163     return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam,
164                               USB_HOST_MSD_CBW_FLAGS_DIRECTION_IN, ufiBytes);
165 }
166 
USB_HostMsdTestUnitReady(usb_host_class_handle classHandle,uint8_t logicalUnit,transfer_callback_t callbackFn,void * callbackParam)167 usb_status_t USB_HostMsdTestUnitReady(usb_host_class_handle classHandle,
168                                       uint8_t logicalUnit,
169                                       transfer_callback_t callbackFn,
170                                       void *callbackParam)
171 {
172     uint8_t ufiBytes[] = {UFI_TEST_UNIT_READY,
173                           (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
174                           0x00,
175                           0x00,
176                           0x00,
177                           0x00,
178                           0x00,
179                           0x00,
180                           0x00,
181                           0x00};
182     return USB_HostMsdCommand(classHandle, NULL, 0, callbackFn, callbackParam, USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT,
183                               ufiBytes);
184 }
185 
USB_HostMsdRequestSense(usb_host_class_handle classHandle,uint8_t logicalUnit,uint8_t * buffer,uint32_t bufferLength,transfer_callback_t callbackFn,void * callbackParam)186 usb_status_t USB_HostMsdRequestSense(usb_host_class_handle classHandle,
187                                      uint8_t logicalUnit,
188                                      uint8_t *buffer,
189                                      uint32_t bufferLength,
190                                      transfer_callback_t callbackFn,
191                                      void *callbackParam)
192 {
193     uint8_t ufiBytes[] = {UFI_REQUEST_SENSE,
194                           (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
195                           0x00,
196                           0x00,
197                           (uint8_t)bufferLength,
198                           0x00,
199                           0x00,
200                           0x00,
201                           0x00,
202                           0x00};
203     return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam,
204                               USB_HOST_MSD_CBW_FLAGS_DIRECTION_IN, ufiBytes);
205 }
206 
USB_HostMsdModeSelect(usb_host_class_handle classHandle,uint8_t logicalUnit,uint8_t * buffer,uint32_t bufferLength,transfer_callback_t callbackFn,void * callbackParam)207 usb_status_t USB_HostMsdModeSelect(usb_host_class_handle classHandle,
208                                    uint8_t logicalUnit,
209                                    uint8_t *buffer,
210                                    uint32_t bufferLength,
211                                    transfer_callback_t callbackFn,
212                                    void *callbackParam)
213 {
214     uint8_t ufiBytes[] = {UFI_MODE_SELECT,
215                           (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
216                           0x00,
217                           0x00,
218                           0x00,
219                           0x00,
220                           0x00,
221                           GET_BYTE_FROM_LE_LONG(bufferLength, 1),
222                           GET_BYTE_FROM_LE_LONG(bufferLength, 0),
223                           0x00};
224     return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam,
225                               USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT, ufiBytes);
226 }
227 
USB_HostMsdModeSense(usb_host_class_handle classHandle,uint8_t logicalUnit,uint8_t pageControl,uint8_t pageCode,uint8_t * buffer,uint32_t bufferLength,transfer_callback_t callbackFn,void * callbackParam)228 usb_status_t USB_HostMsdModeSense(usb_host_class_handle classHandle,
229                                   uint8_t logicalUnit,
230                                   uint8_t pageControl,
231                                   uint8_t pageCode,
232                                   uint8_t *buffer,
233                                   uint32_t bufferLength,
234                                   transfer_callback_t callbackFn,
235                                   void *callbackParam)
236 {
237     uint8_t ufiBytes[] = {UFI_MODE_SENSE,
238                           (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
239                           (uint8_t)(((uint32_t)pageCode << USB_HOST_UFI_MODE_SENSE_PAGE_CONTROL_SHIFT) |
240                                     ((uint32_t)pageCode << USB_HOST_UFI_MODE_SENSE_PAGE_CODE_SHIFT)),
241                           0x00,
242                           0x00,
243                           0x00,
244                           0x00,
245                           GET_BYTE_FROM_LE_LONG(bufferLength, 1),
246                           GET_BYTE_FROM_LE_LONG(bufferLength, 0),
247                           0x00};
248     return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam,
249                               USB_HOST_MSD_CBW_FLAGS_DIRECTION_IN, ufiBytes);
250 }
251 
USB_HostMsdInquiry(usb_host_class_handle classHandle,uint8_t logicalUnit,uint8_t * buffer,uint32_t bufferLength,transfer_callback_t callbackFn,void * callbackParam)252 usb_status_t USB_HostMsdInquiry(usb_host_class_handle classHandle,
253                                 uint8_t logicalUnit,
254                                 uint8_t *buffer,
255                                 uint32_t bufferLength,
256                                 transfer_callback_t callbackFn,
257                                 void *callbackParam)
258 {
259     uint8_t ufiBytes[] = {UFI_INQUIRY,
260                           (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
261                           0x00,
262                           0x00,
263                           (uint8_t)bufferLength,
264                           0x00,
265                           0x00,
266                           0x00,
267                           0x00,
268                           0x00};
269     return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam,
270                               USB_HOST_MSD_CBW_FLAGS_DIRECTION_IN, ufiBytes);
271 }
272 
USB_HostMsdReadFormatCapacities(usb_host_class_handle classHandle,uint8_t logicalUnit,uint8_t * buffer,uint32_t bufferLength,transfer_callback_t callbackFn,void * callbackParam)273 usb_status_t USB_HostMsdReadFormatCapacities(usb_host_class_handle classHandle,
274                                              uint8_t logicalUnit,
275                                              uint8_t *buffer,
276                                              uint32_t bufferLength,
277                                              transfer_callback_t callbackFn,
278                                              void *callbackParam)
279 {
280     uint8_t ufiBytes[] = {UFI_READ_FORMAT_CAPACITY,
281                           (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
282                           0x00,
283                           0x00,
284                           0x00,
285                           0x00,
286                           0x00,
287                           GET_BYTE_FROM_LE_LONG(bufferLength, 1),
288                           GET_BYTE_FROM_LE_LONG(bufferLength, 0),
289                           0x00};
290     return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam,
291                               USB_HOST_MSD_CBW_FLAGS_DIRECTION_IN, ufiBytes);
292 }
293 
USB_HostMsdFormatUnit(usb_host_class_handle classHandle,uint8_t logicalUnit,uint8_t trackNumber,uint16_t interLeave,uint8_t * buffer,uint32_t bufferLength,transfer_callback_t callbackFn,void * callbackParam)294 usb_status_t USB_HostMsdFormatUnit(usb_host_class_handle classHandle,
295                                    uint8_t logicalUnit,
296                                    uint8_t trackNumber,
297                                    uint16_t interLeave,
298                                    uint8_t *buffer,
299                                    uint32_t bufferLength,
300                                    transfer_callback_t callbackFn,
301                                    void *callbackParam)
302 {
303     uint8_t ufiBytes[] = {UFI_FORMAT_UNIT,
304                           (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
305                           trackNumber,
306                           GET_BYTE_FROM_LE_LONG(interLeave, 1),
307                           GET_BYTE_FROM_LE_LONG(interLeave, 0),
308                           0x00,
309                           0x00,
310                           GET_BYTE_FROM_LE_LONG(bufferLength, 1),
311                           GET_BYTE_FROM_LE_LONG(bufferLength, 0),
312                           0x00};
313     return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam,
314                               USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT, ufiBytes);
315 }
316 
USB_HostMsdPreventAllowRemoval(usb_host_class_handle classHandle,uint8_t logicalUnit,uint8_t prevent,transfer_callback_t callbackFn,void * callbackParam)317 usb_status_t USB_HostMsdPreventAllowRemoval(usb_host_class_handle classHandle,
318                                             uint8_t logicalUnit,
319                                             uint8_t prevent,
320                                             transfer_callback_t callbackFn,
321                                             void *callbackParam)
322 {
323     uint8_t ufiBytes[] = {UFI_MEDIUM_REMOVAL,
324                           (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
325                           0x00,
326                           0x00,
327                           prevent,
328                           0x00,
329                           0x00,
330                           0x00,
331                           0x00,
332                           0x00};
333     return USB_HostMsdCommand(classHandle, NULL, 0, callbackFn, callbackParam, USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT,
334                               ufiBytes);
335 }
336 
USB_HostMsdWriteAndVerify(usb_host_class_handle classHandle,uint8_t logicalUnit,uint32_t blockAddress,uint8_t * buffer,uint32_t bufferLength,uint32_t blockNumber,transfer_callback_t callbackFn,void * callbackParam)337 usb_status_t USB_HostMsdWriteAndVerify(usb_host_class_handle classHandle,
338                                        uint8_t logicalUnit,
339                                        uint32_t blockAddress,
340                                        uint8_t *buffer,
341                                        uint32_t bufferLength,
342                                        uint32_t blockNumber,
343                                        transfer_callback_t callbackFn,
344                                        void *callbackParam)
345 {
346     uint8_t ufiBytes[] = {UFI_WRITE_VERIFY,
347                           (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
348                           GET_BYTE_FROM_LE_LONG(blockAddress, 3),
349                           GET_BYTE_FROM_LE_LONG(blockAddress, 2),
350                           GET_BYTE_FROM_LE_LONG(blockAddress, 1),
351                           GET_BYTE_FROM_LE_LONG(blockAddress, 0),
352                           0x00,
353                           GET_BYTE_FROM_LE_LONG(blockNumber, 1),
354                           GET_BYTE_FROM_LE_LONG(blockNumber, 0),
355                           0x00};
356     return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam,
357                               USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT, ufiBytes);
358 }
359 
USB_HostMsdStartStopUnit(usb_host_class_handle classHandle,uint8_t logicalUnit,uint8_t loadEject,uint8_t start,transfer_callback_t callbackFn,void * callbackParam)360 usb_status_t USB_HostMsdStartStopUnit(usb_host_class_handle classHandle,
361                                       uint8_t logicalUnit,
362                                       uint8_t loadEject,
363                                       uint8_t start,
364                                       transfer_callback_t callbackFn,
365                                       void *callbackParam)
366 {
367     uint8_t ufiBytes[] = {UFI_START_STOP,
368                           (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
369                           0x00,
370                           0x00,
371                           (uint8_t)(((uint32_t)loadEject << USB_HOST_UFI_START_STOP_UNIT_LOEJ_SHIFT) |
372                                     ((uint32_t)start << USB_HOST_UFI_START_STOP_UNIT_START_SHIFT)),
373                           0x00,
374                           0x00,
375                           0x00,
376                           0x00,
377                           0x00};
378     return USB_HostMsdCommand(classHandle, NULL, 0, callbackFn, callbackParam, USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT,
379                               ufiBytes);
380 }
381 
USB_HostMsdVerify(usb_host_class_handle classHandle,uint8_t logicalUnit,uint32_t blockAddress,uint16_t verificationLength,transfer_callback_t callbackFn,void * callbackParam)382 usb_status_t USB_HostMsdVerify(usb_host_class_handle classHandle,
383                                uint8_t logicalUnit,
384                                uint32_t blockAddress,
385                                uint16_t verificationLength,
386                                transfer_callback_t callbackFn,
387                                void *callbackParam)
388 {
389     uint8_t ufiBytes[] = {UFI_VERIFY,
390                           (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
391                           GET_BYTE_FROM_LE_LONG(blockAddress, 3),
392                           GET_BYTE_FROM_LE_LONG(blockAddress, 2),
393                           GET_BYTE_FROM_LE_LONG(blockAddress, 1),
394                           GET_BYTE_FROM_LE_LONG(blockAddress, 0),
395                           0x00,
396                           GET_BYTE_FROM_LE_LONG(verificationLength, 1),
397                           GET_BYTE_FROM_LE_LONG(verificationLength, 0),
398                           0x00};
399     return USB_HostMsdCommand(classHandle, NULL, 0, callbackFn, callbackParam, USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT,
400                               ufiBytes);
401 }
402 
USB_HostMsdRezeroUnit(usb_host_class_handle classHandle,uint8_t logicalUnit,transfer_callback_t callbackFn,void * callbackParam)403 usb_status_t USB_HostMsdRezeroUnit(usb_host_class_handle classHandle,
404                                    uint8_t logicalUnit,
405                                    transfer_callback_t callbackFn,
406                                    void *callbackParam)
407 {
408     uint8_t ufiBytes[] = {UFI_REZERO_UINT,
409                           (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
410                           0x00,
411                           0x00,
412                           0x00,
413                           0x00,
414                           0x00,
415                           0x00,
416                           0x00,
417                           0x00};
418     return USB_HostMsdCommand(classHandle, NULL, 0, callbackFn, callbackParam, USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT,
419                               ufiBytes);
420 }
421 
USB_HostMsdSeek10(usb_host_class_handle classHandle,uint8_t logicalUnit,uint32_t blockAddress,transfer_callback_t callbackFn,void * callbackParam)422 usb_status_t USB_HostMsdSeek10(usb_host_class_handle classHandle,
423                                uint8_t logicalUnit,
424                                uint32_t blockAddress,
425                                transfer_callback_t callbackFn,
426                                void *callbackParam)
427 {
428     uint8_t ufiBytes[] = {UFI_SEEK,
429                           (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
430                           GET_BYTE_FROM_LE_LONG(blockAddress, 3),
431                           GET_BYTE_FROM_LE_LONG(blockAddress, 2),
432                           GET_BYTE_FROM_LE_LONG(blockAddress, 1),
433                           GET_BYTE_FROM_LE_LONG(blockAddress, 0),
434                           0x00,
435                           0x00,
436                           0x00,
437                           0x00};
438     return USB_HostMsdCommand(classHandle, NULL, 0, callbackFn, callbackParam, USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT,
439                               ufiBytes);
440 }
441 
USB_HostMsdSendDiagnostic(usb_host_class_handle classHandle,uint8_t logicalUnit,uint8_t selfTest,transfer_callback_t callbackFn,void * callbackParam)442 usb_status_t USB_HostMsdSendDiagnostic(usb_host_class_handle classHandle,
443                                        uint8_t logicalUnit,
444                                        uint8_t selfTest,
445                                        transfer_callback_t callbackFn,
446                                        void *callbackParam)
447 {
448     uint8_t ufiBytes[] = {UFI_REZERO_UINT,
449                           (uint8_t)(((uint32_t)logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION) |
450                                     ((uint32_t)selfTest << USB_HOST_UFI_SEND_DIAGNOSTIC_SELF_TEST_SHIFT)),
451                           0x00,
452                           0x00,
453                           0x00,
454                           0x00,
455                           0x00,
456                           0x00,
457                           0x00,
458                           0x00};
459     return USB_HostMsdCommand(classHandle, NULL, 0, callbackFn, callbackParam, USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT,
460                               ufiBytes);
461 }
462 
463 #endif /* USB_HOST_CONFIG_MSD */
464