1 /**
2   **************************************************************************
3   * @file     usbh_core.c
4   * @brief    usb host driver
5   **************************************************************************
6   *                       Copyright notice & Disclaimer
7   *
8   * The software Board Support Package (BSP) that is made available to
9   * download from Artery official website is the copyrighted work of Artery.
10   * Artery authorizes customers to use, copy, and distribute the BSP
11   * software and its related documentation for the purpose of design and
12   * development in conjunction with Artery microcontrollers. Use of the
13   * software is governed by this copyright notice and the following disclaimer.
14   *
15   * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
16   * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
17   * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
18   * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
19   * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
20   * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
21   *
22   **************************************************************************
23   */
24 
25 #include "usbh_core.h"
26 #include "usb_core.h"
27 #include "usbh_ctrl.h"
28 
29 #ifdef USE_OTG_HOST_MODE
30 
31 /** @defgroup USBH_drivers_core
32   * @brief usb host drivers core
33   * @{
34   */
35 
36 /** @defgroup USBH_core_private_functions
37   * @{
38   */
39 
40 static void usbh_attached(usbh_core_type *uhost);
41 static void usbh_enumeration(usbh_core_type *uhost);
42 static void usbh_class_request(usbh_core_type *uhost);
43 static void usbh_class(usbh_core_type *uhost);
44 static void usbh_suspend(usbh_core_type *uhost);
45 static void usbh_wakeup(usbh_core_type *uhost);
46 static void usbh_disconnect(usbh_core_type *uhost);
47 /**
48   * @brief  usb host free channel
49   * @param  uhost: to the structure of usbh_core_type
50   * @param  index: channle number
51   * @retval none
52   */
usbh_free_channel(usbh_core_type * uhost,uint8_t index)53 void usbh_free_channel(usbh_core_type *uhost, uint8_t index)
54 {
55   if(index < USB_HOST_CHANNEL_NUM)
56   {
57     /* free host channel */
58     uhost->channel[index] = 0x0;
59   }
60 }
61 
62 /**
63   * @brief  get usb host free channel
64   * @param  uhost: to the structure of usbh_core_type
65   * @retval channel index
66   */
usbh_get_free_channel(usbh_core_type * uhost)67 uint16_t usbh_get_free_channel(usbh_core_type *uhost)
68 {
69   uint16_t i_index = 0;
70   for(i_index = 0; i_index < USB_HOST_CHANNEL_NUM; i_index ++)
71   {
72     /* find unuse channel */
73     if((uhost->channel[i_index] & HCH_USED) == 0)
74     {
75       /* return channel index */
76       return i_index;
77     }
78   }
79   return HCH_ERROR;
80 }
81 
82 
83 /**
84   * @brief  usb host set toggle
85   * @param  uhost: to the structure of usbh_core_type
86   * @param  hc_num: channel number
87   * @param  toggle: toggle value
88   * @retval status: usb_sts_type status
89   */
usbh_set_toggle(usbh_core_type * uhost,uint8_t hc_num,uint8_t toggle)90 usb_sts_type usbh_set_toggle(usbh_core_type *uhost, uint8_t hc_num, uint8_t toggle)
91 {
92   if(uhost->hch[hc_num].dir)
93   {
94     /* direction in */
95     uhost->hch[hc_num].toggle_in = toggle;
96   }
97   else
98   {
99     /* direction out */
100     uhost->hch[hc_num].toggle_out = toggle;
101   }
102   return USB_OK;
103 }
104 
105 /**
106   * @brief  usb host in out request
107   * @param  uhost: to the structure of usbh_core_type
108   * @param  hc_num: channel number
109   * @retval status: usb_sts_type status
110   */
usbh_in_out_request(usbh_core_type * uhost,uint8_t hc_num)111 usb_sts_type usbh_in_out_request(usbh_core_type *uhost, uint8_t hc_num)
112 {
113   usb_sts_type status = USB_OK;
114   uint32_t n_packet = 0;
115   uint32_t num_words = 0;
116   uint32_t tmp;
117   otg_global_type *usbx = uhost->usb_reg;
118   otg_hchannel_type *ch = USB_CHL(uhost->usb_reg, hc_num);
119 
120   /* set usb request block to idle */
121   uhost->urb_state[hc_num] = URB_IDLE;
122   uhost->hch[hc_num].state = HCH_IDLE;
123 
124   /* set usb channel transmit count to zero */
125   uhost->hch[hc_num].trans_count = 0;
126 #ifdef BSP_USB_SPEED_HS
127   if(uhost->speed == USB_HIGH_SPEED)
128   {
129     if((uhost->dma_en) && ((uhost->hch[hc_num].ept_type == EPT_CONTROL_TYPE) ||
130     (uhost->hch[hc_num].ept_type == EPT_BULK_TYPE)))
131     {
132       ch->hcintmsk_bit.ackmsk = FALSE;
133       ch->hcintmsk_bit.nakmsk = FALSE;
134       ch->hcintmsk_bit.nyetmsk = FALSE;
135     }
136     if((uhost->dma_en == FALSE) && (uhost->hch[hc_num].do_ping == TRUE))
137     {
138       usb_do_ping(usbx, hc_num);
139       return USB_OK;
140     }
141   }
142 #endif
143   /* check transmit data len */
144   if(uhost->hch[hc_num].trans_len > 0)
145   {
146     /* count how many packet need to send */
147     n_packet = (uhost->hch[hc_num].trans_len + \
148                uhost->hch[hc_num].maxpacket - 1) / \
149                uhost->hch[hc_num].maxpacket;
150 
151     /* packet count max 256 */
152     if(n_packet > 256)
153     {
154       n_packet = 256;
155       uhost->hch[hc_num].trans_len = n_packet * uhost->hch[hc_num].maxpacket;
156     }
157   }
158   else
159   {
160     /* zero data len */
161     n_packet = 1;
162   }
163 
164   /* direction is in */
165   if(uhost->hch[hc_num].dir)
166   {
167     uhost->hch[hc_num].trans_len = n_packet * uhost->hch[hc_num].maxpacket;
168   }
169 
170   /* set transfer information to channel register */
171   ch->hctsiz = (uhost->hch[hc_num].trans_len & USB_OTG_HCTSIZ_XFERSIZE) |
172                ((n_packet << 19) & USB_OTG_HCTSIZ_PKTCNT) |
173                ((uhost->hch[hc_num].data_pid << 29) & USB_OTG_HCTSIZ_PID);
174 #ifdef BSP_USB_SPEED_HS
175   if(uhost->dma_en == TRUE)
176   {
177     ch->hcdma = (uint32_t)uhost->hch[hc_num].trans_buf;
178   }
179 #endif
180   /* set odd frame */
181   ch->hcchar_bit.oddfrm = !(OTG_HOST(uhost->usb_reg)->hfnum & 0x1);
182 
183   /* clear channel disable bit and enable channel */
184   tmp = ch->hcchar;
185   tmp &= ~(USB_OTG_HCCHAR_CHDIS);
186   tmp |= USB_OTG_HCCHAR_CHENA;
187   ch->hcchar = tmp;
188 #ifdef BSP_USB_SPEED_HS
189   if( uhost->dma_en == TRUE)
190   {
191     return status;
192   }
193 #endif
194   /* channel direction is out and transfer len > 0 */
195   if((uhost->hch[hc_num].dir == 0) &&
196     (uhost->hch[hc_num].trans_len > 0 ))
197   {
198     switch(uhost->hch[hc_num].ept_type)
199     {
200       case EPT_CONTROL_TYPE:
201       case EPT_BULK_TYPE:
202         num_words = (uhost->hch[hc_num].trans_len + 3) / 4;
203 
204         /* non-periodic transfer */
205         if(num_words > usbx->gnptxsts_bit.nptxfspcavail)
206         {
207           usbx->gintmsk_bit.nptxfempmsk = 1;
208         }
209         break;
210       case EPT_ISO_TYPE:
211       case EPT_INT_TYPE:
212         num_words = (uhost->hch[hc_num].trans_len + 3) / 4;
213 
214         /* periodic transfer */
215         if(num_words > OTG_HOST(usbx)->hptxsts_bit.ptxfspcavil)
216         {
217           usbx->gintmsk_bit.ptxfempmsk = 1;
218         }
219         break;
220       default:
221         break;
222     }
223     /* write data to fifo */
224     usb_write_packet(usbx, uhost->hch[hc_num].trans_buf,
225                     hc_num, uhost->hch[hc_num].trans_len);
226   }
227 
228   return status;
229 }
230 
231 /**
232   * @brief  usb host interrupt receive request
233   * @param  uhost: to the structure of usbh_core_type
234   * @param  hc_num: channel number
235   * @param  buffer: receive buffer
236   * @param  length: receive length
237   * @retval status: usb_sts_type status
238   */
usbh_interrupt_recv(usbh_core_type * uhost,uint8_t hc_num,uint8_t * buffer,uint16_t length)239 usb_sts_type usbh_interrupt_recv(usbh_core_type *uhost, uint8_t hc_num,
240                             uint8_t *buffer, uint16_t length)
241 {
242   /* set direction is in */
243   uhost->hch[hc_num].dir = 1;
244 
245   /* set transfer buffer */
246   uhost->hch[hc_num].trans_buf = buffer;
247 
248   /* set transfer len*/
249   uhost->hch[hc_num].trans_len = length;
250 
251   if(uhost->hch[hc_num].toggle_in == 0)
252   {
253     /* pid: data0 */
254     uhost->hch[hc_num].data_pid = HCH_PID_DATA0;
255   }
256   else
257   {
258     /* pid: data1 */
259     uhost->hch[hc_num].data_pid = HCH_PID_DATA1;
260   }
261 
262   return usbh_in_out_request(uhost, hc_num);
263 }
264 
265 /**
266   * @brief  usb host interrupt send request
267   * @param  uhost: to the structure of usbh_core_type
268   * @param  hc_num: channel number
269   * @param  buffer: send buffer
270   * @param  length: send length
271   * @retval status: usb_sts_type status
272   */
usbh_interrupt_send(usbh_core_type * uhost,uint8_t hc_num,uint8_t * buffer,uint16_t length)273 usb_sts_type usbh_interrupt_send(usbh_core_type *uhost, uint8_t hc_num,
274                             uint8_t *buffer, uint16_t length)
275 {
276   /* set direction is out */
277   uhost->hch[hc_num].dir = 0;
278 
279   /* set transfer buffer */
280   uhost->hch[hc_num].trans_buf = buffer;
281 
282   /* set transfer len*/
283   uhost->hch[hc_num].trans_len = length;
284 
285   if(uhost->hch[hc_num].toggle_out == 0)
286   {
287     /* pid: data0 */
288     uhost->hch[hc_num].data_pid = HCH_PID_DATA0;
289   }
290   else
291   {
292     /* pid: data1 */
293     uhost->hch[hc_num].data_pid = HCH_PID_DATA1;
294   }
295 
296   return usbh_in_out_request(uhost, hc_num);
297 }
298 
299 
300 /**
301   * @brief  usb host bulk receive request
302   * @param  uhost: to the structure of usbh_core_type
303   * @param  hc_num: channel number
304   * @param  buffer: receive buffer
305   * @param  length: receive length
306   * @retval status: usb_sts_type status
307   */
usbh_bulk_recv(usbh_core_type * uhost,uint8_t hc_num,uint8_t * buffer,uint16_t length)308 usb_sts_type usbh_bulk_recv(usbh_core_type *uhost, uint8_t hc_num,
309                             uint8_t *buffer, uint16_t length)
310 {
311   /* set direction is in */
312   uhost->hch[hc_num].dir = 1;
313 
314   /* set transfer buffer */
315   uhost->hch[hc_num].trans_buf = buffer;
316 
317   /* set transfer len*/
318   uhost->hch[hc_num].trans_len = length;
319 
320   if(uhost->hch[hc_num].toggle_in == 0)
321   {
322     /* pid: data0 */
323     uhost->hch[hc_num].data_pid = HCH_PID_DATA0;
324   }
325   else
326   {
327     /* pid: data1 */
328     uhost->hch[hc_num].data_pid = HCH_PID_DATA1;
329   }
330 
331   return usbh_in_out_request(uhost, hc_num);
332 }
333 
334 
335 /**
336   * @brief  usb host bulk send request
337   * @param  uhost: to the structure of usbh_core_type
338   * @param  hc_num: channel number
339   * @param  buffer: receive buffer
340   * @param  length: receive length
341   * @retval status: usb_sts_type status
342   */
usbh_bulk_send(usbh_core_type * uhost,uint8_t hc_num,uint8_t * buffer,uint16_t length)343 usb_sts_type usbh_bulk_send(usbh_core_type *uhost, uint8_t hc_num,
344                             uint8_t *buffer, uint16_t length)
345 {
346   /* set direction is out */
347   uhost->hch[hc_num].dir = 0;
348 
349   /* set transfer buffer */
350   uhost->hch[hc_num].trans_buf = buffer;
351 
352   /* set transfer len*/
353   uhost->hch[hc_num].trans_len = length;
354 
355   if(uhost->hch[hc_num].toggle_out == 0)
356   {
357     /* pid: data0 */
358     uhost->hch[hc_num].data_pid = HCH_PID_DATA0;
359   }
360   else
361   {
362     /* pid: data1 */
363     uhost->hch[hc_num].data_pid = HCH_PID_DATA1;
364   }
365 
366   return usbh_in_out_request(uhost, hc_num);
367 }
368 
369 
370 /**
371   * @brief  usb host iso send request
372   * @param  uhost: to the structure of usbh_core_type
373   * @param  hc_num: channel number
374   * @param  buffer: send buffer
375   * @param  length: send length
376   * @retval status: usb_sts_type status
377   */
usbh_isoc_send(usbh_core_type * uhost,uint8_t hc_num,uint8_t * buffer,uint16_t length)378 usb_sts_type usbh_isoc_send(usbh_core_type *uhost, uint8_t hc_num,
379                             uint8_t *buffer, uint16_t length)
380 {
381   /* set direction is out */
382   uhost->hch[hc_num].dir = 0;
383 
384   /* set transfer buffer */
385   uhost->hch[hc_num].trans_buf = buffer;
386 
387   /* set transfer len*/
388   uhost->hch[hc_num].trans_len = length;
389 
390   /* pid: data0 */
391   uhost->hch[hc_num].data_pid = HCH_PID_DATA0;
392 
393   return usbh_in_out_request(uhost, hc_num);
394 }
395 
396 /**
397   * @brief  usb host iso receive request
398   * @param  uhost: to the structure of usbh_core_type
399   * @param  hc_num: channel number
400   * @param  buffer: receive buffer
401   * @param  length: receive length
402   * @retval status: usb_sts_type status
403   */
usbh_isoc_recv(usbh_core_type * uhost,uint8_t hc_num,uint8_t * buffer,uint16_t length)404 usb_sts_type usbh_isoc_recv(usbh_core_type *uhost, uint8_t hc_num,
405                             uint8_t *buffer, uint16_t length)
406 {
407   /* set direction is in */
408   uhost->hch[hc_num].dir = 1;
409 
410   /* set transfer buffer */
411   uhost->hch[hc_num].trans_buf = buffer;
412 
413   /* set transfer len*/
414   uhost->hch[hc_num].trans_len = length;
415 
416   /* pid: data0 */
417   uhost->hch[hc_num].data_pid = HCH_PID_DATA0;
418 
419   return usbh_in_out_request(uhost, hc_num);
420 }
421 
422 /**
423   * @brief  usb host cfg default init
424   * @param  uhost: to the structure of usbh_core_type
425   * @retval status: usb_sts_type status
426   */
usbh_cfg_default_init(usbh_core_type * uhost)427 usb_sts_type usbh_cfg_default_init(usbh_core_type *uhost)
428 {
429   /* set global state to idle */
430   uhost->global_state = USBH_IDLE;
431 
432   /* enumeration state to get description */
433   uhost->enum_state = ENUM_GET_MIN_DESC;
434 
435   /* request state send */
436   uhost->req_state = CMD_SEND;
437 
438   /* control transfer state is idle*/
439   uhost->ctrl.state = CONTROL_IDLE;
440 
441   /* defaut endpoint 0 max size is 8byte */
442   uhost->ctrl.ept0_size = 8;
443 
444   /* default device address is 0 */
445   uhost->dev.address = 0;
446 
447   /* default speed is full speed */
448   uhost->dev.speed = USB_FULL_SPEED_CORE_ID;
449 
450   uhost->timer = 0;
451 
452   uhost->ctrl.err_cnt = 0;
453 
454   /* free all channel */
455   usbh_free_channel(uhost, uhost->ctrl.hch_in);
456   usbh_free_channel(uhost, uhost->ctrl.hch_out);
457   return USB_OK;
458 }
459 
460 /**
461   * @brief  usb host enter suspend
462   * @param  uhost: to the structure of usbh_core_type
463   * @retval none
464   */
usbh_enter_suspend(usbh_core_type * uhost)465 void usbh_enter_suspend(usbh_core_type *uhost)
466 {
467   otg_host_type *host = OTG_HOST(uhost->usb_reg);
468   uint32_t hprt_val = host->hprt;
469 
470   hprt_val &= ~(USB_OTG_HPRT_PRTENA | USB_OTG_HPRT_PRTENCHNG |
471                USB_OTG_HPRT_PRTOVRCACT | USB_OTG_HPRT_PRTCONDET);
472 
473   /* set port suspend */
474   host->hprt = hprt_val | USB_OTG_HPRT_PRTSUSP;
475 
476   /* stop phy clock */
477   usb_stop_phy_clk(uhost->usb_reg);
478 
479 }
480 
481 /**
482   * @brief  usb host resume
483   * @param  uhost: to the structure of usbh_core_type
484   * @retval none
485   */
usbh_resume(usbh_core_type * uhost)486 void usbh_resume(usbh_core_type *uhost)
487 {
488   otg_host_type *host = OTG_HOST(uhost->usb_reg);
489   uint32_t temp = host->hprt;
490 
491   /* open phy clock */
492   usb_open_phy_clk(uhost->usb_reg);
493 
494   /* clear port suspend and set port resume*/
495   temp &= ~(USB_OTG_HPRT_PRTENA | USB_OTG_HPRT_PRTENCHNG |
496            USB_OTG_HPRT_PRTOVRCACT | USB_OTG_HPRT_PRTCONDET
497            | USB_OTG_HPRT_PRTSUSP);
498   host->hprt = temp | USB_OTG_HPRT_PRTRES;
499 
500   /* delay 20 ms */
501   rt_thread_mdelay(20);
502 
503   /*clear port resume */
504   temp = host->hprt;
505   temp &= ~(USB_OTG_HPRT_PRTENA | USB_OTG_HPRT_PRTENCHNG |
506            USB_OTG_HPRT_PRTOVRCACT | USB_OTG_HPRT_PRTCONDET
507            | USB_OTG_HPRT_PRTRES);
508   host->hprt = temp;
509   rt_thread_mdelay(5);
510 }
511 
512 /**
513   * @brief  usb host core initialize
514   * @param  uhost: to the structure of usbh_core_type
515   * @param  usb_reg: usb otgfs peripheral global register
516   *         this parameter can be one of the following values:
517   *         OTG1_GLOBAL , OTG2_GLOBAL
518   * @param  class_handler: usb host class handler type pointer
519   * @param  user_handler: usb host user handler type pointer
520   * @param  core_id: usb core select id
521   * @retval status: usb_sts_type status
522   */
usbh_core_init(usbh_core_type * uhost,usb_reg_type * usb_reg,uint8_t core_id)523 usb_sts_type usbh_core_init(usbh_core_type *uhost,
524                             usb_reg_type *usb_reg,
525                             uint8_t core_id)
526 {
527   usb_sts_type status = USB_OK;
528   uint32_t i_index;
529   uint32_t hs_phytype;
530   otg_global_type *usbx = usb_reg;
531   otg_host_type *host =  OTG_HOST(usbx);
532   uhost->usb_reg = usb_reg;
533   hs_phytype = *(__IO uint32_t *)((uint32_t)usbx + 0x48) & 0xC0;
534 
535   uhost->timer = 0;
536 
537   /* usb host cfg default init */
538   usbh_cfg_default_init(uhost);
539 
540   /* clear host config to default value */
541   for(i_index = 0; i_index < USB_HOST_CHANNEL_NUM; i_index ++)
542   {
543     uhost->err_cnt[i_index] = 0;
544     uhost->xfer_cnt[i_index] = 0;
545     uhost->hch_state[i_index] = HCH_IDLE;
546     uhost->hch[0].maxpacket = 8;
547   }
548 
549   /* no device connect */
550   uhost->conn_sts = 0;
551 
552   /* disable usb interrupt */
553   usb_interrupt_disable(usbx);
554 
555   /* usb global init */
556   usb_global_init(usbx);
557 
558   if(uhost->dma_en == TRUE && hs_phytype)
559   {
560     usbx->gahbcfg |= 1 << 5 | 3 << 1;
561   }
562   else
563   {
564     uhost->dma_en = FALSE;
565   }
566 
567   /* set usb host mode */
568   usb_global_set_mode(usbx, OTG_HOST_MODE);
569 
570   rt_thread_mdelay(25);
571 
572   /* open usb phy clock*/
573   usb_open_phy_clk(usbx);
574 
575   if(hs_phytype)
576   {
577     host->hcfg_bit.fslssupp = 0;
578     usbh_fsls_clksel(usbx, USB_HCFG_CLK_60M);
579   }
580   else
581   {
582     /* set support ls and fs device */
583     host->hcfg_bit.fslssupp = 0;
584     usbh_fsls_clksel(usbx, USB_HCFG_CLK_48M);
585   }
586 
587   if(usbx == OTG1_GLOBAL)
588   {
589     /* set receive fifo size */
590     usbx->grxfsiz = USBH_RX_FIFO_SIZE;
591 
592     /* set non-periodic transmit fifo start address and depth */
593     usbx->gnptxfsiz_ept0tx_bit.nptxfstaddr = USBH_RX_FIFO_SIZE;
594     usbx->gnptxfsiz_ept0tx_bit.nptxfdep = USBH_NP_TX_FIFO_SIZE;
595 
596     /* set periodic transmit fifo start address and depth */
597     usbx->hptxfsiz_bit.ptxfstaddr = USBH_RX_FIFO_SIZE + USBH_NP_TX_FIFO_SIZE;
598     usbx->hptxfsiz_bit.ptxfsize = USBH_P_TX_FIFO_SIZE;
599   }
600 #ifdef OTG2_GLOBAL
601   if(usbx == OTG2_GLOBAL)
602   {
603     /* set receive fifo size */
604     usbx->grxfsiz = USBH2_RX_FIFO_SIZE;
605 
606     /* set non-periodic transmit fifo start address and depth */
607     usbx->gnptxfsiz_ept0tx_bit.nptxfstaddr = USBH2_RX_FIFO_SIZE;
608     usbx->gnptxfsiz_ept0tx_bit.nptxfdep = USBH2_NP_TX_FIFO_SIZE;
609 
610     /* set periodic transmit fifo start address and depth */
611     usbx->hptxfsiz_bit.ptxfstaddr = USBH2_RX_FIFO_SIZE + USBH2_NP_TX_FIFO_SIZE;
612     usbx->hptxfsiz_bit.ptxfsize = USBH2_P_TX_FIFO_SIZE;
613   }
614 #endif
615   /* flush tx fifo */
616   usb_flush_tx_fifo(usbx, 16);
617 
618   /* flush rx fifo */
619   usb_flush_rx_fifo(usbx);
620 
621   /* clear host channel interrut mask and status */
622   for(i_index = 0; i_index < USB_HOST_CHANNEL_NUM; i_index ++)
623   {
624     USB_CHL(usbx, i_index)->hcintmsk = 0;
625     USB_CHL(usbx, i_index)->hcint = 0xFFFFFFFF;
626   }
627 
628   /* power on to this port */
629   usb_port_power_on(usbx, TRUE);
630 
631   /* clear global interrupt mask and status */
632   usbx->gintmsk = 0;
633   usbx->gintsts = 0xBFFFFFFF;
634 
635   /* set global interrut mask */
636   usbx->gintmsk = USB_OTG_SOF_INT  |
637                   USB_OTG_USBSUSP_INT | USB_OTG_PRT_INT |
638                    USB_OTG_HCH_INT | USB_OTG_INCOMISOIN_INT |
639                   USB_OTG_INCOMPIP_INCOMPISOOUT_INT | USB_OTG_WKUP_INT |
640                   USB_OTG_DISCON_INT;
641 
642   if(uhost->dma_en == FALSE)
643   {
644     usbx->gintmsk |= USB_OTG_RXFLVL_INT;
645   }
646 
647   /* enable usb global interrupt */
648   usb_interrupt_enable(usbx);
649 
650   /* active vbus */
651   usbh_active_vbus(uhost, TRUE);
652   return status;
653 }
654 
655 /**
656   * @brief  usb host open channel
657   * @param  uhost: to the structure of usbh_core_type
658   * @param  chn: host channel number
659   * @param  ept_num: devvice endpoint number
660   * @param  dev_address: device address
661   * @param  type: channel transfer type
662   *         this parameter can be one of the following values:
663   *         - EPT_CONTROL_TYPE
664   *         - EPT_BULK_TYPE
665   *         - EPT_INT_TYPE
666   *         - EPT_ISO_TYPE
667   * @param  maxpacket: support max packe size for this channel
668   * @param  speed: device speed
669   *         this parameter can be one of the following values:
670   *         - USB_PRTSPD_FULL_SPEED
671   *         - USB_PRTSPD_LOW_SPEED
672   * @param  ept_addr: endpoint address
673   * @retval usb_sts_type
674   */
usbh_hc_open(usbh_core_type * uhost,uint8_t chn,uint8_t ept_num,uint8_t dev_address,uint8_t type,uint16_t maxpacket,uint8_t speed)675 void usbh_hc_open(usbh_core_type *uhost,
676                    uint8_t chn,
677                    uint8_t ept_num,
678                    uint8_t dev_address,
679                    uint8_t type,
680                    uint16_t maxpacket,
681                    uint8_t speed)
682 {
683   /* device address */
684   uhost->hch[chn].address = dev_address;
685 
686   /* device speed */
687   uhost->hch[chn].speed = speed;
688 
689   /* endpoint transfer type */
690   uhost->hch[chn].ept_type = type;
691 
692   /* endpoint support maxpacket */
693   uhost->hch[chn].maxpacket = maxpacket;
694 
695   /* endpoint direction in or out */
696   uhost->hch[chn].dir = (ept_num & 0x80)?1:0;;
697 
698   /* host channel number */
699   uhost->hch[chn].ch_num = chn;
700 
701   /* device endpoint number */
702   uhost->hch[chn].ept_num = ept_num;
703 
704   /* enable channel */
705   usb_hc_enable(uhost->usb_reg, chn,
706                 ept_num, dev_address,
707                 type, maxpacket, speed
708            );
709 }
710 
711 /**
712   * @brief  disable host channel
713   * @param  usbx: to select the otgfs peripheral.
714   *         this parameter can be one of the following values:
715   *         - OTG1_GLOBAL
716   *         - OTG2_GLOBAL
717   * @param  chn: channel number
718   * @retval none
719   */
usbh_ch_disable(usbh_core_type * uhost,uint8_t chn)720 void usbh_ch_disable(usbh_core_type *uhost, uint8_t chn)
721 {
722   usb_hch_halt(uhost->usb_reg, chn);
723 }
724 
725 /**
726   * @brief  usb host alloc channel
727   * @param  uhost: to the structure of usbh_core_type
728   * @param  ept_addr: endpoint address
729   * @retval usb_sts_type
730   */
usbh_alloc_channel(usbh_core_type * uhost,uint8_t ept_addr)731 uint16_t usbh_alloc_channel(usbh_core_type *uhost, uint8_t ept_addr)
732 {
733   /* get one free channel */
734   uint16_t ch_num = usbh_get_free_channel(uhost);
735 
736   if(ch_num == HCH_ERROR)
737     return USB_FAIL;
738 
739   /* set channel to used */
740   uhost->channel[ch_num] = HCH_USED | ept_addr;
741   return ch_num;
742 }
743 
usbh_get_status(usbh_core_type * uhost,uint8_t ch_num)744 hch_sts_type usbh_get_status(usbh_core_type *uhost, uint8_t ch_num)
745 {
746    return uhost->hch_state[ch_num];
747 }
748 
749 /**
750   * @brief  usb host get urb status
751   * @param  uhost: to the structure of usbh_core_type
752   * @param  ch_num: channel number
753   * @retval urb_sts_type: urb status
754   */
usbh_get_urb_status(usbh_core_type * uhost,uint8_t ch_num)755 urb_sts_type usbh_get_urb_status(usbh_core_type *uhost, uint8_t ch_num)
756 {
757   return uhost->urb_state[ch_num];
758 }
759 /**
760   * @brief  usb wait control setup complete
761   * @param  uhost: to the structure of usbh_core_type
762   * @param  next_ctrl_state: next ctrl state when setup complete
763   * @param  next_enum_state: next enum state when setup complete
764   * @retval status: usb_sts_type status
765   */
usbh_ctrl_result_check(usbh_core_type * uhost,ctrl_ept0_sts_type next_ctrl_state,uint8_t next_enum_state)766 usb_sts_type usbh_ctrl_result_check(usbh_core_type *uhost, ctrl_ept0_sts_type next_ctrl_state, uint8_t next_enum_state)
767 {
768   usb_sts_type status;
769 
770   /* control transfer loop */
771   status = usbh_ctrl_transfer_loop(uhost);
772 
773   if(status == USB_OK)
774   {
775     uhost->ctrl.state = next_ctrl_state;
776     uhost->enum_state = next_enum_state;
777     uhost->req_state = CMD_SEND;
778   }
779   else if(status == USB_ERROR)
780   {
781     uhost->ctrl.state = CONTROL_IDLE;
782     uhost->req_state = CMD_SEND;
783   }
784   else if(status == USB_NOT_SUPPORT)
785   {
786     uhost->ctrl.state = next_ctrl_state;
787     uhost->enum_state = next_enum_state;
788     uhost->req_state = CMD_SEND;
789   }
790   return status;
791 }
792 
793 /**
794   * @brief  auto alloc address (1...20)
795   * @param  none
796   * @retval address (1...20)
797   */
usbh_alloc_address(void)798 uint8_t usbh_alloc_address(void)
799 {
800   static uint8_t address = 1;
801   if(address == 20)
802     address = 1;
803   return address ++;
804 }
805 
806 
807 /**
808   * @brief  usb host enumeration handler
809   * @param  uhost: to the structure of usbh_core_type
810   * @retval status: usb_sts_type status
811   */
usbh_enum_handler(usbh_core_type * uhost)812 usb_sts_type usbh_enum_handler(usbh_core_type *uhost)
813 {
814   usb_sts_type status = USB_WAIT;
815   switch(uhost->enum_state)
816   {
817     case ENUM_IDLE:
818       break;
819     case ENUM_GET_MIN_DESC:
820       /* get description */
821       if(uhost->ctrl.state == CONTROL_IDLE)
822       {
823         usbh_get_device_descriptor(uhost, 8);
824       }
825       if(usbh_ctrl_result_check(uhost, CONTROL_IDLE, ENUM_GET_FULL_DESC) == USB_OK)
826       {
827         usbh_parse_dev_desc(uhost, uhost->rx_buffer, 8);
828 
829         /* set new control endpoint maxpacket size */
830         uhost->ctrl.ept0_size = (uhost->dev).dev_desc.bMaxPacketSize0;
831 
832         /* enable channel */
833         usbh_hc_open(uhost, uhost->ctrl.hch_in,0x80,
834                       uhost->dev.address, EPT_CONTROL_TYPE,
835                       uhost->ctrl.ept0_size,
836                       uhost->dev.speed);
837 
838         /* enable channel */
839         usbh_hc_open(uhost, uhost->ctrl.hch_out,0x00,
840                       uhost->dev.address, EPT_CONTROL_TYPE,
841                       uhost->ctrl.ept0_size,
842                       uhost->dev.speed);
843       }
844       break;
845 
846     case ENUM_GET_FULL_DESC:
847       /* get description */
848       if(uhost->ctrl.state == CONTROL_IDLE)
849       {
850         usbh_get_device_descriptor(uhost, 18);
851       }
852       if(usbh_ctrl_result_check(uhost, CONTROL_IDLE, ENUM_SET_ADDR) == USB_OK)
853       {
854         usbh_parse_dev_desc(uhost, uhost->rx_buffer, 18);
855       }
856       break;
857 
858     case ENUM_SET_ADDR:
859       /* set device address */
860       if(uhost->ctrl.state == CONTROL_IDLE)
861       {
862         uhost->dev.address = usbh_alloc_address();
863         usbh_set_address(uhost, uhost->dev.address);
864       }
865       if (usbh_ctrl_result_check(uhost, CONTROL_IDLE, ENUM_GET_CFG) == USB_OK)
866       {
867         /* enable channel */
868         usbh_hc_open(uhost, uhost->ctrl.hch_in,0x80,
869                       uhost->dev.address, EPT_CONTROL_TYPE,
870                       uhost->ctrl.ept0_size,
871                       uhost->dev.speed);
872 
873         /* enable channel */
874         usbh_hc_open(uhost, uhost->ctrl.hch_out,0x00,
875                       uhost->dev.address, EPT_CONTROL_TYPE,
876                       uhost->ctrl.ept0_size,
877                       uhost->dev.speed);
878       }
879       break;
880 
881     case ENUM_GET_CFG:
882       /* get device confiuration */
883       if(uhost->ctrl.state == CONTROL_IDLE)
884       {
885         usbh_get_configure_descriptor(uhost, 9);
886       }
887 
888       if(usbh_ctrl_result_check(uhost, CONTROL_IDLE, ENUM_GET_FULL_CFG) == USB_OK)
889       {
890         usbh_parse_configure_desc(uhost, uhost->rx_buffer, 9);
891       }
892       break;
893 
894     case ENUM_GET_FULL_CFG:
895       /* get device confiuration */
896       if(uhost->ctrl.state == CONTROL_IDLE)
897       {
898         usbh_get_configure_descriptor(uhost, uhost->dev.cfg_desc.cfg.wTotalLength);
899       }
900 
901       if(usbh_ctrl_result_check(uhost, CONTROL_IDLE, ENUM_GET_MFC_STRING) == USB_OK)
902       {
903         usbh_parse_configure_desc(uhost, uhost->rx_buffer, uhost->dev.cfg_desc.cfg.wTotalLength);
904       }
905       break;
906 
907     case ENUM_GET_MFC_STRING:
908       /* get device mfc string */
909       if(uhost->ctrl.state == CONTROL_IDLE)
910       {
911         usbh_get_sting_descriptor(uhost, uhost->dev.dev_desc.iManufacturer,
912                                   uhost->rx_buffer, 0xFF);
913       }
914 
915       if(usbh_ctrl_result_check(uhost, CONTROL_IDLE, ENUM_GET_PRODUCT_STRING) == USB_OK)
916       {
917         usbh_parse_string_desc(uhost->rx_buffer, uhost->rx_buffer, 0xFF);
918         uhost->user_handler->user_mfc_string(uhost->rx_buffer);
919       }
920       break;
921 
922     case ENUM_GET_PRODUCT_STRING:
923       /* get device product string */
924       if(uhost->ctrl.state == CONTROL_IDLE)
925       {
926         usbh_get_sting_descriptor(uhost, uhost->dev.dev_desc.iProduct,
927                                   uhost->rx_buffer, 0xFF);
928       }
929 
930       if(usbh_ctrl_result_check(uhost, CONTROL_IDLE, ENUM_GET_SERIALNUM_STRING) == USB_OK)
931       {
932         usbh_parse_string_desc(uhost->rx_buffer, uhost->rx_buffer, 0xFF);
933         uhost->user_handler->user_product_string(uhost->rx_buffer);
934       }
935       break;
936 
937     case ENUM_GET_SERIALNUM_STRING:
938       /* get device serial string */
939       if(uhost->ctrl.state == CONTROL_IDLE)
940       {
941         usbh_get_sting_descriptor(uhost, uhost->dev.dev_desc.iSerialNumber,
942                                   uhost->rx_buffer, 0xFF);
943       }
944 
945       if(usbh_ctrl_result_check(uhost, CONTROL_IDLE, ENUM_SET_CONFIG) == USB_OK)
946       {
947         usbh_parse_string_desc(uhost->rx_buffer, uhost->rx_buffer, 0xFF);
948         uhost->user_handler->user_serial_string(uhost->rx_buffer);
949       }
950       break;
951 
952     case ENUM_SET_CONFIG:
953       /* set device config */
954       if(uhost->ctrl.state == CONTROL_IDLE)
955       {
956         usbh_set_configuration(uhost, uhost->dev.cfg_desc.cfg.bConfigurationValue);
957       }
958       usbh_ctrl_result_check(uhost, CONTROL_IDLE, ENUM_COMPLETE);
959 
960       break;
961 
962     case ENUM_COMPLETE:
963       /* enum complete */
964       status = USB_OK;
965       break;
966     default:
967       break;
968   }
969   return status;
970 }
971 
972 /**
973   * @brief  active vbus.
974   * @param  uhost: to the structure of usbh_core_type
975   * @param  state: vbus state
976   * @retval none
977   */
usbh_active_vbus(usbh_core_type * uhost,confirm_state state)978 void usbh_active_vbus(usbh_core_type *uhost, confirm_state state)
979 {
980 }
981 
982 /**
983   * @brief  reset usb port
984   * @param  usbx: to the structure of otg_global_type
985   * @retval none
986   */
usbh_reset_port(usbh_core_type * uhost)987 void usbh_reset_port(usbh_core_type *uhost)
988 {
989   otg_host_type *usb_host = OTG_HOST(uhost->usb_reg);
990   uint32_t hprt_val = usb_host->hprt;
991 
992   hprt_val &= ~(USB_OTG_HPRT_PRTENA | USB_OTG_HPRT_PRTENCHNG |
993                USB_OTG_HPRT_PRTOVRCACT | USB_OTG_HPRT_PRTCONDET);
994 
995   /* set port reset */
996   usb_host->hprt = hprt_val | USB_OTG_HPRT_PRTRST;
997 
998   rt_thread_mdelay(100);
999 
1000   /* clear port reset */
1001   usb_host->hprt = hprt_val & (~USB_OTG_HPRT_PRTRST);
1002 
1003   rt_thread_mdelay(20);
1004 }
1005 
1006 /**
1007   * @brief  usb host attached
1008   * @param  uhost: to the structure of usbh_core_type
1009   * @retval none
1010   */
usbh_attached(usbh_core_type * uhost)1011 static void usbh_attached(usbh_core_type *uhost)
1012 {
1013   /* get free channel */
1014   uhost->ctrl.hch_in = usbh_alloc_channel(uhost, 0x80);
1015   uhost->ctrl.hch_out = usbh_alloc_channel(uhost, 0x00);
1016 
1017   /* user reset callback handler */
1018   uhost->user_handler->user_reset();
1019 
1020   /* get device speed */
1021   uhost->dev.speed = OTG_HOST(uhost->usb_reg)->hprt_bit.prtspd;
1022   uhost->global_state  = USBH_ENUMERATION;
1023   uhost->user_handler->user_speed(uhost->dev.speed);
1024 
1025   /* enable channel */
1026   usbh_hc_open(uhost, uhost->ctrl.hch_in,0x80,
1027                 uhost->dev.address, EPT_CONTROL_TYPE,
1028                 uhost->ctrl.ept0_size,
1029                 uhost->dev.speed);
1030 
1031   /* enable channel */
1032   usbh_hc_open(uhost, uhost->ctrl.hch_out,0x00,
1033                 uhost->dev.address, EPT_CONTROL_TYPE,
1034                 uhost->ctrl.ept0_size,
1035                 uhost->dev.speed);
1036 
1037   usb_flush_tx_fifo(uhost->usb_reg, 0x10);
1038   usb_flush_rx_fifo(uhost->usb_reg);
1039 
1040   /* user attached callback */
1041   uhost->user_handler->user_attached();
1042 }
1043 
1044 
1045 /**
1046   * @brief  usb host enumeration
1047   * @param  uhost: to the structure of usbh_core_type
1048   * @retval none
1049   */
usbh_enumeration(usbh_core_type * uhost)1050 static void usbh_enumeration(usbh_core_type *uhost)
1051 {
1052   /* enumeration process */
1053   if(usbh_enum_handler(uhost) == USB_OK)
1054   {
1055     /* user enumeration done callback */
1056     uhost->user_handler->user_enumeration_done();
1057     uhost->global_state  = USBH_USER_HANDLER;
1058   }
1059 }
1060 
1061 /**
1062   * @brief  usb host class request
1063   * @param  uhost: to the structure of usbh_core_type
1064   * @retval none
1065   */
usbh_class_request(usbh_core_type * uhost)1066 static void usbh_class_request(usbh_core_type *uhost)
1067 {
1068   usb_sts_type status;
1069 
1070   /* class request callback */
1071   status = uhost->class_handler->request_handler((void *)uhost);
1072   if(status == USB_OK)
1073   {
1074     uhost->global_state = USBH_CLASS;
1075   }
1076   else if(status == USB_ERROR || status == USB_FAIL)
1077   {
1078     uhost->global_state = USBH_ERROR_STATE;
1079   }
1080   else if(status == USB_NOT_SUPPORT)
1081   {
1082     uhost->global_state = USBH_ERROR_STATE;
1083   }
1084 }
1085 
1086 /**
1087   * @brief  usb host class handler
1088   * @param  uhost: to the structure of usbh_core_type
1089   * @retval none
1090   */
usbh_class(usbh_core_type * uhost)1091 static void usbh_class(usbh_core_type *uhost)
1092 {
1093   /* process handler */
1094   if(uhost->class_handler->process_handler((void *)uhost) == USB_OK)
1095   {
1096   }
1097 }
1098 
1099 /**
1100   * @brief  usb host suspend
1101   * @param  uhost: to the structure of usbh_core_type
1102   * @retval none
1103   */
usbh_suspend(usbh_core_type * uhost)1104 static void usbh_suspend(usbh_core_type *uhost)
1105 {
1106   /* set device feature */
1107   if(uhost->ctrl.state == CONTROL_IDLE)
1108   {
1109     usbh_set_feature(uhost, 0x01, 0);
1110   }
1111   if(usbh_ctrl_result_check(uhost, CONTROL_IDLE, ENUM_IDLE) == USB_OK)
1112   {
1113     /* enter suspend mode */
1114     rt_thread_mdelay(3);
1115     usbh_enter_suspend(uhost);
1116     uhost->global_state = USBH_SUSPENDED;
1117 
1118   }
1119 }
1120 
1121 /**
1122   * @brief  usb host wakeup
1123   * @param  uhost: to the structure of usbh_core_type
1124   * @retval none
1125   */
usbh_wakeup(usbh_core_type * uhost)1126 static void usbh_wakeup(usbh_core_type *uhost)
1127 {
1128   /* clear device feature */
1129   if(uhost->ctrl.state == CONTROL_IDLE)
1130   {
1131    /* usb host resume */
1132     usbh_resume(uhost);
1133     usbh_clear_dev_feature(uhost, 0x01, 0);
1134   }
1135   if(usbh_ctrl_result_check(uhost, CONTROL_IDLE, ENUM_IDLE) == USB_OK)
1136   {
1137     uhost->global_state = USBH_CLASS_REQUEST;
1138   }
1139 }
1140 
1141 /**
1142   * @brief  usb host disconnect
1143   * @param  uhost: to the structure of usbh_core_type
1144   * @retval none
1145   */
usbh_disconnect(usbh_core_type * uhost)1146 static void usbh_disconnect(usbh_core_type *uhost)
1147 {
1148   uint8_t i_index = 0;
1149 
1150   /* set host to default state */
1151   usbh_cfg_default_init(uhost);
1152 
1153   /* free host channel */
1154   for(i_index = 0; i_index < USB_HOST_CHANNEL_NUM; i_index ++)
1155   {
1156     usbh_free_channel(uhost, i_index);
1157   }
1158 
1159   /* call class reset handler */
1160   if(uhost->class_handler->reset_handler != RT_NULL)
1161   {
1162     uhost->class_handler->reset_handler(uhost);
1163   }
1164 
1165   /* set global state to idle */
1166   uhost->global_state = USBH_IDLE;
1167 
1168   /*call user disconnect function */
1169   uhost->user_handler->user_disconnect();
1170 }
1171 
1172 
1173 /**
1174   * @brief  usb host enum loop handler
1175   * @param  uhost: to the structure of usbh_core_type
1176   * @retval none
1177   */
usbh_loop_handler(usbh_core_type * uhost)1178 usb_sts_type usbh_loop_handler(usbh_core_type *uhost)
1179 {
1180   usb_sts_type status = USB_FAIL;
1181 
1182   if(uhost->conn_sts == 0 &&
1183       uhost->global_state != USBH_IDLE &&
1184       uhost->global_state != USBH_DISCONNECT)
1185   {
1186     uhost->global_state  = USBH_IDLE;
1187   }
1188   switch(uhost->global_state)
1189   {
1190     case USBH_IDLE:
1191       if(uhost->conn_sts == 1)
1192       {
1193         uhost->global_state  = USBH_PORT_EN;
1194 
1195         /* wait stable */
1196         rt_thread_mdelay(200);
1197 
1198         /* port reset */
1199         usbh_reset_port(uhost);
1200 
1201         /* user reset */
1202         uhost->user_handler->user_reset();
1203       }
1204       break;
1205 
1206     case USBH_PORT_EN:
1207       if(uhost->port_enable)
1208       {
1209         uhost->global_state  = USBH_ATTACHED;
1210         rt_thread_mdelay(50);
1211       }
1212       break;
1213 
1214     case USBH_ATTACHED:
1215       usbh_attached(uhost);
1216       break;
1217 
1218     case USBH_ENUMERATION:
1219       usbh_enumeration(uhost);
1220       break;
1221 
1222     case USBH_USER_HANDLER:
1223       uhost->global_state  = USBH_CLASS_REQUEST;
1224       if( uhost->class_handler->init_handler(uhost) == USB_NOT_SUPPORT)
1225       {
1226         uhost->global_state = USBH_UNSUPPORT;
1227       }
1228       break;
1229 
1230     case USBH_CLASS_REQUEST:
1231       usbh_class_request(uhost);
1232       break;
1233 
1234     case USBH_CLASS:
1235       usbh_class(uhost);
1236       break;
1237 
1238     case USBH_SUSPEND:
1239       usbh_suspend(uhost);
1240       break;
1241 
1242     case USBH_SUSPENDED:
1243       break;
1244 
1245     case USBH_WAKEUP:
1246       usbh_wakeup(uhost);
1247       break;
1248 
1249     case USBH_DISCONNECT:
1250       usbh_disconnect(uhost);
1251       break;
1252 
1253     case USBH_ERROR_STATE:
1254       usbh_cfg_default_init(uhost);
1255       uhost->class_handler->reset_handler(uhost);
1256       uhost->user_handler->user_reset();
1257       break;
1258     case USBH_UNSUPPORT:
1259       break;
1260     default:
1261       break;
1262   }
1263 
1264   return status;
1265 }
1266 
1267 /**
1268   * @}
1269   */
1270 
1271 /**
1272   * @}
1273   */
1274 
1275 #endif
1276