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