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 driver
9 *
10 * USBH driver implementation:
11 * This source file implements the common functionality of USB host mode
12 *
13 */
14
15
16 #include "mpfs_hal/mss_hal.h"
17 #include "mss_usb_common_cif.h"
18 #include "mss_usb_common_reg_io.h"
19 #include "mss_usb_host.h"
20 #include "mss_usb_host_cif.h"
21 #include "mss_usb_host_reg_io.h"
22 #include "mss_usb_std_def.h"
23
24
25 #ifdef __cplusplus
26 extern "C" {
27 #endif
28
29 #ifdef MSS_USB_HOST_ENABLED
30
31 /***************************************************************************//**
32 Constant values internally used by USBH driver.
33 */
34 #define MSS_USB_1ms_DIVISION_VAL 1000u /*In miliSeconds*/
35 #define MSS_USB_TARGET_RESET_DELAY 20u /*In miliSeconds*/
36 #define MSS_USB_TARGET_VRISE_DELAY 20u /*In miliSeconds*/
37 #define MSS_USB_TARGET_SUSPEND_DELAY 20u /*In miliSeconds*/
38
39 /***************************************************************************//**
40 Types internally used by USBH driver.
41 */
42 typedef enum enum_state {
43 ENUM_IDLE,
44 ENUM_GET_DEF_DEV_DESC,
45 ENUM_WAIT_GET_DEF_DEV_DESC,
46 ENUM_RESET_TDEV,
47 ENUM_CLR_RESET_TDEV,
48 ENUM_SET_TDEV_ADDR,
49 ENUM_WAIT_SET_TDEV_ADDR,
50 ENUM_GET_FUL_DEV_DESC,
51 ENUM_WAIT_GET_FUL_DEV_DESC,
52 ENUM_GET_DEF_CONFG_DESC,
53 ENUM_WAIT_GET_DEF_CONFG_DESC,
54 ENUM_GET_FUL_CONFG_DESC,
55 ENUM_WAIT_GET_FUL_CONFG_DESC,
56 ENUM_CHECK_TDEV_CLASS_SUPPORT,
57 ENUM_SUCCESS,
58 ENUM_ERROR,
59 ENUM_PET_SET_CONFIG,
60 ENUM_PET_WAIT_SET_CONFIG
61 } mss_usb_enum_state_t;
62
63 typedef enum host_state {
64 HOST_IDLE,
65 HOST_ROOT_TARGET_DETECTED,
66 HOST_ROOT_TARGET_RESETING,
67 HOST_ROOT_TARGET_ENUMERATING,
68 HOST_ROOT_TARGET_ALLOCATE_CLASSD,
69 HOST_ROOT_TARGET_SERVICING,
70 HOST_ROOT_TARGET_ERROR
71 } mss_usbh_state_t;
72
73 typedef enum {
74 TDEV_R,
75 TDEV_RHP1,
76 TDEV_RHP2
77 } tdev_id_t;
78
79 /***************************************************************************//**
80 Data structures internally used by USBH driver.
81 */
82 typedef struct {
83 uint8_t alloc_state;
84 mss_usbh_class_cb_t* class_handle;
85 } class_driver_info_t;
86
87 /* This structure type is used to read device and config descriptor from pen drive.
88 At a time only one descriptor is operated upon.*/
89 typedef struct {
90 union
91 {
92 uint8_t da[20];
93 dev_desc_t ds;
94 }dev_desc;
95 union
96 {
97 /* Def_confg + First Interface Desc+AddressAlign */
98 uint8_t ca[20];
99 def_conf_desc_t cs;
100 }conf_desc;
101 int8_t desc_err_code;
102 } tdev_desc_t;
103
104 /******************************************************************************
105 Global variable declarations for this file (USBH Driver).
106 */
107
108 /* Flags to indicate the Callback Events */
109 uint8_t volatile gh_tdev_connect_event = 0u;
110 uint8_t volatile gh_tdev_discon_event = 0u;
111 uint8_t volatile gh_cep_cb_event = 0u;
112
113 /* Track the physically connected number of target devices */
114 tdev_id_t tdev_idx = TDEV_R;
115
116 /*
117 * Information about the connected target devices
118 * Index of this array is tdev_idx i.e. physical location on SF2 receptacle.
119 */
120 static mss_usbh_tdev_info_t g_tdev[1];
121 int8_t g_tdev_error_code = 0;
122
123 /*
124 * Holds the Target device descriptor information.
125 * Currently we support only one device. Still an array is used so that future
126 * support for multiple devices would be easy.
127 * MPH:Number of connected target Devices.
128 */
129 static tdev_desc_t g_tdev_desc[1];
130
131 /* General purpose milliseconds count */
132 volatile uint32_t ms = 0;
133
134 /* Track current state of the Host */
135 static mss_usbh_state_t g_host_state = HOST_IDLE;
136
137 /* Track current state of ENUMERATION FSM */
138 static mss_usb_enum_state_t g_enum_state = ENUM_IDLE;
139
140 /* MSS USB has 4 Transmit, 4 Receive and one control Endpoint */
141 mss_usb_ep_t gh_tx_ep[5]; /*[0] ==> Control EP*/
142 mss_usb_ep_t gh_rx_ep[5]; /*[0] ==> Empty*/
143
144 /* Use this at time of class allocation after device is enumerated
145 * Currently we support only one device.Hence one Class allocation, still an
146 * array is used so that future support for multiple devices would be easy.*/
147 /* MPH:Number of registered classes */
148 static class_driver_info_t g_rcd[1];
149
150 static volatile uint8_t g_cep_xfr_result = MSS_USB_EP_XFR_SUCCESS;
151
152 /* User application call-back handler */
153 static mss_usbh_user_cb_t* g_user_cb;
154
155 /* Apart from this driver, Class drivers can also do a CEP transfers as per
156 * need. This variable is to differentiate between transfers started by this
157 * driver and CRP transfers started by Class driver.
158 */
159 static volatile uint8_t g_internal_cep_xfr = 0u;
160
161 extern volatile uint8_t txep_irq;
162
163 /******************************************************************************
164 Private function declarations for this file (USBH driver).
165 */
166 static void mss_usbh_enum_fsm(void);
167 static void mss_usbh_control_xfr_fsm(void);
168
169 /* Call-back functions used by Host CIF layer to communicate with this layer */
170 static void mss_usbh_ep_tx_complete_cb(uint8_t ep_num, uint8_t status);
171 static void mss_usbh_ep_rx_cb(uint8_t ep_num, uint8_t status);
172 static void mss_usbh_cep_cb(uint8_t status);
173 static void mss_usbh_sof_cb(uint32_t frame_number);
174 static void mss_usbh_connect_cb(mss_usb_device_speed_t target_speed,
175 mss_usb_vbus_level_t vbus_level);
176
177 static void mss_usbh_disconnect_cb(void);
178 static void mss_usbh_vbus_err_cb(mss_usb_vbus_level_t vbus_level);
179 static void mss_usbh_babble_err_cb(void);
180 static void mss_usbh_session_request_cb(void);
181 static void mss_usbh_dma_handler_cb(mss_usb_ep_num_t ep_num,
182 mss_usb_dma_dir_t dma_dir, uint8_t status,
183 uint32_t dma_addr_val);
184
185 static int8_t host_enum_check_class_support(tdev_id_t tid);
186 static int8_t validate_dev_desc(dev_desc_t* p_desc);
187 static int8_t validate_def_conf_desc(def_conf_desc_t* p_desc);
188 static void mss_usbh_fsm(void);
189 static void mss_usbh_reset_enum_fsm(void);
190 static void mss_usbh_start_enum_fsm(void);
191 static mss_usb_enum_state_t mss_usbh_get_enum_fsm_state(void);
192 static void mss_usbh_handle_discon_event(void);
193
194 /* Host call-back functions */
195 mss_usbh_cb_t g_mss_usbh_cb = {
196 mss_usbh_ep_tx_complete_cb,
197 mss_usbh_ep_rx_cb,
198 mss_usbh_cep_cb,
199 mss_usbh_sof_cb,
200 mss_usbh_connect_cb,
201 mss_usbh_disconnect_cb,
202 mss_usbh_vbus_err_cb,
203 mss_usbh_babble_err_cb,
204 mss_usbh_session_request_cb,
205 mss_usbh_dma_handler_cb
206 };
207
208 /*******************************************************************************
209 * EXPORTED API Functions
210 *******************************************************************************/
211 /******************************************************************************
212 * See mss_usb_host.h for details of how to use this function.
213 */
214 void
MSS_USBH_init(mss_usbh_user_cb_t * app_cb)215 MSS_USBH_init
216 (
217 mss_usbh_user_cb_t* app_cb
218 )
219 {
220 /*
221 * By Default Prepare CEP for HS target.
222 * Actual speed will be found in Enumeration FSM
223 */
224 g_tdev[TDEV_R].addr = USB_DEFAULT_TARGET_ADDR;
225 g_tdev[TDEV_R].speed = MSS_USB_DEVICE_HS;
226 g_tdev[TDEV_R].state = MSS_USB_NOT_ATTACHED_STATE;
227 g_tdev[TDEV_R].hub_addr = 0u;
228 g_tdev[TDEV_R].hub_port = 0u;
229 g_tdev[TDEV_R].hub_mtt = 0u;
230 g_tdev[TDEV_R].tdev_maxpktsz0 = CEP_MAX_PKT_SIZE;
231 g_tdev[TDEV_R].class_handle = 0u;
232 g_user_cb = app_cb;
233
234 /* Initialize host core interface layer */
235 MSS_USBH_CIF_init();
236 MSS_USBH_configure_control_pipe(TDEV_R);
237 }
238
239 /******************************************************************************
240 * See mss_usb_host.h for details of how to use this function.
241 */
242 int8_t
MSS_USBH_register_class_driver(void * class_handle)243 MSS_USBH_register_class_driver
244 (
245 void* class_handle
246 )
247 {
248 volatile int8_t value = 0;
249
250 g_rcd[0].alloc_state = 0u;
251 if ((mss_usbh_class_cb_t*)0 != class_handle)
252 {
253 g_rcd[0].class_handle = (mss_usbh_class_cb_t*)class_handle;
254 value = 0;
255 }
256 else
257 {
258 value = 1;
259 }
260
261 return(value);
262 }
263
264 /******************************************************************************
265 * See mss_usb_host.h for details of how to use this function.
266 */
267 int8_t
MSS_USBH_configure_control_pipe(uint8_t target_addr)268 MSS_USBH_configure_control_pipe
269 (
270 uint8_t target_addr
271 )
272 {
273 tdev_id_t tid = (tdev_id_t)0u;
274 mss_usb_ep_t* cep_ptr = &gh_tx_ep[MSS_USB_CEP];
275
276 /*
277 * Find the physical location of Target Device from Assigned address.
278 * This will be used to call the correct call-back function assigned to this
279 * address.
280 * For multiple devices support using a HUB will be must. we intent to assign
281 * non-zero device addresses starting with 1 (This will be HUB).This will be
282 * done by this driver in mss_usbh_enum_fsm() function. This way array indexing
283 * will be easier. But all this only when Multiple devices are supported.
284 * Currently we assign 0x10 as the non-zero address for single connected device
285 * and this will evaluate tdex_idx to 0.
286 */
287 tid = (tdev_id_t)(target_addr & 0x03u);
288 cep_ptr->tdev_idx = tid;
289
290 cep_ptr->num = MSS_USB_CEP;
291 cep_ptr->fifo_size = 64u;
292 cep_ptr->max_pkt_size = g_tdev[tid].tdev_maxpktsz0;
293 cep_ptr->num_usb_pkt = 1u;
294 cep_ptr->state = MSS_USB_CEP_IDLE;
295
296 /* Control Endpoint Config is fixed. NakLimit = MaxVal.*/
297 cep_ptr->interval = 32768u;
298
299 MSS_USBH_CIF_cep_configure(cep_ptr);
300
301 /* Type0:Default target speed */
302 MSS_USBH_CIF_cep_set_type0_reg(g_tdev[tid].speed);
303 MSS_USBH_CIF_tx_ep_set_target_func_addr(MSS_USB_CEP,target_addr);
304
305 return (0);
306 }
307
308 /******************************************************************************
309 * See mss_usb_host.h for details of how to use this function.
310 */
311 int8_t
MSS_USBH_configure_out_pipe(uint8_t target_addr,uint8_t outpipe_num,uint8_t target_ep,uint16_t fifo_addr,uint16_t fifo_size,uint16_t max_pkt_size,uint8_t num_usb_pkt,uint8_t dma_enable,mss_usb_dma_channel_t dma_channel,mss_usb_xfr_type_t xfr_type,uint32_t add_zlp,uint32_t interval)312 MSS_USBH_configure_out_pipe
313 (
314 uint8_t target_addr,
315 uint8_t outpipe_num,
316 uint8_t target_ep,
317 uint16_t fifo_addr,
318 uint16_t fifo_size,
319 uint16_t max_pkt_size,
320 uint8_t num_usb_pkt,
321 uint8_t dma_enable,
322 mss_usb_dma_channel_t dma_channel,
323 mss_usb_xfr_type_t xfr_type,
324 uint32_t add_zlp,
325 uint32_t interval
326 )
327 {
328 mss_usb_ep_t* txep_ptr = &gh_tx_ep[outpipe_num];
329
330 /* TODO: Error check for all the parameters. */
331 tdev_id_t tid = (tdev_id_t)0u;
332
333 tid = (tdev_id_t)(target_addr & 0x03u);
334 txep_ptr->tdev_idx = tid;
335
336 txep_ptr->num = (mss_usb_ep_num_t)outpipe_num;
337 txep_ptr->dpb_enable = DPB_DISABLE;
338 txep_ptr->fifo_size = fifo_size;
339 txep_ptr->fifo_addr =fifo_addr;
340 txep_ptr->dma_enable =dma_enable;
341 txep_ptr->dma_channel =dma_channel;
342 txep_ptr->max_pkt_size = max_pkt_size;
343 txep_ptr->stall = 0u;
344 txep_ptr->state = MSS_USB_EP_VALID;
345 txep_ptr->xfr_type = xfr_type;
346 txep_ptr->add_zlp = add_zlp;
347 txep_ptr->num_usb_pkt = 1u;
348 txep_ptr->buf_addr = 0u;
349
350 txep_ptr->xfr_length = 0u;
351 txep_ptr->xfr_count = 0u;
352 txep_ptr->txn_length = 0u;
353 txep_ptr->txn_count = 0u;
354 txep_ptr->disable_ping = 1u;
355 txep_ptr->req_pkt_n = 0u;
356 txep_ptr->interval = interval;
357
358 /* Configure MP Registers with Target Device informations */
359 MSS_USBH_CIF_tx_ep_mp_configure(outpipe_num,
360 target_ep,
361 target_addr,
362 g_tdev[tid].hub_addr,
363 g_tdev[tid].hub_port,
364 g_tdev[tid].hub_mtt,
365 g_tdev[tid].speed,
366 interval,
367 xfr_type
368 );
369
370 MSS_USBH_CIF_tx_ep_configure(txep_ptr);
371
372 return (0);
373 }
374
375 /******************************************************************************
376 * See mss_usb_host.h for details of how to use this function.
377 */
378 int8_t
MSS_USBH_configure_in_pipe(uint8_t target_addr,uint8_t inpipe_num,uint8_t target_ep,uint16_t fifo_addr,uint16_t fifo_size,uint16_t max_pkt_size,uint8_t num_usb_pkt,uint8_t dma_enable,mss_usb_dma_channel_t dma_channel,mss_usb_xfr_type_t xfr_type,uint32_t add_zlp,uint32_t interval)379 MSS_USBH_configure_in_pipe
380 (
381 uint8_t target_addr,
382 uint8_t inpipe_num,
383 uint8_t target_ep,
384 uint16_t fifo_addr,
385 uint16_t fifo_size,
386 uint16_t max_pkt_size,
387 uint8_t num_usb_pkt,
388 uint8_t dma_enable,
389 mss_usb_dma_channel_t dma_channel,
390 mss_usb_xfr_type_t xfr_type,
391 uint32_t add_zlp,
392 uint32_t interval
393 )
394 {
395 /* TODO: Error check for all the parameters.*/
396 tdev_id_t tid = (tdev_id_t)0u;
397 mss_usb_ep_t* rxep_ptr = &gh_rx_ep[inpipe_num];
398
399 tid = (tdev_id_t)(target_addr & 0x03u);
400 rxep_ptr->tdev_idx = tid;
401
402 rxep_ptr->num = (mss_usb_ep_num_t)inpipe_num;
403 rxep_ptr->dpb_enable = DPB_DISABLE;
404 rxep_ptr->fifo_size = fifo_size;
405 rxep_ptr->fifo_addr = fifo_addr;
406 rxep_ptr->dma_enable = dma_enable;
407 rxep_ptr->dma_channel = dma_channel;
408 rxep_ptr->max_pkt_size = max_pkt_size;
409 rxep_ptr->stall = 0u;
410 rxep_ptr->state = MSS_USB_EP_VALID;
411 rxep_ptr->xfr_type = xfr_type;
412 rxep_ptr->add_zlp = add_zlp;
413 rxep_ptr->num_usb_pkt = 1u;
414 rxep_ptr->buf_addr = 0u;
415
416 rxep_ptr->xfr_length = 0u;
417 rxep_ptr->xfr_count = 0u;
418 rxep_ptr->txn_length = 0u;
419 rxep_ptr->txn_count = 0u;
420
421 rxep_ptr->disable_ping = 1u;
422 rxep_ptr->req_pkt_n = 0u;
423
424 rxep_ptr->interval = interval;
425
426 /* Configure MP Registers with Target Device informations */
427 MSS_USBH_CIF_rx_ep_mp_configure(inpipe_num,
428 target_ep,
429 target_addr,
430 g_tdev[tid].hub_addr,
431 g_tdev[tid].hub_port,
432 g_tdev[tid].hub_mtt,
433 g_tdev[tid].speed,
434 interval,
435 xfr_type);
436
437 MSS_USBH_CIF_rx_ep_configure(rxep_ptr);
438
439 return (0);
440 }
441
442 /******************************************************************************
443 * See mss_usb_host.h for details of how to use this function.
444 */
445 int8_t
MSS_USBH_write_out_pipe(uint8_t target_addr,uint8_t outpipe_num,uint8_t tdev_ep_num,uint16_t maxpktsz,uint8_t * buf,uint32_t length)446 MSS_USBH_write_out_pipe
447 (
448 uint8_t target_addr,
449 uint8_t outpipe_num,
450 uint8_t tdev_ep_num,
451 uint16_t maxpktsz,
452 uint8_t* buf,
453 uint32_t length
454 )
455 {
456 mss_usb_ep_t* txep_ptr = &gh_tx_ep[outpipe_num];
457
458 /* TODO: Error check for all the parameters. */
459 tdev_id_t tid = (tdev_id_t)0u;
460
461 ASSERT(target_addr);
462 ASSERT(outpipe_num);
463 ASSERT(tdev_ep_num);
464 ASSERT(maxpktsz);
465 ASSERT(buf);
466
467 if ((target_addr != 0) && (outpipe_num != 0) && (tdev_ep_num != 0) &&
468 (maxpktsz != 0u) && (buf != 0u) )
469 {
470 tid = (tdev_id_t)(target_addr & 0x03u);
471 txep_ptr->tdev_idx = tid;
472
473 txep_ptr->xfr_length = length;
474
475 if (length > maxpktsz)
476 {
477 txep_ptr->txn_length = maxpktsz;
478 }
479 else
480 {
481 txep_ptr->txn_length = length;
482 }
483
484 txep_ptr->xfr_count = 0u;
485 txep_ptr->txn_count = 0u;
486
487 txep_ptr->buf_addr = buf;
488 txep_ptr->state = MSS_USB_EP_VALID;
489 MSS_USB_CIF_ep_write_pkt(txep_ptr->num,
490 txep_ptr->buf_addr,
491 txep_ptr->dma_enable,
492 txep_ptr->dma_channel,
493 txep_ptr->xfr_type,
494 txep_ptr->xfr_length,
495 txep_ptr->txn_length);
496
497 return (0);
498 }
499 else
500 {
501 return (1);
502 }
503 }
504
505 /******************************************************************************
506 * See mss_usb_host.h for details of how to use this function.
507 */
508 int8_t
MSS_USBH_read_in_pipe(uint8_t target_addr,uint8_t inpipe_num,uint8_t tdev_ep_num,uint16_t tdev_ep_maxpktsz,uint8_t * buf,uint32_t length)509 MSS_USBH_read_in_pipe
510 (
511 uint8_t target_addr,
512 uint8_t inpipe_num,
513 uint8_t tdev_ep_num,
514 uint16_t tdev_ep_maxpktsz,
515 uint8_t* buf,
516 uint32_t length
517 )
518 {
519 mss_usb_ep_t* rxep_ptr = &gh_rx_ep[inpipe_num];
520
521 /* TODO: Error check for all the parameters. */
522 tdev_id_t tid = (tdev_id_t)0u;
523
524 ASSERT(target_addr);
525 ASSERT(inpipe_num);
526 ASSERT(tdev_ep_num);
527 ASSERT(tdev_ep_maxpktsz);
528 ASSERT(buf);
529
530 if ((target_addr != 0) && (inpipe_num != 0) && (tdev_ep_num != 0) &&
531 (tdev_ep_maxpktsz != 0u) && (buf != 0u))
532 {
533 tid = (tdev_id_t)(target_addr & 0x03u);
534 rxep_ptr->tdev_idx = tid;
535
536 rxep_ptr->xfr_length = length;
537
538 if (length > tdev_ep_maxpktsz)
539 {
540 rxep_ptr->txn_length = tdev_ep_maxpktsz;
541 }
542 else
543 {
544 rxep_ptr->txn_length = length;
545 }
546
547 rxep_ptr->xfr_count = 0u;
548 rxep_ptr->txn_count = 0u;
549 rxep_ptr->buf_addr = buf;
550
551 if ((DMA_ENABLE == rxep_ptr->dma_enable) &&
552 (MSS_USB_XFR_BULK == rxep_ptr->xfr_type))
553 {
554 if (rxep_ptr->xfr_length >= rxep_ptr->max_pkt_size)
555 {
556 MSS_USBH_CIF_rx_ep_set_reqpkt_count(rxep_ptr->num,
557 (rxep_ptr->xfr_length/
558 rxep_ptr->max_pkt_size));
559 }
560 MSS_USBH_CIF_rx_ep_set_autoreq(rxep_ptr->num);
561 }
562
563 if ((rxep_ptr->max_pkt_size <= rxep_ptr->fifo_size) &&
564 (rxep_ptr->txn_length <= rxep_ptr->fifo_size))
565 {
566 MSS_USB_CIF_rx_ep_read_prepare(rxep_ptr->num,
567 rxep_ptr->buf_addr,
568 rxep_ptr->dma_enable,
569 rxep_ptr->dma_channel,
570 rxep_ptr->xfr_type,
571 rxep_ptr->xfr_length);
572 MSS_USBH_CIF_rx_ep_set_reqpkt((mss_usb_ep_num_t)inpipe_num);
573 }
574 return (0);
575 }
576 else
577 {
578 return (1);
579 }
580 }
581
582 /******************************************************************************
583 * See mss_usb_host.h for details of how to use this function.
584 */
585 mss_usb_state_t
MSS_USBH_get_tdev_state(uint8_t target_addr)586 MSS_USBH_get_tdev_state
587 (
588 uint8_t target_addr
589 )
590 {
591 tdev_id_t tid = (tdev_id_t)0;
592
593 if (target_addr)
594 {
595 tid = (tdev_id_t)(target_addr & 0x03u);
596 }
597
598 ASSERT(g_tdev[tid].addr == target_addr);
599
600 return (g_tdev[tid].state);
601 }
602
603 /******************************************************************************
604 * See mss_usb_host.h for details of how to use this function.
605 */
606 void
MSS_USBH_task(void)607 MSS_USBH_task
608 (
609 void
610 )
611 {
612 mss_usbh_control_xfr_fsm();
613 mss_usbh_enum_fsm();
614 mss_usbh_fsm();
615 }
616
617 /******************************************************************************
618 * See mss_usb_host.h for details of how to use this function.
619 */
620 uint8_t
MSS_USBH_start_control_xfr(uint8_t * cbuf_addr,uint8_t * dbuf_addr,uint8_t data_dir,uint32_t data_len)621 MSS_USBH_start_control_xfr
622 (
623 uint8_t* cbuf_addr,
624 uint8_t* dbuf_addr,
625 uint8_t data_dir,
626 uint32_t data_len
627 /*Add tdev_addr, speed and tdevmaxpktsz as the parameter*/
628 )
629 {
630 mss_usb_ep_t* cep_ptr = &gh_tx_ep[MSS_USB_CEP];
631
632 ASSERT(cbuf_addr != (uint8_t*)0);
633 ASSERT(dbuf_addr != (uint8_t*)0);
634 ASSERT(!(((uint32_t)cbuf_addr) & 0x00000002U));
635 ASSERT(!(((uint32_t)dbuf_addr) & 0x00000002U));
636 ASSERT((data_dir == USB_STD_REQ_DATA_DIR_IN) ||
637 (data_dir == USB_STD_REQ_DATA_DIR_OUT));
638
639 cep_ptr->buf_addr = dbuf_addr;
640 cep_ptr->cep_cmd_addr = cbuf_addr;
641
642 cep_ptr->xfr_length = data_len;
643
644 /* Set the logical MaxPktSize of Host CEP to the MazPktsz of the associated
645 * Target CEP
646 */
647 /* TODO: Copy from Parameter*/
648 /* cep_ptr->max_pkt_size = cep_ptr->tdev_addr */
649
650 cep_ptr->cep_data_dir = data_dir;
651 cep_ptr->xfr_count = 0u;
652 cep_ptr->txn_count = 0u;
653 cep_ptr->xfr_type = MSS_USB_XFR_CONTROL;
654
655 g_cep_xfr_result = 0u;
656
657 MSS_USBH_CIF_load_tx_fifo(MSS_USB_CEP,
658 cbuf_addr,
659 USB_SETUP_PKT_LEN);
660
661 cep_ptr->state = MSS_USB_CEP_SETUP;
662 MSS_USBH_CIF_cep_set_setuppktrdy();
663
664 return (0);
665 }
666
667 /******************************************************************************
668 * See mss_usb_host.h for details of how to use this function.
669 */
670 void
MSS_USBH_construct_get_descr_command(uint8_t * buf,uint8_t xfr_dir,uint8_t req_type,uint8_t recip_type,uint8_t request,uint8_t desc_type,uint8_t strng_idx,uint16_t length)671 MSS_USBH_construct_get_descr_command
672 (
673 uint8_t* buf,
674 uint8_t xfr_dir,
675 uint8_t req_type,
676 uint8_t recip_type,
677 uint8_t request,
678 uint8_t desc_type,
679 uint8_t strng_idx,
680 uint16_t length
681 )
682 {
683 /* bmRequestType */
684 buf[0] = (xfr_dir| req_type| recip_type);
685
686 /* bRequest */
687 buf[1] = request;
688
689 /* wValue-MSB = desc_type */
690 buf[3] = desc_type;
691
692 if ((request == USB_STD_REQ_GET_DESCRIPTOR) &&
693 (desc_type == USB_STRING_DESCRIPTOR_TYPE))
694 {
695 /* We support only one LANGID 0x0409.
696 * Refer USB standards for list of all supported LangIDs */
697 buf[2] = strng_idx; /* wValue-LSB = string_idx */
698 buf[4] = (uint8_t)0x09u; /* wIndex-LSB = LangID for string Desc */
699 buf[5] = (uint8_t)0x04u; /* wIndex-MSB */
700 }
701 else
702 {
703 /*
704 * wValue-LSB = Conf_idx, Field should be used only for Conf_desc or
705 * String Desc.
706 * Since we support only one configuration, we set it to zero for
707 * Conf_desc. For all other descriptors this field must be zero
708 */
709 buf[2] = 0x00U;
710
711 /* wIndex-LSB and MSB => other than String Desc, these values must be
712 * zero */
713 buf[4] = 0x00U;
714 buf[5] = 0x00U;
715 }
716
717 /* wLength-LSB and MSB, Length of data to be received */
718 buf[6] = (uint8_t)length;
719 buf[7] = (uint8_t)(length >> 8u);
720 }
721
722 /******************************************************************************
723 * See mss_usb_host.h for details of how to use this function.
724 */
725 mss_usb_ep_state_t
MSS_USBH_get_cep_state(void)726 MSS_USBH_get_cep_state
727 (
728 void
729 )
730 {
731 return (gh_tx_ep[MSS_USB_CEP].state);
732 }
733
734 /******************************************************************************
735 * See mss_usb_host.h for details of how to use this function.
736 */
737 void
MSS_USBH_1ms_tick(void)738 MSS_USBH_1ms_tick
739 (
740 void
741 )
742 {
743 ms++;
744 }
745
746 /******************************************************************************
747 * See mss_usb_host.h for details of how to use this function.
748 */
749 uint32_t
MSS_USBH_get_milis(void)750 MSS_USBH_get_milis
751 (
752 void
753 )
754 {
755 return (ms);
756 }
757
758 /******************************************************************************
759 * See mss_usb_host.h for details of how to use this function.
760 */
761 int8_t
MSS_USBH_get_std_dev_descr(uint8_t * buffer)762 MSS_USBH_get_std_dev_descr
763 (
764 uint8_t* buffer
765 )
766 {
767 uint8_t command_buf[USB_SETUP_PKT_LEN] = {0};
768
769 g_internal_cep_xfr = 1u;
770
771 /* 0x10 is the fixed non-zero device address we are using */
772 MSS_USBH_configure_control_pipe(0x10u);
773
774 memset(command_buf, 0u, USB_SETUP_PKT_LEN *(sizeof(uint8_t)));
775
776 /* Read first 8 bytes of the Device descriptor */
777 MSS_USBH_construct_get_descr_command(command_buf,
778 USB_STD_REQ_DATA_DIR_IN,
779 USB_STANDARD_REQUEST,
780 USB_STD_REQ_RECIPIENT_DEVICE,
781 USB_STD_REQ_GET_DESCRIPTOR,
782 USB_DEVICE_DESCRIPTOR_TYPE,
783 0u,
784 8u);
785
786 MSS_USBH_start_control_xfr(command_buf,
787 buffer,
788 USB_STD_REQ_DATA_DIR_IN,
789 8u);
790
791 /* Wait for internal CEP transfer to complete */
792 while ((0u == g_cep_xfr_result) && (g_internal_cep_xfr == 1u))
793 {
794 ;
795 }
796
797 if (MSS_USB_EP_XFR_SUCCESS == g_cep_xfr_result)
798 {
799 return 0;
800 }
801 else
802 {
803 return -1;
804 }
805 }
806
807 /******************************************************************************
808 * See mss_usb_host.h for details of how to use this function.
809 */
810 void
MSS_USBH_test_mode(uint8_t test_case)811 MSS_USBH_test_mode
812 (
813 uint8_t test_case
814 )
815 {
816 switch (test_case)
817 {
818 case USB_TEST_MODE_SELECTOR_TEST_PACKET:
819 MSS_USB_CIF_start_testpacket();
820 break;
821
822 case USB_TEST_MODE_SELECTOR_TEST_J:
823 MSS_USB_CIF_start_testj();
824 break;
825
826 case USB_TEST_MODE_SELECTOR_TEST_K:
827 MSS_USB_CIF_start_testk();
828 break;
829
830 case USB_TEST_MODE_SELECTOR_TEST_SE0NAK:
831 MSS_USB_CIF_start_testse0nak();
832 break;
833
834 case USB_TEST_MODE_SELECTOR_TEST_FORCE_ENA:
835 MSS_USB_CIF_start_forcehost_ena();
836 break;
837
838 default:
839 /* Empty default */
840 break;
841 }
842 }
843
844 /******************************************************************************
845 * See mss_usb_host.h for details of how to use this function.
846 */
847 void
MSS_USBH_suspend(void)848 MSS_USBH_suspend
849 (
850 void
851 )
852 {
853 /* suspendM enabled. RemoteWakeup not supported. */
854 MSS_USBH_CIF_bus_suspend(0u);
855 }
856
857 /******************************************************************************
858 * See mss_usb_host.h for details of how to use this function.
859 */
860 void
MSS_USBH_resume(void)861 MSS_USBH_resume
862 (
863 void
864 )
865 {
866 volatile static uint32_t resume_milis = 0u;
867
868 resume_milis = MSS_USBH_get_milis();
869
870 MSS_USBH_CIF_clr_suspend_bus();
871
872 MSS_USBH_CIF_assert_bus_resume();
873
874 /* This delay should be at lease 20ms */
875 while ((MSS_USBH_get_milis() - resume_milis) <= 40u)
876 {
877 ;
878 }
879
880 MSS_USBH_CIF_clr_bus_resume();
881 }
882
883 void
MSS_USBH_abort_in_pipe(mss_usb_ep_num_t inpipe_num)884 MSS_USBH_abort_in_pipe
885 (
886 mss_usb_ep_num_t inpipe_num
887 )
888 {
889 MSS_USBH_CIF_rx_ep_clr_reqpkt(inpipe_num);
890 MSS_USBH_CIF_rx_ep_clr_naktimeout_err(inpipe_num);
891 MSS_USBH_CIF_rx_ep_clr_rxstall_err(inpipe_num);
892 MSS_USBH_CIF_rx_ep_clr_retry_err(inpipe_num);
893 if (MSS_USBH_CIF_rx_ep_is_rxpktrdy(inpipe_num))
894 {
895 MSS_USBH_CIF_rx_ep_flush_fifo_reg(inpipe_num);
896 MSS_USB_CIF_rx_ep_clr_rxpktrdy(inpipe_num);
897 }
898 }
899
900 void
MSS_USBH_abort_out_pipe(mss_usb_ep_num_t outpipe_num)901 MSS_USBH_abort_out_pipe
902 (
903 mss_usb_ep_num_t outpipe_num
904 )
905 {
906 gh_tx_ep[outpipe_num].state = MSS_USB_EP_ABORTED;
907
908 MSS_USBH_CIF_tx_ep_clr_autoset(outpipe_num);
909 MSS_USBH_CIF_tx_ep_flush_fifo_reg(outpipe_num);
910 MSS_USB_CIF_tx_ep_disable_dma(outpipe_num);
911 MSS_USBH_CIF_tx_ep_clr_retry_err(outpipe_num);
912 MSS_USBH_CIF_tx_ep_clr_rxstall_err(outpipe_num);
913 MSS_USBH_CIF_tx_ep_clr_naktimeout_err(outpipe_num);
914 }
915
916 /*******************************************************************************
917 * Internal Functions
918 *******************************************************************************/
919 /*
920 * This function is the main FSM of the USB Host. It handles connect/disconnect
921 * events, initiate enumeration FSM when device is detected and handles allocation
922 * of class driver to the device.
923 */
924 static void
mss_usbh_fsm(void)925 mss_usbh_fsm
926 (
927 void
928 )
929 {
930 static uint32_t reset_milis = 0u;
931 mss_usb_enum_state_t enum_st;
932
933 if (1u == gh_tdev_discon_event)
934 {
935 mss_usbh_handle_discon_event();
936 gh_tdev_discon_event = 0u;
937 g_host_state = HOST_IDLE;
938 }
939 switch (g_host_state)
940 {
941 case HOST_IDLE:
942 /*
943 * Repeatedly enable session bit so that MUSB sample Idig pin to
944 * detect device connection
945 */
946 MSS_USB_CIF_start_session();
947 if (gh_tdev_connect_event)
948 {
949 gh_tdev_connect_event = 0u;
950 g_tdev[tdev_idx].state = MSS_USB_ATTACHED_STATE;
951 reset_milis = MSS_USBH_get_milis();
952 g_host_state = HOST_ROOT_TARGET_DETECTED;
953 }
954 break;
955
956 case HOST_ROOT_TARGET_DETECTED:
957 /* Wait for at least 100ms for target power de-bounce as per spec */
958 if ((MSS_USBH_get_milis() - reset_milis) >= 100u)
959 {
960 MSS_USB_CIF_enable_usbirq(VBUS_ERROR_IRQ_MASK);
961 g_tdev[TDEV_R].state = MSS_USB_POWERED_STATE;
962 reset_milis = MSS_USBH_get_milis();
963 MSS_USBH_CIF_assert_bus_reset(); /*Reset Root device*/
964 g_host_state = HOST_ROOT_TARGET_RESETING;
965 }
966 break;
967
968 case HOST_ROOT_TARGET_RESETING:
969 /* Keep target device in reset, at least for 20ms as per spec */
970 if ((MSS_USBH_get_milis() - reset_milis) == 20u)
971 {
972 MSS_USBH_CIF_clr_bus_reset();
973 }
974 else if ((MSS_USBH_get_milis() - reset_milis) >= 40u)
975 {
976 /* If target was operating at FS, check if can work with HS as well */
977 if ((g_tdev[TDEV_R].speed == MSS_USB_DEVICE_FS) &&
978 (MSS_USBH_CIF_is_hs_mode()))
979 {
980 g_tdev[TDEV_R].speed = MSS_USB_DEVICE_HS;
981 }
982 if (0 != g_user_cb->usbh_tdev_attached)
983 {
984 g_user_cb->usbh_tdev_attached(g_tdev[tdev_idx].speed);
985 }
986
987 /* Configure CEP for the detected speed */
988 MSS_USBH_configure_control_pipe(TDEV_R);
989
990 g_tdev[TDEV_R].state = MSS_USB_DEFAULT_STATE;
991 g_host_state = HOST_ROOT_TARGET_ENUMERATING;
992 }
993 break;
994
995 case HOST_ROOT_TARGET_ENUMERATING:
996 enum_st = mss_usbh_get_enum_fsm_state();
997 if (ENUM_IDLE == enum_st)
998 {
999 mss_usbh_start_enum_fsm();
1000 }
1001 else if (ENUM_SUCCESS == enum_st)
1002 {
1003 g_tdev[TDEV_R].state = MSS_USB_ADDRESS_STATE;
1004
1005 mss_usbh_reset_enum_fsm();
1006 g_host_state = HOST_ROOT_TARGET_ALLOCATE_CLASSD;
1007 }
1008 else if (ENUM_ERROR == enum_st)
1009 {
1010 mss_usbh_reset_enum_fsm();
1011 g_tdev[TDEV_R].state = MSS_USB_ATTACHED_STATE;
1012 g_host_state = HOST_ROOT_TARGET_ERROR;
1013 }
1014 else
1015 {
1016 /* EnumFSM in progress, Do nothing */
1017 }
1018 break;
1019
1020 case HOST_ROOT_TARGET_ALLOCATE_CLASSD:
1021 g_rcd[TDEV_R].class_handle->usbh_class_allocate(g_tdev[TDEV_R].addr);
1022 g_host_state = HOST_ROOT_TARGET_SERVICING;
1023
1024 if (0 != g_user_cb->usbh_tdev_class_driver_assigned)
1025 {
1026 g_user_cb->usbh_tdev_class_driver_assigned();
1027 }
1028
1029 break;
1030
1031 case HOST_ROOT_TARGET_SERVICING:
1032 /* Class driver FSM is active now */
1033 break;
1034
1035 case HOST_ROOT_TARGET_ERROR:
1036 if (0 != g_user_cb->usbh_tdev_not_supported)
1037 {
1038 g_user_cb->usbh_tdev_not_supported(g_tdev_error_code);
1039 }
1040 g_host_state = HOST_IDLE;
1041
1042 /*
1043 * Clear Enum-FSM
1044 * Clear Target_info for all targets.
1045 * Clear EP0 config
1046 * Give Visual Err Indication and remain in this state,
1047 * till Disconnect Interrupt occurs or USER wants to give a retry
1048 * command.
1049 */
1050 break;
1051
1052 default:
1053 /* Empty default */
1054 break;
1055 }
1056 }
1057
1058 /*
1059 * This function handles the enumeration process which includes, device reset,
1060 * speed detection, and standard USB request for retrieving Device and Config
1061 * Descriptor from the device.
1062 */
1063 static void
mss_usbh_enum_fsm(void)1064 mss_usbh_enum_fsm
1065 (
1066 void
1067 )
1068 {
1069 uint8_t command_buf[USB_SETUP_PKT_LEN] = {0};
1070 static uint32_t reset_milis = 0u;
1071 int8_t cd_idx = 0x04;
1072 uint8_t dummy[8];
1073 /*
1074 * We do not do any assert checks here.
1075 * Before Calling this FSM, Calling function should make sure that This FSM
1076 * can be executed
1077 */
1078 switch(g_enum_state)
1079 {
1080 case ENUM_IDLE:
1081 /* Free running Enum FSM hits here when doing nothing */
1082 break;
1083
1084 case ENUM_GET_DEF_DEV_DESC:
1085 MSS_USBH_construct_get_descr_command(command_buf,
1086 USB_STD_REQ_DATA_DIR_IN,
1087 USB_STANDARD_REQUEST,
1088 USB_STD_REQ_RECIPIENT_DEVICE,
1089 USB_STD_REQ_GET_DESCRIPTOR,
1090 USB_DEVICE_DESCRIPTOR_TYPE,
1091 0u,
1092 USB_SETUP_PKT_LEN);
1093
1094 g_enum_state = ENUM_WAIT_GET_DEF_DEV_DESC;
1095
1096 MSS_USBH_start_control_xfr(command_buf,
1097 (uint8_t*)&g_tdev_desc[tdev_idx].dev_desc,
1098 USB_STD_REQ_DATA_DIR_IN,
1099 USB_SETUP_PKT_LEN);
1100 break;
1101
1102 case ENUM_WAIT_GET_DEF_DEV_DESC:
1103 if (g_cep_xfr_result)
1104 {
1105 if (MSS_USB_EP_XFR_SUCCESS == g_cep_xfr_result)
1106 {
1107 g_tdev[TDEV_R].tdev_maxpktsz0 =
1108 g_tdev_desc[TDEV_R].dev_desc.ds.bMaxPacketSize0;
1109
1110 g_enum_state = ENUM_RESET_TDEV;
1111 }
1112 else
1113 {
1114 g_enum_state = ENUM_ERROR;
1115 }
1116 }
1117 break;
1118
1119 case ENUM_RESET_TDEV:
1120 reset_milis = MSS_USBH_get_milis();
1121 MSS_USBH_CIF_assert_bus_reset();
1122 g_enum_state = ENUM_CLR_RESET_TDEV;
1123 break;
1124
1125 case ENUM_CLR_RESET_TDEV:
1126 if ((MSS_USBH_get_milis() - reset_milis) == 20u)
1127 {
1128 MSS_USBH_CIF_clr_bus_reset();
1129 }
1130 else if ((MSS_USBH_get_milis() - reset_milis) >= 40u)
1131 {
1132 /* Wait for 20ms to let the Target settle down */
1133 g_enum_state = ENUM_SET_TDEV_ADDR;
1134 }
1135 break;
1136
1137 case ENUM_SET_TDEV_ADDR:
1138 /* Configure CEP Since Maxpkt0 might have changed. */
1139 MSS_USBH_configure_control_pipe(TDEV_R);
1140
1141 memset(command_buf, 0, USB_SETUP_PKT_LEN*(sizeof(uint8_t)));
1142 command_buf[1] = USB_STD_REQ_SET_ADDRESS;
1143 command_buf[2] = 0x10U; /*New non-zero ADDR*/
1144 reset_milis = MSS_USBH_get_milis();
1145 g_enum_state = ENUM_WAIT_SET_TDEV_ADDR;
1146 MSS_USBH_start_control_xfr(command_buf,
1147 command_buf, /*Dummy Buf for zld req*/
1148 USB_STD_REQ_DATA_DIR_OUT,
1149 0u);
1150 break;
1151
1152 case ENUM_WAIT_SET_TDEV_ADDR:
1153 if (g_cep_xfr_result)
1154 {
1155 if (MSS_USB_EP_XFR_SUCCESS == g_cep_xfr_result)
1156 {
1157 int8_t res;
1158
1159 /* SetAddrDelay at least 2ms */
1160 if ((MSS_USBH_get_milis() - reset_milis) >= 5u)
1161 {
1162 g_tdev[TDEV_R].addr = 0x10U; /* New non-zero ADDR */
1163 MSS_USBH_CIF_tx_ep_set_target_func_addr(gh_tx_ep[MSS_USB_CEP].num,
1164 g_tdev[TDEV_R].addr);
1165
1166 /* Validate DevDescriptor. Take exception for FS LS
1167 * devices */
1168 res = validate_dev_desc((dev_desc_t*)&g_tdev_desc[tdev_idx].dev_desc);
1169 g_tdev_desc[tdev_idx].desc_err_code = res;
1170 if (0u == res)
1171 {
1172 g_enum_state = ENUM_GET_FUL_DEV_DESC;
1173 }
1174 else
1175 {
1176 g_enum_state = ENUM_ERROR;
1177 g_tdev_error_code = res;
1178 }
1179 }
1180 }
1181 else
1182 {
1183 g_tdev[TDEV_R].addr = 0x00u;
1184 g_enum_state = ENUM_ERROR;
1185 }
1186 }
1187 break;
1188
1189 case ENUM_GET_FUL_DEV_DESC:
1190 MSS_USBH_construct_get_descr_command(command_buf,
1191 USB_STD_REQ_DATA_DIR_IN,
1192 USB_STANDARD_REQUEST,
1193 USB_STD_REQ_RECIPIENT_DEVICE,
1194 USB_STD_REQ_GET_DESCRIPTOR,
1195 USB_DEVICE_DESCRIPTOR_TYPE,
1196 0u,
1197 USB_STD_DEVICE_DESCR_LEN);
1198
1199 g_enum_state = ENUM_WAIT_GET_FUL_DEV_DESC;
1200
1201 MSS_USBH_start_control_xfr(command_buf,
1202 (uint8_t*)&g_tdev_desc[tdev_idx].dev_desc,
1203 USB_STD_REQ_DATA_DIR_IN,
1204 USB_STD_DEVICE_DESCR_LEN);
1205 break;
1206
1207 case ENUM_WAIT_GET_FUL_DEV_DESC:
1208 if (g_cep_xfr_result)
1209 {
1210 if (MSS_USB_EP_XFR_SUCCESS == g_cep_xfr_result)
1211 {
1212 /* Support for PET device with VID = 0x1A0A PID = PID=0x0200*/
1213 if ((g_tdev_desc[tdev_idx].dev_desc.ds.idVendor == 0x1A0AU) &&
1214 (g_tdev_desc[tdev_idx].dev_desc.ds.idProduct == 0x0200U))
1215 {
1216 g_enum_state = ENUM_PET_SET_CONFIG;
1217 }
1218 else
1219 {
1220 int8_t res;
1221
1222 /* Validate DevDescriptor */
1223 res = validate_dev_desc((dev_desc_t*)&g_tdev_desc[tdev_idx].dev_desc);
1224 g_tdev_desc[tdev_idx].desc_err_code = res;
1225
1226 if (0u == res)
1227 {
1228 g_enum_state = ENUM_GET_DEF_CONFG_DESC;
1229 }
1230 else
1231 {
1232 g_enum_state = ENUM_ERROR;
1233 g_tdev_error_code = res;
1234 }
1235 }
1236 }
1237 else
1238 {
1239 g_enum_state = ENUM_ERROR;
1240 }
1241 }
1242 break;
1243
1244 case ENUM_GET_DEF_CONFG_DESC:
1245 memset(command_buf, 0u, USB_SETUP_PKT_LEN*(sizeof(uint8_t)));
1246 MSS_USBH_construct_get_descr_command(command_buf,
1247 USB_STD_REQ_DATA_DIR_IN,
1248 USB_STANDARD_REQUEST,
1249 USB_STD_REQ_RECIPIENT_DEVICE,
1250 USB_STD_REQ_GET_DESCRIPTOR,
1251 USB_CONFIGURATION_DESCRIPTOR_TYPE,
1252 0x0U, /*stringID*/
1253 USB_STD_CONFIG_DESCR_LEN);
1254
1255 g_enum_state = ENUM_WAIT_GET_DEF_CONFG_DESC;
1256
1257 MSS_USBH_start_control_xfr(command_buf,
1258 (uint8_t*)&g_tdev_desc[tdev_idx].conf_desc,
1259 USB_STD_REQ_DATA_DIR_IN,
1260 USB_STD_CONFIG_DESCR_LEN);
1261 break;
1262
1263 case ENUM_WAIT_GET_DEF_CONFG_DESC:
1264 if (g_cep_xfr_result)
1265 {
1266 if (MSS_USB_EP_XFR_SUCCESS == g_cep_xfr_result)
1267 {
1268 int8_t res;
1269 res = validate_def_conf_desc((def_conf_desc_t*)&g_tdev_desc[tdev_idx].conf_desc);
1270 g_tdev_desc[tdev_idx].desc_err_code = res;
1271 if (0u == res)
1272 {
1273 g_enum_state = ENUM_GET_FUL_CONFG_DESC;
1274 }
1275 else
1276 {
1277 g_enum_state = ENUM_ERROR;
1278 g_tdev_error_code = res;
1279 }
1280 }
1281 else
1282 {
1283 g_enum_state = ENUM_ERROR;
1284 }
1285 }
1286 break;
1287
1288 case ENUM_GET_FUL_CONFG_DESC:
1289 /* We already read the Standard Config desc of size 9. Now read
1290 * additional MSC class specific descriptor data. reading first
1291 * 18 bytes is sufficient for supporting MSC class */
1292 memset(command_buf, 0u, USB_SETUP_PKT_LEN*(sizeof(uint8_t)));
1293 MSS_USBH_construct_get_descr_command(command_buf,
1294 USB_STD_REQ_DATA_DIR_IN,
1295 USB_STANDARD_REQUEST,
1296 USB_STD_REQ_RECIPIENT_DEVICE,
1297 USB_STD_REQ_GET_DESCRIPTOR,
1298 USB_CONFIGURATION_DESCRIPTOR_TYPE,
1299 0u, /*stringID*/
1300 18u);
1301
1302 g_enum_state = ENUM_WAIT_GET_FUL_CONFG_DESC;
1303
1304 MSS_USBH_start_control_xfr(command_buf,
1305 (uint8_t*)&g_tdev_desc[tdev_idx].conf_desc,
1306 USB_STD_REQ_DATA_DIR_IN,
1307 18u);
1308
1309 break;
1310
1311 case ENUM_WAIT_GET_FUL_CONFG_DESC:
1312 if (g_cep_xfr_result)
1313 {
1314 if (MSS_USB_EP_XFR_SUCCESS == g_cep_xfr_result)
1315 {
1316 g_enum_state = ENUM_CHECK_TDEV_CLASS_SUPPORT;
1317 }
1318 else
1319 {
1320 g_enum_state = ENUM_ERROR;
1321 }
1322 }
1323 break;
1324
1325 case ENUM_CHECK_TDEV_CLASS_SUPPORT:
1326 cd_idx = host_enum_check_class_support(TDEV_R);
1327
1328 if (cd_idx < (int8_t)0u)
1329 {
1330 g_enum_state = ENUM_ERROR;
1331 g_tdev_error_code = cd_idx;
1332 }
1333 /* Max No of classDriver is 3 */
1334 else if (cd_idx < 3u)
1335 {
1336 g_rcd[cd_idx].alloc_state = 1u;
1337 g_tdev[TDEV_R].class_handle = g_rcd[cd_idx].class_handle;
1338 g_enum_state = ENUM_SUCCESS;
1339 }
1340 break;
1341
1342 case ENUM_PET_SET_CONFIG:
1343 memset(command_buf, 0u, USB_SETUP_PKT_LEN*(sizeof(uint8_t)));
1344 command_buf[1] = USB_STD_REQ_SET_CONFIG;
1345 command_buf[2] = 0x01u; /* ConfigNum for PET Device */
1346 g_enum_state = ENUM_PET_WAIT_SET_CONFIG;
1347
1348 MSS_USBH_start_control_xfr(command_buf,
1349 (uint8_t*)dummy,
1350 USB_STD_REQ_DATA_DIR_IN,
1351 0u);
1352 break;
1353
1354 case ENUM_PET_WAIT_SET_CONFIG:
1355 if (g_cep_xfr_result)
1356 {
1357 if (MSS_USB_EP_XFR_SUCCESS == g_cep_xfr_result)
1358 {
1359 g_enum_state = ENUM_CHECK_TDEV_CLASS_SUPPORT;
1360 }
1361 else
1362 {
1363 g_enum_state = ENUM_ERROR;
1364 }
1365 }
1366 break;
1367
1368 case ENUM_SUCCESS:
1369 break;
1370
1371 case ENUM_ERROR:
1372 default:
1373 ASSERT(0); /* Should never happen */
1374 break;
1375 }
1376 }
1377
1378 /*
1379 * This function is the FSM for the control transfer. Once the control transfer
1380 * is initiated, this function will monitor it's progress in all the stages and
1381 * record the status at the end.
1382 */
1383 static void
mss_usbh_control_xfr_fsm(void)1384 mss_usbh_control_xfr_fsm
1385 (
1386 void
1387 )
1388 {
1389 volatile mss_usb_ep_state_t cep_event_st = MSS_USB_EP_VALID;
1390 uint32_t rem_length = 0u;
1391
1392 mss_usb_ep_t* cep_ptr = &gh_tx_ep[MSS_USB_CEP];
1393
1394 MSS_USB_CIF_cep_disable_irq();
1395
1396 /* gh_cep_cb_event is critical */
1397 cep_event_st = (mss_usb_ep_state_t)gh_cep_cb_event;
1398 gh_cep_cb_event = 0u;
1399 MSS_USB_CIF_cep_enable_irq();
1400 MSS_USB_CIF_set_index_reg(MSS_USB_CEP);
1401
1402 switch (cep_ptr->state)
1403 {
1404 case MSS_USB_CEP_IDLE:
1405 /* do nothing. Free running CEP-FSM hits here when doing no transfers */
1406 break;
1407
1408 case MSS_USB_CEP_SETUP:
1409 if (cep_event_st)
1410 {
1411 if (MSS_USB_EP_TXN_SUCCESS == cep_event_st)
1412 {
1413 if (0u == cep_ptr->xfr_length)
1414 {
1415 /* zdl-request is sent. Get the status now */
1416 cep_ptr->state = MSS_USB_CEP_STATUS_AFTER_OUT;
1417 MSS_USBH_CIF_cep_set_statuspktrdy_after_out();
1418 }
1419 else
1420 {
1421 rem_length = cep_ptr->xfr_length - cep_ptr->xfr_count;
1422
1423 if (rem_length > cep_ptr->max_pkt_size)
1424 {
1425 cep_ptr->txn_length = cep_ptr->max_pkt_size;
1426 }
1427 else
1428 {
1429 cep_ptr->txn_length = rem_length;
1430 }
1431
1432 if (USB_STD_REQ_DATA_DIR_IN == cep_ptr->cep_data_dir)
1433 {
1434 cep_ptr->state = MSS_USB_CEP_RX;
1435 MSS_USBH_CIF_cep_set_request_in_pkt(); /* One Packet at a time */
1436 }
1437 else if (USB_STD_REQ_DATA_DIR_OUT == cep_ptr->cep_data_dir)
1438 {
1439 MSS_USBH_CIF_cep_write_pkt(cep_ptr);
1440 cep_ptr->state = MSS_USB_CEP_TX;
1441 MSS_USBH_CIF_cep_set_txpktrdy();
1442 }
1443 else
1444 {
1445 ASSERT(0); /* DataDir not valid */
1446 }
1447 }
1448 }
1449 else
1450 {
1451 cep_ptr->state = cep_event_st;
1452 }
1453 }
1454 break;
1455
1456 case MSS_USB_CEP_RX:
1457
1458 if (MSS_USB_EP_TXN_SUCCESS == cep_event_st)
1459 {
1460 MSS_USBH_CIF_cep_read_pkt(cep_ptr);
1461
1462 if (cep_ptr->xfr_count == cep_ptr->xfr_length)
1463 {
1464 cep_ptr->state = MSS_USB_CEP_STATUS_AFTER_IN;
1465 MSS_USBH_CIF_cep_set_statuspktrdy_after_in();
1466 }
1467 else
1468 {
1469 rem_length = cep_ptr->xfr_length - cep_ptr->xfr_count;
1470
1471 if (rem_length > cep_ptr->max_pkt_size)
1472 {
1473 cep_ptr->txn_length = cep_ptr->max_pkt_size;
1474 }
1475 else
1476 {
1477 cep_ptr->txn_length = rem_length;
1478 }
1479
1480 cep_ptr->state = MSS_USB_CEP_RX;
1481 MSS_USBH_CIF_cep_set_request_in_pkt(); /*One Packet at a time*/
1482 }
1483 }
1484 else
1485 {
1486 cep_ptr->state = cep_event_st;
1487 ASSERT(0);/* Flush fifo, if RxpktRdy is set.MUSB:21.2.2 */
1488 }
1489 break;
1490
1491 case MSS_USB_CEP_TX:
1492 if (MSS_USB_EP_TXN_SUCCESS == cep_event_st)
1493 {
1494 if (cep_ptr->xfr_count == cep_ptr->xfr_length)
1495 {
1496 cep_ptr->state = MSS_USB_CEP_STATUS_AFTER_OUT;
1497 MSS_USBH_CIF_cep_set_statuspktrdy_after_out();
1498 }
1499 else
1500 {
1501 rem_length = cep_ptr->xfr_length - cep_ptr->xfr_count;
1502
1503 if (rem_length > cep_ptr->max_pkt_size)
1504 {
1505 cep_ptr->txn_length = cep_ptr->max_pkt_size;
1506 }
1507 else
1508 {
1509 cep_ptr->txn_length = rem_length;
1510 }
1511
1512 MSS_USBH_CIF_cep_write_pkt(cep_ptr);
1513 }
1514 }
1515 else
1516 {
1517 cep_ptr->state = cep_event_st;
1518 ASSERT(0); /* Error response received in INTR */
1519 }
1520 /* TODO: Check if more data needs to Transmitted */
1521 /* Initiate IN status phase. */
1522 break;
1523
1524 case MSS_USB_CEP_STATUS_AFTER_IN:
1525 if (MSS_USB_EP_TXN_SUCCESS == cep_event_st)
1526 {
1527 uint8_t this_tdev = cep_ptr->tdev_idx;
1528 cep_ptr->state = MSS_USB_EP_XFR_SUCCESS;
1529
1530 if ((0u == g_tdev[(cep_ptr->tdev_idx)].class_handle) ||
1531 (1u == g_internal_cep_xfr))
1532 {
1533 g_cep_xfr_result = MSS_USB_EP_XFR_SUCCESS;
1534 g_internal_cep_xfr = 0u;
1535 }
1536 else
1537 {
1538 if (0 != g_tdev[this_tdev].class_handle->usbh_class_cep_xfr_done)
1539 {
1540 g_tdev[this_tdev].class_handle->
1541 usbh_class_cep_xfr_done(g_tdev[this_tdev].addr,
1542 cep_ptr->state,
1543 cep_ptr->xfr_count);
1544 }
1545 else
1546 {
1547 ASSERT(0);/* invalid pointer */
1548 }
1549 }
1550
1551 cep_ptr->state = MSS_USB_CEP_IDLE;
1552 }
1553 else
1554 {
1555 cep_ptr->state = cep_event_st;
1556 ASSERT(0);
1557 }
1558 break;
1559
1560 case MSS_USB_CEP_STATUS_AFTER_OUT:
1561 if (MSS_USB_EP_TXN_SUCCESS == cep_event_st)
1562 {
1563 uint8_t this_tdev = cep_ptr->tdev_idx;
1564 MSS_USBH_CIF_cep_clr_statusRxpktrdy();
1565 cep_ptr->state = MSS_USB_EP_XFR_SUCCESS;
1566
1567 if ((0 == g_tdev[(cep_ptr->tdev_idx)].class_handle) ||
1568 (1u == g_internal_cep_xfr))
1569 {
1570 g_cep_xfr_result = MSS_USB_EP_XFR_SUCCESS;
1571 }
1572 else
1573 {
1574 if (0 != g_tdev[this_tdev].class_handle->usbh_class_cep_xfr_done)
1575 {
1576 g_tdev[this_tdev].class_handle->
1577 usbh_class_cep_xfr_done(g_tdev[this_tdev].addr,
1578 cep_ptr->state,
1579 cep_ptr->xfr_count);
1580 }
1581 else
1582 {
1583 ASSERT(0); /* invalid pointer */
1584 }
1585 }
1586
1587 cep_ptr->state = MSS_USB_CEP_IDLE;
1588 }
1589 else
1590 {
1591 cep_ptr->state = cep_event_st;
1592 ASSERT(0);
1593 }
1594 break;
1595
1596 case MSS_USB_EP_NAK_TOUT:
1597 case MSS_USB_EP_NO_RESPONSE:
1598 case MSS_USB_EP_STALL_RCVD:
1599 {
1600 uint8_t this_tdev = cep_ptr->tdev_idx;
1601 if ((0 == g_tdev[(cep_ptr->tdev_idx)].class_handle) ||
1602 (1u == g_internal_cep_xfr))
1603 {
1604 g_cep_xfr_result = cep_ptr->state;
1605 g_internal_cep_xfr = 0u;
1606 }
1607 else
1608 {
1609 if (0 != g_tdev[this_tdev].class_handle->usbh_class_cep_xfr_done)
1610 {
1611 g_tdev[this_tdev].class_handle->
1612 usbh_class_cep_xfr_done(g_tdev[this_tdev].addr,
1613 cep_ptr->state,
1614 cep_ptr->xfr_count);
1615 }
1616 else
1617 {
1618 ASSERT(0); /* invalid pointer */
1619 }
1620
1621 cep_ptr->state = MSS_USB_CEP_IDLE;
1622 }
1623 }
1624 break;
1625
1626 default:
1627 {
1628 ASSERT(0); /* Invalid CEP state */
1629 break;
1630 }
1631 }
1632 }
1633
1634 /*
1635 * This function is used to start the enumeration FSM
1636 */
1637 static void
mss_usbh_start_enum_fsm(void)1638 mss_usbh_start_enum_fsm
1639 (
1640 void
1641 )
1642 {
1643 g_enum_state = ENUM_GET_DEF_DEV_DESC;
1644 }
1645
1646 /*
1647 * This function is used to bring the enum FSM to it's initial IDLE state.
1648 */
1649 static void
mss_usbh_reset_enum_fsm(void)1650 mss_usbh_reset_enum_fsm
1651 (
1652 void
1653 )
1654 {
1655 g_enum_state = ENUM_IDLE;
1656 }
1657
1658 /*
1659 * This function is used to find the current status of the enumeration FSM. The
1660 * state information is used to know if the enumeration was successful or not.
1661 */
1662 static mss_usb_enum_state_t
mss_usbh_get_enum_fsm_state(void)1663 mss_usbh_get_enum_fsm_state
1664 (
1665 void
1666 )
1667 {
1668 return (g_enum_state);
1669 }
1670
1671 /*
1672 * This Call-back function is executed on completion of current OUT transfer.
1673 */
1674 static void
mss_usbh_ep_tx_complete_cb(uint8_t ep_num,uint8_t status)1675 mss_usbh_ep_tx_complete_cb
1676 (
1677 uint8_t ep_num,
1678 uint8_t status
1679 )
1680 {
1681 uint8_t this_tdev = 0u;
1682 uint8_t transfer_complete = 0u;
1683
1684 mss_usb_ep_t* txep_ptr = &gh_tx_ep[ep_num];
1685
1686 /* retrieve tdev_idx which transmitted data. */
1687 this_tdev = gh_tx_ep[ep_num].tdev_idx;
1688
1689 if (MSS_USB_EP_ABORTED != txep_ptr->state)
1690 {
1691 txep_ptr->txn_count = txep_ptr->txn_length;
1692 txep_ptr->xfr_count += txep_ptr->txn_length;
1693
1694 if (0u == status)
1695 {
1696 if (DMA_ENABLE == txep_ptr->dma_enable)
1697 {
1698 txep_ptr->state = MSS_USB_EP_XFR_SUCCESS;
1699
1700 txep_ptr->xfr_count = MSS_USB_CIF_dma_read_addr(txep_ptr->dma_channel) -
1701 ((uint32_t)txep_ptr->buf_addr);
1702 ASSERT(txep_ptr->xfr_count == txep_ptr->xfr_length);
1703 transfer_complete = 1u;
1704 }
1705 else
1706 {
1707 if (MSS_USB_XFR_BULK == txep_ptr->xfr_type)
1708 {
1709 if (txep_ptr->xfr_count < txep_ptr->xfr_length)
1710 {
1711 transfer_complete = 0u;
1712 }
1713 else if (txep_ptr->xfr_count == txep_ptr->xfr_length)
1714 {
1715 if (ADD_ZLP_TO_XFR == txep_ptr->add_zlp)
1716 {
1717 if (0u == txep_ptr->txn_count)
1718 {
1719 transfer_complete = 1u;
1720 }
1721 else
1722 {
1723 if (txep_ptr->txn_count == txep_ptr->max_pkt_size)
1724 {
1725 transfer_complete = 0u;
1726 }
1727 else if (txep_ptr->txn_count < txep_ptr->max_pkt_size)
1728 {
1729 transfer_complete = 1u;
1730 }
1731 }
1732 }
1733 else /* no zlp */
1734 {
1735 transfer_complete = 1u;
1736 }
1737 }
1738 else
1739 {
1740 /* If xfr_count is more than xfr_lenght then something
1741 * has seriously gone bad.*/
1742 ASSERT(0);
1743 }
1744 }
1745 }
1746 }
1747 else
1748 {
1749 txep_ptr->state = (mss_usb_ep_state_t)status;
1750 transfer_complete = 1u;
1751 }
1752 if (1u == transfer_complete)
1753 {
1754 if (0 != g_tdev[this_tdev].class_handle->usbh_class_tx_done)
1755 {
1756 /* call-back class driver */
1757 if (0u == txep_ptr->xfr_count)
1758 {
1759 ASSERT(0);
1760 }
1761 else
1762 {
1763 g_tdev[this_tdev].class_handle->usbh_class_tx_done(g_tdev[this_tdev].addr,
1764 status,
1765 txep_ptr->xfr_count);
1766
1767 }
1768 }
1769 else
1770 {
1771 ASSERT(0); /* Invalid function pointer */
1772 }
1773 }
1774 else
1775 {
1776 txep_ptr->txn_count = 0u;/* reset txn_count for next txn */
1777 ASSERT(txep_ptr->xfr_length >= txep_ptr->xfr_count);
1778
1779 if ((txep_ptr->xfr_length - txep_ptr->xfr_count) >= txep_ptr->max_pkt_size)
1780 {
1781 txep_ptr->txn_length = txep_ptr->max_pkt_size;
1782 }
1783 else
1784 {
1785 txep_ptr->txn_length = (txep_ptr->xfr_length - txep_ptr->xfr_count);
1786 }
1787
1788 while (MSS_USB_CIF_is_txepfifo_notempty(txep_ptr->num))
1789 {
1790 ;
1791 }
1792
1793 if ((txep_ptr->max_pkt_size <= txep_ptr->fifo_size) &&
1794 (txep_ptr->txn_length <= txep_ptr->fifo_size))
1795 {
1796 txep_ptr->state = MSS_USB_EP_VALID;
1797 MSS_USB_CIF_ep_write_pkt(txep_ptr->num,
1798 (txep_ptr->buf_addr +
1799 txep_ptr->xfr_count),
1800 txep_ptr->dma_enable,
1801 txep_ptr->dma_channel,
1802 txep_ptr->xfr_type,
1803 txep_ptr->xfr_length,
1804 txep_ptr->txn_length);
1805 }
1806 else
1807 {
1808 ASSERT(0);
1809 }
1810 }
1811 }
1812 else
1813 {
1814 /* The Transmit endpoint generates an endpoint interrupt when previously
1815 * initiated TX transfer is aborted.Class driver doesn't need to know this.
1816 * Also this driver doesn't need to do anything in this case.*/
1817 }
1818 }
1819
1820 /*
1821 * This Call-back function is executed on completion of current IN transfer.
1822 */
1823 static void
mss_usbh_ep_rx_cb(uint8_t ep_num,uint8_t status)1824 mss_usbh_ep_rx_cb
1825 (
1826 uint8_t ep_num,
1827 uint8_t status
1828 )
1829 {
1830 uint8_t this_tdev = 0u;
1831 uint8_t transfer_complete = 0u;
1832 uint32_t received_count = 0u;
1833
1834 mss_usb_ep_t* rxep_ptr = &gh_rx_ep[ep_num];
1835
1836 /* Retrieve tdev_idx which received data. */
1837 this_tdev = gh_rx_ep[ep_num].tdev_idx;
1838
1839 if (status & (RX_EP_OVER_RUN_ERROR | RX_EP_STALL_ERROR |
1840 RX_EP_DATA_ERROR | RX_EP_PID_ERROR | RX_EP_ISO_INCOMP_ERROR))
1841 {
1842 transfer_complete = 1u;
1843 }
1844 else
1845 {
1846 if (MSS_USB_CIF_rx_ep_is_rxpktrdy((mss_usb_ep_num_t)ep_num))
1847 {
1848 received_count = (uint32_t)MSS_USB_CIF_rx_ep_read_count((mss_usb_ep_num_t)ep_num);
1849 if (DMA_ENABLE == rxep_ptr->dma_enable)
1850 {
1851 if (MSS_USB_DMA_MODE1 == (MSS_USB_CIF_rx_ep_get_dma_mode((mss_usb_ep_num_t)ep_num)))
1852 {
1853 uint32_t increamented_addr;
1854
1855 /*
1856 * This means we are in BULK transfer with DMA mode1.
1857 * all the rxmaxP size pkts are received and last short pkt
1858 * need to be read without DMA or by switching to mode 0.
1859 * After switching mode to 0, this ISR handler is invoked
1860 * again. Data packet will be read then.
1861 */
1862
1863 /* Read 'short packet' without DMA */
1864 MSS_USB_CIF_dma_stop_xfr(rxep_ptr->dma_channel);
1865 MSS_USB_CIF_rx_ep_clr_autoclr((mss_usb_ep_num_t)ep_num);
1866
1867 increamented_addr = MSS_USB_CIF_dma_read_addr(rxep_ptr->dma_channel);
1868
1869 /* Count number of bytes read so far,since DMA was operating
1870 * in m1 with Autoclr.*/
1871 rxep_ptr->xfr_count = (increamented_addr - ((uint32_t)(rxep_ptr->buf_addr)));
1872
1873 if (received_count)
1874 {
1875 MSS_USB_CIF_read_rx_fifo((mss_usb_ep_num_t)ep_num,
1876 (rxep_ptr->buf_addr+rxep_ptr->xfr_count),
1877 received_count);
1878
1879 rxep_ptr->xfr_count += received_count;
1880 MSS_USB_CIF_rx_ep_clr_rxpktrdy((mss_usb_ep_num_t)ep_num);
1881 }
1882 transfer_complete = 1u;
1883 }
1884 else
1885 {
1886 MSS_USB_CIF_dma_write_count(rxep_ptr->dma_channel, received_count);
1887 MSS_USB_CIF_dma_start_xfr(rxep_ptr->dma_channel);
1888 transfer_complete = 2u;
1889 /*Upper layer cb will be called from DMA ISR*/
1890 }
1891 }
1892 else /* dma disable */
1893 {
1894 if (received_count)
1895 {
1896 MSS_USB_CIF_read_rx_fifo((mss_usb_ep_num_t)ep_num,
1897 (rxep_ptr->buf_addr+rxep_ptr->xfr_count),
1898 received_count);
1899 rxep_ptr->txn_count = received_count;
1900 rxep_ptr->xfr_count += received_count;
1901 MSS_USB_CIF_rx_ep_clr_rxpktrdy((mss_usb_ep_num_t)ep_num);
1902 }
1903
1904 if (rxep_ptr->xfr_count == rxep_ptr->xfr_length)
1905 {
1906 transfer_complete = 1u;
1907 }
1908 else if (rxep_ptr->xfr_count < rxep_ptr->xfr_length)
1909 {
1910 /* Reset txn_count for next txn */
1911 rxep_ptr->txn_count = 0u;
1912
1913 if ((rxep_ptr->xfr_length - rxep_ptr->xfr_count) > rxep_ptr->max_pkt_size)
1914 {
1915 rxep_ptr->txn_length = rxep_ptr->max_pkt_size;
1916 }
1917 else
1918 {
1919 rxep_ptr->txn_length = (rxep_ptr->xfr_length - rxep_ptr->xfr_count);
1920 }
1921
1922 MSS_USBH_CIF_rx_ep_set_reqpkt((mss_usb_ep_num_t)ep_num);
1923 }
1924 else
1925 {
1926 ASSERT(0);
1927 }
1928 }
1929 }
1930 }
1931
1932 if (1u == transfer_complete)
1933 {
1934 rxep_ptr->state = (mss_usb_ep_state_t)status;
1935 if (0 != g_tdev[this_tdev].class_handle->usbh_class_rx_done)
1936 {
1937 /* call-back class driver */ /* count = 0 since there was error */
1938 g_tdev[this_tdev].class_handle->usbh_class_rx_done(g_tdev[this_tdev].addr,
1939 status,
1940 rxep_ptr->xfr_count);
1941 }
1942 else
1943 {
1944 ASSERT(0); /* Invalid pointer */
1945 }
1946
1947 }
1948 }
1949
1950 /*
1951 * This Call-back function is executed on completion of current CONTROL transfer.
1952 */
1953 static void
mss_usbh_cep_cb(uint8_t status)1954 mss_usbh_cep_cb
1955 (
1956 uint8_t status
1957 )
1958 {
1959 gh_cep_cb_event = status;
1960 }
1961
1962 /*
1963 * This Call-back function is executed on receiving SOF interrupt in HOST mode
1964 */
1965 static void
mss_usbh_sof_cb(uint32_t frame_number)1966 mss_usbh_sof_cb
1967 (
1968 uint32_t frame_number
1969 )
1970 {
1971 }
1972
1973 /*
1974 * This Call-back function is executed on detecting the device attach event
1975 */
1976 static void
mss_usbh_connect_cb(mss_usb_device_speed_t target_speed,mss_usb_vbus_level_t vbus_level)1977 mss_usbh_connect_cb
1978 (
1979 mss_usb_device_speed_t target_speed,
1980 mss_usb_vbus_level_t vbus_level
1981 )
1982 {
1983 g_tdev[TDEV_R].speed = target_speed;
1984 gh_tdev_connect_event = 1u;
1985 }
1986
1987 /*
1988 * This Call-back function is executed on detecting the device detach event
1989 */
1990 static void
mss_usbh_disconnect_cb(void)1991 mss_usbh_disconnect_cb
1992 (
1993 void
1994 )
1995 {
1996 gh_tdev_discon_event = 1u;
1997 }
1998
1999 /*
2000 * This Call-back function is executed on detecting a Vbus level error event
2001 */
2002 static void
mss_usbh_vbus_err_cb(mss_usb_vbus_level_t vbus_level)2003 mss_usbh_vbus_err_cb
2004 (
2005 mss_usb_vbus_level_t vbus_level
2006 )
2007 {
2008
2009 }
2010
2011 /*
2012 * This Call-back function is executed on detecting the babble error event
2013 */
2014 static void
mss_usbh_babble_err_cb(void)2015 mss_usbh_babble_err_cb
2016 (
2017 void
2018 )
2019 {
2020 /* Not supported yet */
2021 }
2022
2023 /*
2024 * This Call-back function is executed on detecting the session request event
2025 * when the attached device is also a OTG device.
2026 */
2027 static void
mss_usbh_session_request_cb(void)2028 mss_usbh_session_request_cb
2029 (
2030 void
2031 )
2032 {
2033 /* Not supported yet */
2034 }
2035
mss_usbh_dma_handler_cb(mss_usb_ep_num_t ep_num,mss_usb_dma_dir_t dma_dir,uint8_t status,uint32_t dma_addr_val)2036 static void mss_usbh_dma_handler_cb
2037 (
2038 mss_usb_ep_num_t ep_num,
2039 mss_usb_dma_dir_t dma_dir,
2040 uint8_t status,
2041 uint32_t dma_addr_val
2042 )
2043 {
2044 mss_usb_ep_t* ep_ptr = 0;
2045 uint8_t this_tdev = 0u;
2046
2047 if (DMA_XFR_ERROR == status)
2048 {
2049 ASSERT(0);
2050 }
2051 else
2052 {
2053 if (MSS_USB_DMA_READ == dma_dir) /*TX EP*/
2054 {
2055 ep_ptr = &gh_tx_ep[ep_num];
2056
2057 /* Retrieve tdev_idx which received data.*/
2058 this_tdev = gh_tx_ep[ep_num].tdev_idx;
2059
2060 /* EP interrupt won't happen when short packet is not received */
2061 if ((NO_ZLP_TO_XFR == ep_ptr->add_zlp) &&
2062 (ep_ptr->xfr_length) &&
2063 (!(ep_ptr->xfr_length % ep_ptr->max_pkt_size)))
2064 {
2065 /* Wait till last TxMaxPkt size packet is sent.*/
2066 while (MSS_USB_CIF_tx_ep_is_txpktrdy(ep_num))
2067 {
2068 ;
2069 }
2070 ep_ptr->xfr_count = dma_addr_val - (uint32_t)ep_ptr->buf_addr;
2071 ep_ptr->state = MSS_USB_EP_XFR_SUCCESS;
2072 if (0 != g_tdev[this_tdev].class_handle->usbh_class_tx_done)
2073 {
2074 /* Call-back class driver */
2075 g_tdev[this_tdev].class_handle->usbh_class_tx_done(g_tdev[this_tdev].addr,
2076 status,
2077 ep_ptr->xfr_count);
2078 }
2079 }
2080 else
2081 {
2082 MSS_USB_CIF_tx_ep_set_txpktrdy(ep_num);
2083 }
2084 }
2085 /* RX EP */
2086 else if (MSS_USB_DMA_WRITE == dma_dir)
2087 {
2088 ep_ptr = &gh_rx_ep[ep_num];
2089
2090 /* Retrieve tdev_idx which transmitted data.*/
2091 this_tdev = gh_rx_ep[ep_num].tdev_idx;
2092
2093 if ((NO_ZLP_TO_XFR == ep_ptr->add_zlp) &&
2094 (ep_ptr->xfr_length) &&
2095 (!(ep_ptr->xfr_length % ep_ptr->max_pkt_size)))
2096 {
2097 MSS_USB_CIF_dma_stop_xfr(ep_ptr->dma_channel);
2098 MSS_USBH_CIF_rx_ep_clr_reqpkt((mss_usb_ep_num_t)ep_num);
2099 MSS_USB_CIF_rx_ep_clr_autoclr((mss_usb_ep_num_t)ep_num);
2100
2101 ep_ptr->xfr_count = dma_addr_val - (uint32_t)ep_ptr->buf_addr;
2102 ep_ptr->state = MSS_USB_EP_XFR_SUCCESS;
2103 if (MSS_USB_DMA_MODE0 == (MSS_USB_CIF_rx_ep_get_dma_mode(ep_num)))
2104 {
2105 MSS_USB_CIF_rx_ep_clr_rxpktrdy(ep_num);
2106 }
2107 if (0 != g_tdev[this_tdev].class_handle->usbh_class_rx_done)
2108 {
2109 /* Call-back class driver */
2110 g_tdev[this_tdev].class_handle->
2111 usbh_class_rx_done(g_tdev[this_tdev].addr,
2112 status,
2113 ep_ptr->xfr_count);
2114 }
2115 }
2116 }
2117 }
2118 }
2119
2120 /*
2121 * This function checks errors in the received device descriptor.
2122 */
2123 static int8_t
validate_dev_desc(dev_desc_t * p_desc)2124 validate_dev_desc
2125 (
2126 dev_desc_t* p_desc
2127 )
2128 {
2129 int8_t result = 0;
2130
2131 if (p_desc->bLength != USB_STD_DEVICE_DESCR_LEN)
2132 {
2133 result = DEV_DESC_WRONG_LENGTH;
2134 }
2135 if (p_desc->bDescriptorType != USB_DEVICE_DESCRIPTOR_TYPE)
2136 {
2137 result = DEV_DESC_WRONG_DESC_TYPE;
2138 }
2139
2140 if (!((p_desc->bcdUSB != USB_BCD_VERSION_2_0) ||
2141 (p_desc->bcdUSB != USB_BCD_VERSION_2_1) ||
2142 (p_desc->bcdUSB != USB_BCD_VERSION_1_1) ||
2143 (p_desc->bcdUSB != USB_BCD_VERSION_1_0)))
2144 {
2145 result = DEV_DESC_WRONG_USBBCD;
2146 }
2147
2148 if (!((p_desc->bMaxPacketSize0 != 8u) ||
2149 (p_desc->bMaxPacketSize0 != 16u) ||
2150 (p_desc->bMaxPacketSize0 != 32u) ||
2151 (p_desc->bMaxPacketSize0 != 64u)))
2152
2153 {
2154 result = DEV_DESC_WRONG_MAXPKTSZ0;
2155 }
2156
2157 if ((MSS_USB_DEVICE_HS == g_tdev[TDEV_R].speed))
2158 {
2159 if ((p_desc->bcdUSB != USB_BCD_VERSION_2_0) &&
2160 (p_desc->bcdUSB != USB_BCD_VERSION_2_1))
2161 {
2162 result = DEV_DESC_HS_USBBCD_NOT200;
2163 }
2164 if (p_desc->bMaxPacketSize0 != 64u)
2165 {
2166 result = DEV_DESC_HS_MAXPKTSZ0_NOT64;
2167 }
2168 }
2169
2170 if ((MSS_USB_DEVICE_LS == g_tdev[TDEV_R].speed))
2171 {
2172 if (p_desc->bMaxPacketSize0 != 8u)
2173 {
2174 result = DEV_DESC_LS_MAXPKTSZ0_NOT8;
2175 }
2176 }
2177
2178 if ((MSS_USB_DEVICE_FS == g_tdev[TDEV_R].speed))
2179 {
2180 result = FS_DEV_NOT_SUPPORTED;
2181 }
2182
2183 /* Need to comment the below section for keyboard and mouse are low speed
2184 * device
2185 */
2186 #if 0
2187 if ((MSS_USB_DEVICE_LS == g_tdev[TDEV_R].speed))
2188 {
2189 result = LS_DEV_NOT_SUPPORTED;
2190 }
2191 #endif
2192
2193 /*0 return value indicates success*/
2194 return (result);
2195 }
2196
2197 /*
2198 * This function checks errors in the received configuration descriptor (9bytes)
2199 */
2200 static int8_t
validate_def_conf_desc(def_conf_desc_t * p_desc)2201 validate_def_conf_desc
2202 (
2203 def_conf_desc_t* p_desc
2204 )
2205 {
2206 int8_t result = 0u;
2207 if (p_desc->bLength != USB_STD_CONFIG_DESCR_LEN)
2208 {
2209 result = CONF_DESC_WRONG_LENGTH;
2210 }
2211 if (p_desc->bDescriptorType != USB_CONFIGURATION_DESCRIPTOR_TYPE)
2212 {
2213 result = CONF_DESC_WRONG_DESC_TYPE;
2214 }
2215 if (p_desc->bMaxPower > USB_MAX_BUS_POWER)
2216 {
2217 result = CONF_DESC_POWER_LIM_EXCEED;
2218 }
2219
2220 /*0 return value indicates success*/
2221 return (result);
2222 }
2223
2224 /*
2225 * This function executes the sequence of actions when device is disconnected.
2226 */
2227 static void
mss_usbh_handle_discon_event(void)2228 mss_usbh_handle_discon_event
2229 (
2230 void
2231 )
2232 {
2233 gh_tdev_discon_event = 0u;
2234 tdev_idx = TDEV_R;
2235
2236 if (0 != g_user_cb->usbh_tdev_dettached)
2237 {
2238 g_user_cb->usbh_tdev_dettached();
2239 }
2240
2241 if (1u == g_rcd[TDEV_R].alloc_state)
2242 {
2243 g_rcd[TDEV_R].class_handle->usbh_class_release(g_tdev[TDEV_R].addr);
2244 }
2245
2246 g_tdev[TDEV_R].addr = USB_DEFAULT_TARGET_ADDR;
2247 g_tdev[TDEV_R].speed = MSS_USB_DEVICE_HS;
2248 g_tdev[TDEV_R].state = MSS_USB_NOT_ATTACHED_STATE;
2249 g_tdev[TDEV_R].hub_addr = 0u;
2250 g_tdev[TDEV_R].hub_port = 0u;
2251 g_tdev[TDEV_R].hub_mtt = 0u;
2252 g_tdev[TDEV_R].tdev_maxpktsz0 = CEP_MAX_PKT_SIZE;
2253 g_tdev[TDEV_R].class_handle = 0u;
2254 g_tdev_error_code = 0;
2255
2256 memset(&g_tdev_desc[TDEV_R], 0u, sizeof(tdev_desc_t));
2257
2258 /* Un-register Class driver */
2259 g_rcd[TDEV_R].alloc_state = 0u;
2260
2261 mss_usbh_reset_enum_fsm();
2262
2263 MSS_USB_CIF_enable_usbirq(CONNECT_IRQ_MASK |
2264 DISCONNECT_IRQ_MASK);
2265
2266 MSS_USBH_configure_control_pipe(USB_DEFAULT_TARGET_ADDR);
2267
2268 MSS_USBH_CIF_tx_ep_set_target_func_addr(MSS_USB_CEP,0u);
2269 MSS_USBH_CIF_cep_set_type0_reg((mss_usb_device_speed_t)0u);
2270 }
2271
2272 static int8_t
host_enum_check_class_support(tdev_id_t tid)2273 host_enum_check_class_support
2274 (
2275 tdev_id_t tid
2276 )
2277 {
2278 uint8_t i = 0u;
2279
2280 /* Max number of registered Class drivers supported is 1 */
2281 for (i = 0u;i < 1u;i++)
2282 {
2283 /* Value 9 in interface descriptor's bInterfaceClass field indicates
2284 * HUB Class device
2285 */
2286 if (0x09u == g_tdev_desc[tid].conf_desc.cs.upended_desc[5])
2287 {
2288 return (HUB_CLASS_NOT_SUPPORTED);
2289 }
2290
2291 /* Comparing assigned class driver with the interface descriptor's
2292 * bInterfaceClass, bInterfaceSubClass and bInterfaceProtocol
2293 * fields*/
2294 if (((uint8_t)(g_rcd[i].class_handle->class_id>>16u) ==
2295 g_tdev_desc[tid].conf_desc.cs.upended_desc[5]) &&
2296 ((uint8_t)(g_rcd[i].class_handle->class_id>>8u) ==
2297 g_tdev_desc[tid].conf_desc.cs.upended_desc[6]) &&
2298 ((uint8_t)(g_rcd[i].class_handle->class_id) ==
2299 g_tdev_desc[tid].conf_desc.cs.upended_desc[7]))
2300 {
2301 /* Class driver is matched and available. */
2302 if (g_rcd[i].alloc_state == 0u)
2303 {
2304 /* Allocation successful */
2305 return (i);
2306 }
2307 else
2308 {
2309 /* Match found but Driver is already assigned */
2310 return (CLASS_DRIVER_NOT_FREE);
2311 }
2312 }
2313 }
2314
2315 /* No matching class driver found. */
2316 return (CLASS_DRIVER_NOT_MATCHED);
2317 }
2318
2319 #endif /* MSS_USB_HOST_ENABLED */
2320
2321 #ifdef __cplusplus
2322 }
2323 #endif
2324