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