1 /*******************************************************************************
2 * Copyright 2019-2020 Microchip FPGA Embedded Systems Solutions.
3 *
4 * SPDX-License-Identifier: MIT
5 *
6 * PolarFire SoC MSS USB Driver Stack
7 * USB Logical Layer (USB-LL)
8 * USBH-MSC class driver.
9 *
10 *
11 * This file implements Host side MSC class specific initialization
12 * and request handling.
13 *
14 */
15
16 #include "mss_usb_host_msc.h"
17 #include "mss_usb_host.h"
18 #include "mss_usb_std_def.h"
19
20 #include <string.h>
21 #include <stdio.h>
22 #include "mpfs_hal/mss_hal.h"
23
24 #ifdef __cplusplus
25 extern "C" {
26 #endif
27
28 #ifdef MSS_USB_HOST_ENABLED
29
30 /***************************************************************************//**
31 Constant values internally used by USBH-MSC driver.
32 */
33 #define MSS_USBH_MSC_CLASS_ID 0x08u
34 #define MSS_USBH_MSC_SUBCLASS_ID 0x06u
35 #define MSS_USBH_MSC_PROTOCOL_ID 0x50u
36
37 #define MSS_USBH_MSC_DRIVER_ID (uint32_t)((MSS_USBH_MSC_CLASS_ID << 16) |\
38 (MSS_USBH_MSC_SUBCLASS_ID << 8)|\
39 (MSS_USBH_MSC_PROTOCOL_ID) )
40
41 #define SCSI_COMMAND_PASSED 0x01u
42 #define SCSI_COMMAND_FAILED 0x02u
43 #define SCSI_COMMAND_PHASE_ERR 0x03u
44
45 #define USBH_MSC_BULK_TX_PIPE MSS_USB_TX_EP_1
46 #define USBH_MSC_BULK_RX_PIPE MSS_USB_RX_EP_1
47
48 #define USBH_MSC_BULK_TX_PIPE_FIFOADDR 0x100u
49 #define USBH_MSC_BULK_RX_PIPE_FIFOADDR 0x300u
50
51 #define USBH_MSC_BULK_TX_PIPE_FIFOSZ 0x200u
52 #define USBH_MSC_BULK_RX_PIPE_FIFOSZ 0x200u
53
54 /***************************************************************************//**
55 Types internally used by USBH-MSC driver.
56 */
57 typedef enum {
58 MSC_BOT_IDLE,
59 MSC_BOT_COMMAND_PHASE,
60 MSC_BOT_DATA_PHASE,
61 MSC_BOT_STATUS_PHASE,
62 MSC_BOT_STATUS_WAITCOMPLETE,
63 MSC_BOT_ERROR
64 }g_msc_bot_state_t;
65
66 typedef struct {
67 uint8_t num;
68 uint16_t maxpktsz;
69 } msd_tdev_ep_t;
70
71 typedef struct {
72 uint8_t* cbuf; /* always31bytes */
73 uint8_t* dbuf;
74 uint32_t dbuf_len;
75 uint8_t* sbuf; /* statusalways 13bytes */
76 uint8_t volatile st;
77 } scsi_command_t;
78
79 /***************************************************************************//**
80 Private functions declarations for USBH-MSC driver.
81 */
82 static scsi_command_t g_scsi_command = {0};
83 static volatile uint8_t g_usbh_msc_alloc_event = 0u;
84 static uint8_t g_usbh_msc_release_event = 0u;
85 static volatile uint8_t g_usbh_msc_cep_event = 0u;
86 static volatile uint8_t g_usbh_msc_tx_event = 0u;
87 static volatile uint8_t g_usbh_msc_rx_event = 0u;
88
89 #if defined(__GNUC__)
90 static msd_cbw_t g_bot_cbw __attribute__ ((aligned (4))) = {0};
91 static uint8_t g_bot_csw[13] __attribute__ ((aligned (4))) = {0};
92
93 /* Store Inquiry response */
94 static uint8_t g_bot_inquiry[36] __attribute__ ((aligned (4))) = {0};
95
96 /* Store Read_capacity response */
97 static uint8_t g_bot_readcap[8] __attribute__ ((aligned (4)))= {0};
98
99 #elif defined(__ICCARM__)
100 #pragma data_alignment = 4
101 static msd_cbw_t g_bot_cbw = {0};
102 static uint8_t g_bot_csw[13] = {0};
103 static uint8_t g_bot_inquiry[36] = {0};
104 static uint8_t g_bot_readcap[8] = {0};
105
106 #elif defined(__CC_ARM)
107 __align(4) static msd_cbw_t g_bot_cbw = {0};
108 __align(4) static uint8_t g_bot_csw[13] = {0};
109 __align(4) static uint8_t g_bot_inquiry[36] = {0};
110 __align(4) static uint8_t g_bot_readcap[8] = {0};
111 #endif
112
113 static volatile g_msc_bot_state_t g_msc_bot_state = MSC_BOT_IDLE;
114
115 static uint8_t g_msd_tdev_addr = 0u;
116 static mss_usb_state_t msd_tdev_state = MSS_USB_NOT_ATTACHED_STATE;
117 static uint8_t g_msd_conf_desc[32] = {0};
118
119 /* Data type changed from uint8_t since ASSERT in start_control_xfr() */
120 static uint32_t g_tdev_max_lun_idx = 0u;
121 static msd_tdev_ep_t g_tdev_in_ep = {0};
122 static msd_tdev_ep_t g_tdev_out_ep = {0};
123
124 static volatile mss_usbh_msc_state_t g_msc_state = USBH_MSC_IDLE;
125 static mss_usbh_msc_err_code_t g_msch_error_code = USBH_MSC_NO_ERROR;
126
127 static mss_usbh_msc_user_cb_t* g_msch_user_cb;
128
129 static uint8_t usbh_msc_allocate_cb(uint8_t tdev_addr);
130 static uint8_t usbh_msc_release_cb(uint8_t tdev_addr);
131 static uint8_t usbh_msc_cep_done_cb(uint8_t tdev_addr, uint8_t status, uint32_t count);
132
133 static uint8_t usbh_msc_tx_complete_cb(uint8_t tdev_addr,
134 uint8_t status,
135 uint32_t count);
136
137 static uint8_t usbh_msc_rx_cb(uint8_t tdev_addr, uint8_t status, uint32_t count);
138 static mss_usbh_msc_err_code_t MSS_USBH_MSC_validate_class_desc(uint8_t* p_cd);
139 static mss_usbh_msc_err_code_t MSS_USBH_MSC_extract_tdev_ep_desc(void);
140
141 static void usbh_msc_construct_class_req(uint8_t* buf,
142 uint8_t req,
143 uint8_t bInterfaceNumber);
144
145 /***************************************************************************//**
146 Definition of Class call-back functions used by USBH driver.
147 */
148 mss_usbh_class_cb_t msd_class =
149 {
150 MSS_USBH_MSC_DRIVER_ID,
151 usbh_msc_allocate_cb,
152 usbh_msc_release_cb,
153 usbh_msc_cep_done_cb,
154 usbh_msc_tx_complete_cb,
155 usbh_msc_rx_cb,
156 0
157 };
158
159 /*******************************************************************************
160 * EXPORTED API Functions
161 ******************************************************************************/
162
163 /******************************************************************************
164 * See mss_usb_host_msc.h for details of how to use this function.
165 */
166 void
MSS_USBH_MSC_init(mss_usbh_msc_user_cb_t * user_sb)167 MSS_USBH_MSC_init
168 (
169 mss_usbh_msc_user_cb_t* user_sb
170 )
171 {
172 g_msc_state = USBH_MSC_IDLE;
173 g_msc_bot_state = MSC_BOT_IDLE;
174 g_tdev_max_lun_idx = 0u;
175 memset(g_msd_conf_desc, 0u, sizeof(g_msd_conf_desc));
176 memset(g_bot_inquiry, 0u, sizeof(g_bot_inquiry));
177 memset(&g_bot_csw, 0u, sizeof(g_bot_csw));
178 g_tdev_in_ep.maxpktsz = 0u;
179 g_tdev_in_ep.num = 0u;
180 g_tdev_out_ep.maxpktsz = 0u;
181 g_tdev_out_ep.num = 0u;
182 g_msd_tdev_addr = 0u;
183 g_msch_user_cb = user_sb;
184
185 g_scsi_command.cbuf = (uint8_t*)0;
186 g_scsi_command.dbuf = (uint8_t*)0;
187 g_scsi_command.sbuf = (uint8_t*)0;
188 g_scsi_command.dbuf_len = 0u;
189 g_scsi_command.st = 0u;
190 memset(g_bot_readcap, 0u, sizeof(g_bot_readcap));
191 }
192
193 /******************************************************************************
194 * See mss_usb_host_msc.h for details of how to use this function.
195 */
MSS_USBH_MSC_get_handle(void)196 void* MSS_USBH_MSC_get_handle
197 (
198 void
199 )
200 {
201 return ((void*)&msd_class);
202 }
203
204 /******************************************************************************
205 * See mss_usb_host_msc.h for details of how to use this function.
206 */
207 void
MSS_USBH_MSC_task(void)208 MSS_USBH_MSC_task
209 (
210 void
211 )
212 {
213 uint8_t std_req_buf[USB_SETUP_PKT_LEN] = {0};
214 static volatile uint32_t wait_mili = 0u;
215
216 switch (g_msc_state)
217 {
218 case USBH_MSC_IDLE:
219 if (g_usbh_msc_alloc_event)
220 {
221 g_usbh_msc_alloc_event = 0u;
222 g_msc_state = USBH_MSC_GET_CLASS_DESCR;
223 }
224 break;
225
226 case USBH_MSC_GET_CLASS_DESCR:
227 msd_tdev_state = MSS_USBH_get_tdev_state(g_msd_tdev_addr);
228 if (MSS_USB_ADDRESS_STATE == msd_tdev_state)
229 {
230 mss_usb_ep_state_t cep_st;
231 cep_st = MSS_USBH_get_cep_state();
232 if (MSS_USB_CEP_IDLE == cep_st)
233 {
234 MSS_USBH_configure_control_pipe(g_msd_tdev_addr);
235 memset(std_req_buf, 0u, 8*(sizeof(uint8_t)));
236 MSS_USBH_construct_get_descr_command(std_req_buf,
237 USB_STD_REQ_DATA_DIR_IN,
238 USB_STANDARD_REQUEST,
239 USB_STD_REQ_RECIPIENT_DEVICE,
240 USB_STD_REQ_GET_DESCRIPTOR,
241 USB_CONFIGURATION_DESCRIPTOR_TYPE,
242 0u, /*stringID*/
243 32u);/* config_Desc_length */
244
245 g_msc_state = USBH_MSC_WAIT_GET_CLASS_DESCR;
246 MSS_USBH_start_control_xfr(std_req_buf,
247 (uint8_t*)&g_msd_conf_desc,
248 USB_STD_REQ_DATA_DIR_IN,
249 32u); /* config_Desc_length */
250 }
251 }
252 break;
253
254 case USBH_MSC_WAIT_GET_CLASS_DESCR:
255 if (g_usbh_msc_cep_event)
256 {
257 mss_usbh_msc_err_code_t res = USBH_MSC_NO_ERROR;
258 g_usbh_msc_cep_event = 0u;
259 res = MSS_USBH_MSC_validate_class_desc(0);
260
261 if (res == 0u)
262 {
263 g_msc_state = USBH_MSC_SET_CONFIG;
264 }
265 else
266 {
267 g_msc_state = USBH_MSC_ERROR;
268 g_msch_error_code = res;
269 }
270
271 res = MSS_USBH_MSC_extract_tdev_ep_desc();
272
273 if (res == 0u)
274 {
275 g_msc_state = USBH_MSC_SET_CONFIG;
276 }
277 else
278 {
279 g_msc_state = USBH_MSC_ERROR;
280 g_msch_error_code = res;
281 }
282 }
283 break;
284
285 case USBH_MSC_SET_CONFIG:
286 if (0 != g_msch_user_cb->msch_valid_config)
287 {
288 g_msch_user_cb->msch_valid_config();
289 }
290
291 memset(std_req_buf, 0u, 8*(sizeof(uint8_t)));
292 std_req_buf[1] = USB_STD_REQ_SET_CONFIG;
293
294 /* bConfigurationValue*/
295 std_req_buf[2] = g_msd_conf_desc[5];
296 g_msc_state = USBH_MSC_WAIT_SET_CONFIG;
297
298 MSS_USBH_start_control_xfr(std_req_buf,
299 (uint8_t*)&g_msd_conf_desc,
300 USB_STD_REQ_DATA_DIR_IN,
301 0u);
302 break;
303 case USBH_MSC_WAIT_SET_CONFIG:
304 if (g_usbh_msc_cep_event)
305 {
306 g_usbh_msc_cep_event = 0u;
307 wait_mili = MSS_USBH_get_milis();
308 g_msc_state = USBH_MSC_WAIT_DEV_SETTLE;
309 }
310 break;
311
312 case USBH_MSC_WAIT_DEV_SETTLE:
313 /* After SET_CONFIG command, we must give time for device to settle
314 * down as per spec
315 */
316 if ((MSS_USBH_get_milis() - wait_mili) > 60u)
317 {
318 g_msc_state = USBH_MSC_GET_MAX_LUN;
319 }
320 break;
321
322 case USBH_MSC_GET_MAX_LUN:
323 usbh_msc_construct_class_req(std_req_buf,
324 USB_MSC_BOT_REQ_GET_MAX_LUN,
325 g_msd_conf_desc[11]);/* bInterfaceNum */
326
327 MSS_USBH_configure_control_pipe(g_msd_tdev_addr);
328
329 g_msc_state = USBH_MSC_WAIT_GET_MAX_LUN;
330
331 MSS_USBH_start_control_xfr(std_req_buf,
332 (uint8_t*)&g_tdev_max_lun_idx,
333 USB_STD_REQ_DATA_DIR_IN,
334 1u);
335 break;
336
337 case USBH_MSC_WAIT_GET_MAX_LUN:
338 if (g_usbh_msc_cep_event)
339 {
340 if (MSS_USB_EP_XFR_SUCCESS == g_usbh_msc_cep_event)
341 {
342 g_msc_state = USBH_MSC_CONFIG_BULK_ENDPOINTS;
343 }
344 else if (MSS_USB_EP_STALL_RCVD == g_usbh_msc_cep_event)
345 {
346 /* Stall for this command means single LUN support by Target */
347 g_tdev_max_lun_idx = 0u;
348 g_msc_state = USBH_MSC_CLR_CEP_STALL;
349
350 /* Clear Stall using CLR_FEATURE Command */
351 }
352 else
353 {
354 ASSERT(0); /* Invalid CEP event */
355 }
356
357 g_usbh_msc_cep_event = 0u;
358 }
359 break;
360
361 case USBH_MSC_CLR_CEP_STALL:
362 {
363 /* Std clear CEP STALL command */
364 uint8_t temp_buf[8u] = {0x02u,
365 0x01u,
366 0x00u, 0x00u,
367 0x00u, 0x00u,
368 0x00u, 0x00u};
369
370 g_msc_state = USBH_MSC_WAIT_CLR_CEP_STALL;
371
372 /* clear feature Endpoint halt on Tdev Out EP */
373 MSS_USBH_start_control_xfr(temp_buf,
374 (uint8_t*)&g_tdev_max_lun_idx,
375 USB_STD_REQ_DATA_DIR_IN,
376 0u);
377 break;
378 }
379 case USBH_MSC_WAIT_CLR_CEP_STALL:
380 if (g_usbh_msc_cep_event)
381 {
382 if (MSS_USB_EP_XFR_SUCCESS == g_usbh_msc_cep_event)
383 {
384 g_msc_state = USBH_MSC_CONFIG_BULK_ENDPOINTS;
385 }
386 else if (MSS_USB_EP_STALL_RCVD == g_usbh_msc_cep_event)
387 {
388 g_msc_state = USBH_MSC_ERROR;
389 g_msch_error_code = USBH_MSC_CLR_CEP_STALL_ERROR;
390 }
391 else
392 {
393 ASSERT(0);/* Invalid CEP event */
394 }
395 g_usbh_msc_cep_event = 0u;
396 }
397 break;
398
399 case USBH_MSC_CONFIG_BULK_ENDPOINTS:
400 /* Configure BULK TX/RX Endpoints */
401 MSS_USBH_configure_out_pipe(g_msd_tdev_addr,
402 USBH_MSC_BULK_TX_PIPE,
403 g_tdev_out_ep.num, /* Targeted OUTEP Num */
404 USBH_MSC_BULK_TX_PIPE_FIFOADDR,
405 USBH_MSC_BULK_TX_PIPE_FIFOSZ,
406 g_tdev_out_ep.maxpktsz,
407 1,
408 DMA_DISABLE,
409 MSS_USB_DMA_CHANNEL1,
410 MSS_USB_XFR_BULK,
411 NO_ZLP_TO_XFR,
412 32768);/* Max NAKLimit value */
413
414 MSS_USBH_configure_in_pipe(g_msd_tdev_addr,
415 USBH_MSC_BULK_RX_PIPE,
416 g_tdev_in_ep.num, /* Targeted OutEP Num */
417 USBH_MSC_BULK_RX_PIPE_FIFOADDR,
418 USBH_MSC_BULK_RX_PIPE_FIFOSZ,
419 g_tdev_in_ep.maxpktsz,
420 1,
421 DMA_DISABLE,
422 MSS_USB_DMA_CHANNEL2,
423 MSS_USB_XFR_BULK,
424 NO_ZLP_TO_XFR,
425 32768);/* Max NAKLimit value */
426
427 g_msc_state = USBH_MSC_TEST_UNIT_READY_CPHASE;
428 break;
429
430
431 case USBH_MSC_TEST_UNIT_READY_CPHASE:
432 MSS_USBH_MSC_construct_cbw_cb6byte(USB_MSC_SCSI_TEST_UNIT_READY,
433 0u,
434 &g_bot_cbw);
435
436 MSS_USBH_write_out_pipe(g_msd_tdev_addr,
437 USBH_MSC_BULK_TX_PIPE,
438 g_tdev_out_ep.num,
439 g_tdev_out_ep.maxpktsz,
440 (uint8_t*)&g_bot_cbw,
441 31u); /* std_cbw_len */
442
443 g_msc_state = USBH_MSC_TEST_UNIT_READY_SPHASE;
444 break;
445
446 case USBH_MSC_TEST_UNIT_READY_SPHASE:
447 if (g_usbh_msc_tx_event)
448 {
449 g_usbh_msc_tx_event = 0u;
450 g_msc_state = USBH_MSC_TEST_UNIT_READY_WAITCOMPLETE;
451 MSS_USBH_read_in_pipe(g_msd_tdev_addr,
452 USBH_MSC_BULK_RX_PIPE,
453 g_tdev_in_ep.num,
454 g_tdev_in_ep.maxpktsz,
455 (uint8_t*)&g_bot_csw,
456 13u);/* standard status msg */
457 }
458 break;
459
460 case USBH_MSC_TEST_UNIT_READY_WAITCOMPLETE:
461 if (g_usbh_msc_rx_event)
462 {
463 g_usbh_msc_rx_event = 0u;
464
465 /* decode the received status */
466 if (g_bot_csw[12] == 0x00u) /* PASSED */
467 {
468 g_msc_state = USBH_MSC_SCSI_INQUIRY_CPHASE;
469 }
470 else if (g_bot_csw[12] == 0x01u) /* FAILED */
471 {
472 g_msc_state = USBH_MSC_SCSI_REQSENSE_CPHASE;
473 }
474 else if (g_bot_csw[12] == 0x02u)
475 {
476 ASSERT(0); /* phase error, reset recovery required */
477 }
478 }
479
480 break;
481 case USBH_MSC_SCSI_INQUIRY_CPHASE:
482 MSS_USBH_MSC_construct_cbw_cb6byte(USB_MSC_SCSI_INQUIRY,
483 36u, /*standard INQUIRY response size */
484 &g_bot_cbw);
485
486 g_msc_state = USBH_MSC_SCSI_INQUIRY_DPHASE;
487
488 MSS_USBH_write_out_pipe(g_msd_tdev_addr,
489 USBH_MSC_BULK_TX_PIPE,
490 g_tdev_out_ep.num,
491 g_tdev_out_ep.maxpktsz,
492 (uint8_t*)&g_bot_cbw,
493 31u); /* std_cbw_len */
494 break;
495
496 case USBH_MSC_SCSI_INQUIRY_DPHASE:
497 if (g_usbh_msc_tx_event)
498 {
499 g_usbh_msc_tx_event = 0u;
500 g_msc_state = USBH_MSC_SCSI_INQUIRY_SPHASE;
501
502 MSS_USBH_read_in_pipe(g_msd_tdev_addr,
503 USBH_MSC_BULK_RX_PIPE,
504 g_tdev_in_ep.num,
505 g_tdev_in_ep.maxpktsz,
506 g_bot_inquiry,
507 36u);/* standard INQUIRY response size */
508 }
509 break;
510
511 case USBH_MSC_SCSI_INQUIRY_SPHASE:
512 if (g_usbh_msc_rx_event)
513 {
514 g_usbh_msc_rx_event = 0u;
515 g_msc_state = USBH_MSC_SCSI_INQUIRY_WAITCOMPLETE;
516
517 MSS_USBH_read_in_pipe(g_msd_tdev_addr,
518 USBH_MSC_BULK_RX_PIPE,
519 g_tdev_in_ep.num,
520 g_tdev_in_ep.maxpktsz,
521 (uint8_t*)&g_bot_csw,
522 13u);/* standard status msg */
523 }
524 break;
525
526 case USBH_MSC_SCSI_INQUIRY_WAITCOMPLETE:
527 if (g_usbh_msc_rx_event)
528 {
529 g_usbh_msc_rx_event = 0x0U;
530 g_msc_state = USBH_MSC_SCSI_READ_CAPACITY_CPHASE;
531 }
532 break;
533
534 case USBH_MSC_SCSI_REQSENSE_CPHASE:
535 {
536 /* This is a standard command buffer for REQUEST SENSE command */
537 uint8_t cbuf[] = {0x55U, 0x53U, 0x42U, 0x43U, 0x28U, 0x2EU, 0x59U, 0xAFU,
538 0x12U, 0x00U, 0x00U, 0x00U, 0x80U, 0x00U, 0x0CU, 0x03U,
539 0x00U, 0x00U, 0x00U, 0x12U, 0x00U, 0x00U, 0x00U, 0x00U,
540 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U};
541
542 g_msc_state = USBH_MSC_SCSI_REQSENSE_DPHASE;
543
544 MSS_USBH_write_out_pipe(g_msd_tdev_addr,
545 USBH_MSC_BULK_TX_PIPE,
546 g_tdev_out_ep.num,
547 g_tdev_out_ep.maxpktsz,
548 (uint8_t*)&cbuf,
549 31u); /*std_cbw_len */
550
551 }
552 break;
553 case USBH_MSC_SCSI_REQSENSE_DPHASE:
554 if (g_usbh_msc_tx_event)
555 {
556 /* standard response from device for REQUEST sense command is 18 bytes */
557 static uint8_t reqsense_buf[18];
558 g_usbh_msc_tx_event = 0u;
559 g_msc_state = USBH_MSC_SCSI_REQSENSE_SPHASE;
560
561 MSS_USBH_read_in_pipe(g_msd_tdev_addr,
562 USBH_MSC_BULK_RX_PIPE,
563 g_tdev_in_ep.num,
564 g_tdev_in_ep.maxpktsz,
565 reqsense_buf,
566 18u);
567 }
568 break;
569 case USBH_MSC_SCSI_REQSENSE_SPHASE:
570 if (g_usbh_msc_rx_event)
571 {
572 g_usbh_msc_rx_event = 0u;
573 g_msc_state = USBH_MSC_SCSI_REQSENSE_WAITCOMPLETE;
574
575 MSS_USBH_read_in_pipe(g_msd_tdev_addr,
576 USBH_MSC_BULK_RX_PIPE,
577 g_tdev_in_ep.num,
578 g_tdev_in_ep.maxpktsz,
579 (uint8_t*)&g_bot_csw,
580 13u);/* standard status msg */
581 }
582
583 break;
584 case USBH_MSC_SCSI_REQSENSE_WAITCOMPLETE:
585 if (g_usbh_msc_rx_event)
586 {
587 g_usbh_msc_rx_event = 0u;
588 g_msc_state = USBH_MSC_TEST_UNIT_READY_CPHASE;
589 }
590 break;
591
592 case USBH_MSC_SCSI_READ_CAPACITY_CPHASE:
593
594 MSS_USBH_MSC_construct_cbw_cb10byte(USB_MSC_SCSI_READ_CAPACITY_10,
595 0u,
596 0u,
597 0u,
598 0u,
599 &g_bot_cbw);
600
601 g_msc_state = USBH_MSC_SCSI_READ_CAPACITY_DPHASE;
602
603 MSS_USBH_write_out_pipe(g_msd_tdev_addr,
604 USBH_MSC_BULK_TX_PIPE,
605 g_tdev_out_ep.num,
606 g_tdev_out_ep.maxpktsz,
607 (uint8_t*)&g_bot_cbw,
608 31u); /* std_cbw_len */
609 break;
610
611 case USBH_MSC_SCSI_READ_CAPACITY_DPHASE:
612 if (g_usbh_msc_tx_event)
613 {
614 g_usbh_msc_rx_event = 0u;
615 g_msc_state = USBH_MSC_SCSI_READ_CAPACITY_SPHASE;
616
617 /* standard Read Capacity response size is 8bytes.
618 * We need this info later so keep it in g_bot_readcap
619 */
620 MSS_USBH_read_in_pipe(g_msd_tdev_addr,
621 USBH_MSC_BULK_RX_PIPE,
622 g_tdev_in_ep.num,
623 g_tdev_in_ep.maxpktsz,
624 g_bot_readcap,
625 8u);
626 }
627
628 break;
629
630 case USBH_MSC_SCSI_READ_CAPACITY_SPHASE:
631 if (g_usbh_msc_rx_event)
632 {
633 g_usbh_msc_rx_event = 0u;
634 g_msc_state = USBH_MSC_SCSI_READ_CAPACITY_WAITCOMPLETE;
635
636 MSS_USBH_read_in_pipe(g_msd_tdev_addr,
637 USBH_MSC_BULK_RX_PIPE,
638 g_tdev_in_ep.num,
639 g_tdev_in_ep.maxpktsz,
640 (uint8_t*)&g_bot_csw,
641 13u);/* standard status msg */
642 }
643 break;
644
645 case USBH_MSC_SCSI_READ_CAPACITY_WAITCOMPLETE:
646 if (g_usbh_msc_rx_event)
647 {
648 uint32_t sector_size = 0u;
649 g_usbh_msc_rx_event = 0u;
650
651 sector_size = ((g_bot_readcap[4u] << 24u) | /*sector size */
652 (g_bot_readcap[5u] << 16u) |
653 (g_bot_readcap[6u] << 8u) |
654 g_bot_readcap[7u]);
655
656 if (sector_size != 512u)
657 {
658 g_msc_state = USBH_MSC_ERROR;
659 g_msch_error_code = USBH_MSC_SECTOR_SIZE_NOT_SUPPORTED;
660 }
661 else
662 {
663 g_msc_state = USBH_MSC_DEVICE_READY;
664
665 if (0 != g_msch_user_cb->msch_tdev_ready)
666 {
667 g_msch_user_cb->msch_tdev_ready();
668 }
669 }
670 }
671 break;
672
673 case USBH_MSC_DEVICE_READY:
674 /*
675 * The USBH-MSC driver will stay in this state.
676 * Being in this state, the SCSI requests will be executed as
677 * user the user makes those requests through the APIs of this driver.
678 */
679 break;
680
681 case USBH_MSC_ERROR:
682 {
683 static uint8_t error = 0u;
684 if (0u == error)
685 {
686 error = 1u;
687 if (0 != g_msch_user_cb->msch_error)
688 {
689 g_msch_user_cb->msch_error(g_msch_error_code);
690 }
691 }
692 }
693 break;
694
695 case USBH_MSC_BOT_RETRY:
696 {
697 static uint32_t first_mili = 0;
698 static uint32_t crrent_mili = 0;
699
700 if (0u == first_mili)
701 {
702 first_mili = MSS_USBH_get_milis();
703 }
704
705 crrent_mili = MSS_USBH_get_milis();
706
707 /* Found that the Sandisc devices are reporting NAKTIMEOUT error.
708 * This is mostly happening when moving from DATA phase to Status
709 * phase of the SCSI read/write command. At this stage restarting
710 * the status phase is able to get the device to respond properly.
711 * The NAKLIMIT is device specific. The WIndows hosts allow up to
712 * 5Sec before declaring NAKTIMOUT. MSS USB allows to wait up to
713 * ~4Sec. Hence waiting for another 1 Sec here hoping that the
714 * device is recovered by then.
715 */
716 if (MSC_BOT_STATUS_WAITCOMPLETE == g_msc_bot_state)
717 {
718 if ((crrent_mili - first_mili) >= 1000u)
719 {
720 first_mili = 0u;
721 crrent_mili = 0u;
722 MSS_USBH_abort_in_pipe(USBH_MSC_BULK_RX_PIPE);
723
724 MSS_USBH_read_in_pipe(g_msd_tdev_addr,
725 USBH_MSC_BULK_RX_PIPE,
726 g_tdev_in_ep.num,
727 g_tdev_in_ep.maxpktsz,
728 g_scsi_command.sbuf,
729 13u);
730 g_msc_state = USBH_MSC_DEVICE_READY;
731 }
732 }
733 }
734 break;
735
736 default:
737 {
738 ASSERT(0); /*Reset recovery should be tried.*/
739 }
740 break;
741 }
742 }
743
744 /*******************************************************************************
745 * See mss_usb_host_msc.h for details of how to use this function.
746 */
747 static void
usbh_msc_construct_class_req(uint8_t * buf,uint8_t req,uint8_t bInterfaceNumber)748 usbh_msc_construct_class_req
749 (
750 uint8_t* buf,
751 uint8_t req,
752 uint8_t bInterfaceNumber
753 )
754 {
755 /* This implementation is as per MSC class spec */
756 buf[0] = 0x21u; /* bmRequestType */
757 buf[1] = req; /* bmRequest */
758
759 buf[2] = 0x00u;
760 buf[3] = 0x00u; /* wValue */
761
762 buf[4] = bInterfaceNumber;
763 buf[5] = 0x00u; /* wIndex */
764
765 if (req == USB_MSC_BOT_REQ_GET_MAX_LUN)
766 {
767 buf[6] = 0x01u;
768 buf[0] = 0xA1u; /* bmRequestType */
769 }
770 else if (req == USB_MSC_BOT_REQ_BMS_RESET)
771 {
772 buf[6] = 0x00u;
773 buf[0] = 0x21u; /* bmRequestType */
774 }
775 else
776 {
777 ASSERT(0);/* invalid MSC class class request */
778 }
779
780 buf[7] = 0x00u;
781 }
782
783 /*******************************************************************************
784 * See mss_usb_host_msc.h for details of how to use this function.
785 */
786 void
MSS_USBH_MSC_construct_cbw_cb6byte(uint8_t command_opcode,uint32_t data_xfr_len,msd_cbw_t * buf)787 MSS_USBH_MSC_construct_cbw_cb6byte
788 (
789 uint8_t command_opcode,
790 uint32_t data_xfr_len,
791 msd_cbw_t* buf
792 )
793 {
794 /* This implementation is as per MSC class spec*/
795
796 /* Inquiry, Request_sense, Test_unit_ready commands (cb10 byte commands) */
797 memset(buf, 0u, 31*(sizeof(uint8_t)));
798 buf->dCBWSignature = USB_MSC_BOT_CBW_SIGNATURE;
799 buf->dCBWTag = 0x20304050U;
800
801 buf->dCBWDataTransferLength = data_xfr_len;
802
803 if (USB_MSC_SCSI_TEST_UNIT_READY == command_opcode)
804 {
805 buf->bCBWFlags = 0x00u;
806 }
807 else if ((USB_MSC_SCSI_INQUIRY == command_opcode) ||
808 (USB_MSC_SCSI_REQUEST_SENSE == command_opcode))
809 {
810 buf->bCBWFlags = 0x80u;
811 }
812 else
813 {
814 ASSERT(0);/* invalid cb6byte command */
815 }
816
817 buf->bCBWCBLength = 0x06u;
818 buf->CBWCB[0] = command_opcode;
819 buf->CBWCB[4] = data_xfr_len;
820 }
821
822 /*******************************************************************************
823 * See mss_usb_host_msc.h for details of how to use this function.
824 */
825 void
MSS_USBH_MSC_construct_cbw_cb10byte(uint8_t command_opcode,uint8_t lun,uint32_t lb_addr,uint16_t num_of_lb,uint16_t lb_size,msd_cbw_t * buf)826 MSS_USBH_MSC_construct_cbw_cb10byte
827 (
828 uint8_t command_opcode,
829 uint8_t lun,
830 uint32_t lb_addr,
831 uint16_t num_of_lb,
832 uint16_t lb_size,
833 msd_cbw_t* buf
834 )
835 {
836 /* This implementation is as per MSC class spec */
837
838 /* Read_capacity, Read10, Write10 commands (cb10 byte commands) */
839 memset(buf, 0u, 31*(sizeof(uint8_t)));
840 buf->dCBWSignature = USB_MSC_BOT_CBW_SIGNATURE;
841 buf->dCBWTag = 0x20304050U;
842
843 if (USB_MSC_SCSI_WRITE_10 == command_opcode)
844 {
845 buf->bCBWFlags = 0x00u; /* H2D */
846 }
847 else if ((USB_MSC_SCSI_READ_10 == command_opcode) ||
848 (USB_MSC_SCSI_READ_CAPACITY_10 == command_opcode))
849 {
850 buf->bCBWFlags = 0x80u; /* D2H */
851 }
852
853 buf->bCBWCBLength = 0x0Au;
854 buf->CBWCB[0] = command_opcode;
855
856 if ((USB_MSC_SCSI_READ_10 == command_opcode) ||
857 (USB_MSC_SCSI_WRITE_10 == command_opcode))
858 {
859 buf->dCBWDataTransferLength = (num_of_lb * lb_size); /* Transfer length */
860 buf->CBWCB[1] = lun; /* Lun Number */
861 buf->CBWCB[2] = (uint8_t)((lb_addr >> 24) & 0xFFU); /* MSB first */
862 buf->CBWCB[3] = (uint8_t)((lb_addr >> 16) & 0xFFU);
863 buf->CBWCB[4] = (uint8_t)((lb_addr >> 8) & 0xFFU);
864 buf->CBWCB[5] = (uint8_t)(lb_addr & 0xFFU);
865
866 buf->CBWCB[7] = (uint8_t)((num_of_lb >> 8) & 0xFFU); /* MSB first */
867 buf->CBWCB[8] = (uint8_t)(num_of_lb & 0xFFU);
868 }
869 else if ((USB_MSC_SCSI_READ_CAPACITY_10 == command_opcode))
870 {
871 buf->dCBWDataTransferLength = 0x08u; /* Read Capacity Transfer length */
872 }
873 else
874 {
875 ASSERT(0);/* invalid cb10byte command */
876 }
877 }
878
879 /*******************************************************************************
880 * See mss_usb_host_msc.h for details of how to use this function.
881 */
882 mss_usbh_msc_state_t
MSS_USBH_MSC_get_state(void)883 MSS_USBH_MSC_get_state
884 (
885 void
886 )
887 {
888 return(g_msc_state);
889 }
890
891 uint8_t
MSS_USBH_MSC_scsi_req(uint8_t * command_buf,uint8_t * data_buf,uint32_t data_buf_len,uint8_t * status_buf)892 MSS_USBH_MSC_scsi_req
893 (
894 uint8_t* command_buf, /* always31bytes */
895 uint8_t* data_buf,
896 uint32_t data_buf_len,
897 uint8_t* status_buf /* status always 13bytes */
898 )
899 {
900 g_scsi_command.cbuf = command_buf;
901 g_scsi_command.dbuf = data_buf;
902 g_scsi_command.dbuf_len = data_buf_len;
903 g_scsi_command.sbuf = status_buf;
904
905 g_msc_bot_state = MSC_BOT_COMMAND_PHASE;
906
907 MSS_USBH_write_out_pipe(g_msd_tdev_addr,
908 USBH_MSC_BULK_TX_PIPE,
909 g_tdev_out_ep.num,
910 g_tdev_out_ep.maxpktsz,
911 g_scsi_command.cbuf,
912 31u); /* std_cbw_len */
913
914 return(0);
915 }
916
917 /*******************************************************************************
918 * See mss_usb_host_msc.h for details of how to use this function.
919 */
920 uint8_t
MSS_USBH_MSC_is_scsi_req_complete(void)921 MSS_USBH_MSC_is_scsi_req_complete
922 (
923 void
924 )
925 {
926 return (g_scsi_command.st);
927 }
928
929 /*******************************************************************************
930 * See mss_usb_host_msc.h for details of how to use this function.
931 */
932 uint32_t
MSS_USBH_MSC_get_sector_count(void)933 MSS_USBH_MSC_get_sector_count
934 (
935 void
936 )
937 {
938 /*
939 * TODO:Check this
940 * Read_capacity_10 command returns the Last LAB i.e. Address of the
941 * last Logical block. Hence Number of logical blocks(sectors) is (Last LBA+1)
942 */
943 return ((g_bot_readcap[0u] << 24u) |
944 (g_bot_readcap[1u] << 16u) |
945 (g_bot_readcap[2u] << 8u) |
946 g_bot_readcap[3u]);
947 }
948
949 /*******************************************************************************
950 * See mss_usb_host_msc.h for details of how to use this function.
951 */
952 uint32_t
MSS_USBH_MSC_get_sector_size(void)953 MSS_USBH_MSC_get_sector_size
954 (
955 void
956 )
957 {
958 /*
959 * Return the logical block(sector) size in bytes.
960 */
961 return ((g_bot_readcap[4u] << 24u) |
962 (g_bot_readcap[5u] << 16u) |
963 (g_bot_readcap[6u] << 8u) |
964 g_bot_readcap[7u]);
965 }
966
967 /*******************************************************************************
968 * See mss_usb_host_msc.h for details of how to use this function.
969 */
970 int8_t
MSS_USBH_MSC_read(uint8_t * buf,uint32_t sector,uint32_t count)971 MSS_USBH_MSC_read
972 (
973 uint8_t* buf,
974 uint32_t sector,
975 uint32_t count
976 )
977 {
978 if (0u == g_scsi_command.st)
979 {
980 g_scsi_command.st = 1u;
981 MSS_USBH_MSC_construct_cbw_cb10byte(USB_MSC_SCSI_READ_10,
982 0u,
983 sector,
984 count,
985 512u,
986 &g_bot_cbw);
987
988 MSS_USBH_MSC_scsi_req((uint8_t*)&g_bot_cbw,
989 buf,
990 (count*512u),
991 (uint8_t*)&g_bot_csw);
992 return (0);
993 }
994 else
995 {
996 return (-1); /* previous command is in progress */
997 }
998 }
999
1000 /*******************************************************************************
1001 * See mss_usb_host_msc.h for details of how to use this function.
1002 */
1003 int8_t
MSS_USBH_MSC_write(uint8_t * buf,uint32_t sector,uint32_t count)1004 MSS_USBH_MSC_write
1005 (
1006 uint8_t* buf,
1007 uint32_t sector,
1008 uint32_t count
1009 )
1010 {
1011 if (0u == g_scsi_command.st)
1012 {
1013 g_scsi_command.st = 1u;
1014 MSS_USBH_MSC_construct_cbw_cb10byte(USB_MSC_SCSI_WRITE_10,
1015 0u,
1016 sector,
1017 count,
1018 512u,
1019 &g_bot_cbw);
1020
1021 MSS_USBH_MSC_scsi_req((uint8_t*)&g_bot_cbw,
1022 buf,
1023 (count*512u),
1024 (uint8_t*)&g_bot_csw);
1025 return (0);
1026 }
1027 else
1028 {
1029 return (-1); /* Previous command is in progress */
1030 }
1031 }
1032
1033 /*******************************************************************************
1034 * Internal Functions
1035 ******************************************************************************/
1036
1037 /*
1038 * This Call-back function is executed when the USBH-MSC driver is allocated
1039 * to the attached device by USBH driver.
1040 */
1041 uint8_t
usbh_msc_allocate_cb(uint8_t tdev_addr)1042 usbh_msc_allocate_cb
1043 (
1044 uint8_t tdev_addr
1045 )
1046 {
1047 g_msd_tdev_addr = tdev_addr;
1048 g_usbh_msc_alloc_event = 1u;
1049 return(USB_SUCCESS);
1050 }
1051
1052 /*
1053 * This Call-back function is executed when the USBH-MSC driver is released
1054 * from the attached device by USBH driver.
1055 */
1056 uint8_t
usbh_msc_release_cb(uint8_t tdev_addr)1057 usbh_msc_release_cb
1058 (
1059 uint8_t tdev_addr
1060 )
1061 {
1062 g_msc_state = USBH_MSC_IDLE;
1063 g_msc_bot_state = MSC_BOT_IDLE;
1064 g_tdev_max_lun_idx = 0u;
1065 memset(g_msd_conf_desc, 0u, sizeof(g_msd_conf_desc));
1066 memset(g_bot_inquiry, 0u, sizeof(g_bot_inquiry));
1067 memset(&g_bot_csw, 0u, sizeof(g_bot_csw));
1068 g_tdev_in_ep.maxpktsz = 0u;
1069 g_tdev_in_ep.num = 0u;
1070 g_tdev_out_ep.maxpktsz = 0u;
1071 g_tdev_out_ep.num = 0u;
1072 g_msd_tdev_addr = 0u;
1073
1074 g_scsi_command.cbuf = (uint8_t*)0;
1075 g_scsi_command.dbuf = (uint8_t*)0;
1076 g_scsi_command.sbuf = (uint8_t*)0;
1077 g_scsi_command.dbuf_len = 0u;
1078 g_scsi_command.st = 0u;
1079 memset(g_bot_readcap, 0u, sizeof(g_bot_readcap));
1080
1081 MSS_USB_CIF_tx_ep_disable_irq(USBH_MSC_BULK_RX_PIPE);
1082 MSS_USB_CIF_tx_ep_clr_csrreg(USBH_MSC_BULK_RX_PIPE);
1083 MSS_USB_CIF_dma_clr_ctrlreg(MSS_USB_DMA_CHANNEL2);
1084
1085 MSS_USB_CIF_rx_ep_disable_irq(USBH_MSC_BULK_TX_PIPE);
1086 MSS_USB_CIF_rx_ep_clr_csrreg(USBH_MSC_BULK_TX_PIPE);
1087 MSS_USB_CIF_dma_clr_ctrlreg(MSS_USB_DMA_CHANNEL1);
1088
1089 if (0 != g_msch_user_cb->msch_driver_released)
1090 {
1091 g_msch_user_cb->msch_driver_released();
1092 }
1093
1094 return(USB_SUCCESS);
1095 }
1096
1097 /*
1098 * This Call-back function is executed when the control transfer initiated by this
1099 * driver is complete.
1100 */
1101 uint8_t
usbh_msc_cep_done_cb(uint8_t tdev_addr,uint8_t status,uint32_t count)1102 usbh_msc_cep_done_cb
1103 (
1104 uint8_t tdev_addr,
1105 uint8_t status,
1106 uint32_t count
1107 )
1108 {
1109 g_usbh_msc_cep_event = status;
1110
1111 return (USB_SUCCESS);
1112 }
1113
1114 /*
1115 * This Call-back function is executed when the data OUT transfer initiated by
1116 * this driver is complete.
1117 */
1118 uint8_t
usbh_msc_tx_complete_cb(uint8_t tdev_addr,uint8_t status,uint32_t count)1119 usbh_msc_tx_complete_cb
1120 (
1121 uint8_t tdev_addr,
1122 uint8_t status,
1123 uint32_t count
1124 )
1125 {
1126 if (g_msc_state < USBH_MSC_DEVICE_READY)
1127 {
1128 g_usbh_msc_tx_event = 1u;
1129 }
1130 else
1131 {
1132 if (0u == status)
1133 {
1134 switch (g_msc_bot_state)
1135 {
1136 case MSC_BOT_COMMAND_PHASE:
1137 if (0u == g_scsi_command.dbuf_len)/* zdl request */
1138 {
1139 g_msc_bot_state = MSC_BOT_STATUS_WAITCOMPLETE;
1140 MSS_USBH_read_in_pipe(g_msd_tdev_addr,
1141 USBH_MSC_BULK_RX_PIPE,
1142 g_tdev_in_ep.num,
1143 g_tdev_in_ep.maxpktsz,
1144 g_scsi_command.sbuf,
1145 13u);
1146 }
1147 else
1148 {
1149 g_msc_bot_state = MSC_BOT_DATA_PHASE;
1150 if (g_scsi_command.cbuf[12] & 0x80U) /* bmCBWFLags field -- Read Command */
1151 {
1152 MSS_USBH_read_in_pipe(g_msd_tdev_addr,
1153 USBH_MSC_BULK_RX_PIPE,
1154 g_tdev_in_ep.num,
1155 g_tdev_in_ep.maxpktsz,
1156 g_scsi_command.dbuf,
1157 g_scsi_command.dbuf_len);
1158 }
1159 else /* write command */
1160 {
1161 MSS_USBH_write_out_pipe(g_msd_tdev_addr,
1162 USBH_MSC_BULK_TX_PIPE,
1163 g_tdev_out_ep.num,
1164 g_tdev_out_ep.maxpktsz,
1165 g_scsi_command.dbuf,
1166 g_scsi_command.dbuf_len); /* data_length */
1167 }
1168 }
1169 break;
1170
1171 case MSC_BOT_DATA_PHASE:
1172 if (count == g_scsi_command.dbuf_len)
1173 {
1174 g_msc_bot_state = MSC_BOT_STATUS_WAITCOMPLETE;
1175
1176 MSS_USBH_read_in_pipe(g_msd_tdev_addr,
1177 USBH_MSC_BULK_RX_PIPE,
1178 g_tdev_in_ep.num,
1179 g_tdev_in_ep.maxpktsz,
1180 g_scsi_command.sbuf,
1181 13u);
1182 }
1183 else
1184 {
1185 ASSERT(0); /* at this point all data must be transfered */
1186 }
1187 break;
1188
1189 case MSC_BOT_STATUS_WAITCOMPLETE:
1190 break;
1191
1192 default:
1193 ASSERT(0); /* g_msc_bot_state must not be in any other state */
1194 break;
1195 }
1196 }
1197 else if (MSS_USB_EP_NAK_TOUT & status)
1198 {
1199 /* Device responding with NAKs. Retry */
1200 g_msc_state = USBH_MSC_BOT_RETRY;
1201 }
1202 else
1203 {
1204 ASSERT(0);/* Handling any other error. Not yet supported */
1205 }
1206
1207 }
1208 return (USB_SUCCESS);
1209 }
1210
1211 /*
1212 * This Call-back function is executed when the data IN transfer initiated by
1213 * this driver is complete.
1214 */
1215 uint8_t
usbh_msc_rx_cb(uint8_t tdev_addr,uint8_t status,uint32_t count)1216 usbh_msc_rx_cb
1217 (
1218 uint8_t tdev_addr,
1219 uint8_t status,
1220 uint32_t count
1221 )
1222 {
1223 if (g_msc_state < USBH_MSC_DEVICE_READY)
1224 {
1225 g_usbh_msc_rx_event = 1u;
1226 }
1227 else
1228 {
1229 if (0x0U == status)
1230 {
1231 switch (g_msc_bot_state)
1232 {
1233 case MSC_BOT_DATA_PHASE:
1234 if (count == g_scsi_command.dbuf_len)
1235 {
1236 g_msc_bot_state = MSC_BOT_STATUS_WAITCOMPLETE;
1237
1238 MSS_USBH_read_in_pipe(g_msd_tdev_addr,
1239 USBH_MSC_BULK_RX_PIPE,
1240 g_tdev_in_ep.num,
1241 g_tdev_in_ep.maxpktsz,
1242 g_scsi_command.sbuf,
1243 13u);
1244 }
1245 else
1246 {
1247 ASSERT(0);/* at this point all data must be transferred */
1248 }
1249 break;
1250
1251 case MSC_BOT_STATUS_WAITCOMPLETE:
1252 g_usbh_msc_rx_event = 0u;
1253 g_scsi_command.st = 0u;
1254 g_msc_bot_state = MSC_BOT_IDLE;
1255 break;
1256
1257 default:
1258 ASSERT(0);/*g_msc_bot_state must not be in any other state */
1259 break;
1260 }
1261 }
1262 else if (MSS_USB_EP_NAK_TOUT & status)
1263 {
1264 /* Device responding with NAKs. Retry */
1265 g_msc_state = USBH_MSC_BOT_RETRY;
1266 }
1267 else
1268 {
1269 ASSERT(0);/* Handling any other error. Not yet supported */
1270 }
1271 }
1272
1273 return (USB_SUCCESS);
1274 }
1275
1276 /*
1277 * This function validates the MSC class descriptors.
1278 */
1279 mss_usbh_msc_err_code_t
MSS_USBH_MSC_validate_class_desc(uint8_t * p_cd)1280 MSS_USBH_MSC_validate_class_desc
1281 (
1282 uint8_t* p_cd
1283 )
1284 {
1285 return(USBH_MSC_NO_ERROR);
1286 }
1287
1288 /*
1289 * This function extract the endpoint information from the Config Descriptor.
1290 */
1291 mss_usbh_msc_err_code_t
MSS_USBH_MSC_extract_tdev_ep_desc(void)1292 MSS_USBH_MSC_extract_tdev_ep_desc
1293 (
1294 void
1295 )
1296 {
1297 mss_usbh_msc_err_code_t error = USBH_MSC_NO_ERROR;
1298
1299 if (!(g_msd_conf_desc[21u] & USB_EP_DESCR_ATTR_BULK)) /* FirstEP Attributes Not BulkEP */
1300 {
1301 error = USBH_MSC_WRONG_DESCR;
1302 }
1303 if (!(g_msd_conf_desc[28u] & USB_EP_DESCR_ATTR_BULK)) /*SecondEP Attributes Not BulkEP */
1304 {
1305 error = USBH_MSC_WRONG_DESCR;
1306 }
1307
1308 if (g_msd_conf_desc[20u] & USB_STD_REQ_DATA_DIR_MASK) /* TdevEP is IN type */
1309 {
1310 g_tdev_in_ep.num = (g_msd_conf_desc[20u] & 0x7fu);
1311 g_tdev_in_ep.maxpktsz = (uint16_t)((g_msd_conf_desc[23u] << 8u) |
1312 (g_msd_conf_desc[22u]));
1313
1314 g_tdev_out_ep.num = (g_msd_conf_desc[27u] & 0x7fu);
1315 g_tdev_out_ep.maxpktsz = (uint16_t)((g_msd_conf_desc[30u] << 8u) |
1316 (g_msd_conf_desc[29u]));
1317
1318 }
1319 else if (g_msd_conf_desc[27u] & USB_STD_REQ_DATA_DIR_MASK)
1320 {
1321 g_tdev_in_ep.num = (g_msd_conf_desc[27u] & 0x7fu);
1322 g_tdev_in_ep.maxpktsz = (uint16_t)((g_msd_conf_desc[30u] << 8u) |
1323 (g_msd_conf_desc[29u]));
1324
1325 g_tdev_out_ep.num = (g_msd_conf_desc[20u] & 0x7fu);
1326 g_tdev_out_ep.maxpktsz = (uint16_t)((g_msd_conf_desc[23u] << 8u) |
1327 (g_msd_conf_desc[22u]));
1328 }
1329 else
1330 {
1331 error = USBH_MSC_WRONG_DESCR;
1332 }
1333
1334 return(error);
1335 }
1336
1337 #endif /* MSS_USB_HOST_ENABLED */
1338
1339 #ifdef __cplusplus
1340 }
1341 #endif
1342