1 /*
2  * Copyright (c) 2006-2023, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author            Notes
8  * 2017-10-30     ZYH               the first version
9  * 2019-12-19     tyustli           port to stm32 series
10  * 2021-01-19     Leslie Lee        port to imxrt series
11  */
12 #include <rtthread.h>
13 
14 #if defined(BSP_USB0_HOST) || defined(BSP_USB1_HOST)
15 #include "drv_usbh.h"
16 #include <usb/include/usb_host_config.h>
17 #include <usb/include/usb.h>
18 #include <usb/phy/usb_phy.h>
19 #include <usb/host/usb_host.h>
20 #include <usb/host/usb_host_hci.h>
21 #include <usb/host/usb_host_ehci.h>
22 #include <rtdevice.h>
23 
24 //#define DRV_DEBUG
25 #define LOG_TAG             "drv.usb.host"
26 #include <drv_log.h>
27 
28 /* USB PHY configuration */
29 #ifndef BOARD_USB_PHY_D_CAL
30 #ifdef SOC_IMXRT1170_SERIES
31 #define BOARD_USB_PHY_D_CAL (0x07U)
32 #else
33 #define BOARD_USB_PHY_D_CAL (0x0CU)
34 #endif
35 #endif
36 #ifndef BOARD_USB_PHY_TXCAL45DP
37 #define BOARD_USB_PHY_TXCAL45DP (0x06U)
38 #endif
39 #ifndef BOARD_USB_PHY_TXCAL45DM
40 #define BOARD_USB_PHY_TXCAL45DM (0x06U)
41 #endif
42 
43 #define USB_HOST_INTERRUPT_PRIORITY 6
44 
45 /* Allocate the memory for the heap. */
46 #if defined(configAPPLICATION_ALLOCATED_HEAP) && (configAPPLICATION_ALLOCATED_HEAP)
USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE)47 USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE) uint8_t ucHeap[configTOTAL_HEAP_SIZE];
48 #endif
49 
50 enum
51 {
52 #ifdef BSP_USB0_HOST
53     USBH0_INDEX,
54 #endif
55 #ifdef BSP_USB1_HOST
56     USBH1_INDEX,
57 #endif
58 };
59 
60 struct imxrt_usb_host_pipe
61 {
62     usb_host_pipe_handle pipe_handle;
63     struct rt_completion urb_completion;
64     usb_status_t transfer_status;
65 };
66 
67 struct imxrt_usb_host
68 {
69     struct uhcd uhcd;
70     usb_host_handle host_handle;
71     usb_device_handle device_handle;
72     struct imxrt_usb_host_pipe pipes[16];
73     volatile rt_bool_t connect_status;
74     char *name;
75 };
76 
77 static struct imxrt_usb_host imxrt_usb_host_obj[] =
78 {
79 #ifdef BSP_USB0_HOST
80     {
81         .connect_status = RT_FALSE,
82         .name           = "usbh0"
83     },
84 #endif
85 #ifdef BSP_USB1_HOST
86     {
87         .connect_status = RT_FALSE,
88         .name           = "usbh1"
89     },
90 #endif
91 };
92 
_imxrt_usb_host_send_callback(void * param,usb_host_transfer_t * transfer,usb_status_t status)93 static void _imxrt_usb_host_send_callback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
94 {
95     struct imxrt_usb_host_pipe *pipe = (struct imxrt_usb_host_pipe *)param;
96     pipe->transfer_status = status;
97     rt_completion_done(&pipe->urb_completion);
98 }
99 
100 
101 /*!
102  * @brief Initializes USB specific setting that was not set by the Clocks tool.
103  */
USB_HostClockInit(usb_controller_index_t controller_id)104 static void USB_HostClockInit(usb_controller_index_t controller_id)
105 {
106     uint32_t usbClockFreq;
107     usb_phy_config_struct_t phyConfig = {
108         BOARD_USB_PHY_D_CAL, BOARD_USB_PHY_TXCAL45DP, BOARD_USB_PHY_TXCAL45DM,
109     };
110 
111     usbClockFreq = 24000000;
112 
113     if (controller_id == kUSB_ControllerEhci0)
114     {
115         CLOCK_EnableUsbhs0PhyPllClock(kCLOCK_Usbphy480M, usbClockFreq);
116         CLOCK_EnableUsbhs0Clock(kCLOCK_Usb480M, usbClockFreq);
117     }
118     else
119     {
120         CLOCK_EnableUsbhs1PhyPllClock(kCLOCK_Usbphy480M, usbClockFreq);
121         CLOCK_EnableUsbhs1Clock(kCLOCK_Usb480M, usbClockFreq);
122     }
123 
124     USB_EhciPhyInit(controller_id, 24000000U, &phyConfig);
125 }
126 
127 /*!
128  * @brief Enables interrupt service routines for device.
129  */
USB_HostIsrEnable(usb_controller_index_t controller_id)130 void USB_HostIsrEnable(usb_controller_index_t controller_id)
131 {
132     uint8_t irqNumber;
133 #if ((defined USB_HOST_CONFIG_EHCI) && (USB_HOST_CONFIG_EHCI > 0U))
134     IRQn_Type usbHOSTEhciIrq[] = USBHS_IRQS;
135     irqNumber = usbHOSTEhciIrq[controller_id - kUSB_ControllerEhci0];
136 #endif
137 /* Install isr, set priority, and enable IRQ. */
138 #if defined(__GIC_PRIO_BITS)
139     GIC_SetPriority((IRQn_Type)irqNumber, USB_HOST_INTERRUPT_PRIORITY);
140 #else
141     NVIC_SetPriority((IRQn_Type)irqNumber, USB_HOST_INTERRUPT_PRIORITY);
142 #endif
143     EnableIRQ((IRQn_Type)irqNumber);
144 }
145 
146 #ifdef BSP_USB0_HOST
USB_OTG1_IRQHandler(void)147 void USB_OTG1_IRQHandler(void)
148 {
149     /* enter interrupt */
150     rt_interrupt_enter();
151 
152     USB_HostEhciIsrFunction(imxrt_usb_host_obj[USBH0_INDEX].host_handle);
153     /* leave interrupt */
154     rt_interrupt_leave();
155 }
156 
_ehci0_reset_port(rt_uint8_t port)157 static rt_err_t _ehci0_reset_port(rt_uint8_t port)
158 {
159     // No reset port function available
160     return RT_EOK;
161 }
162 
163 static uint8_t _ehci0_pipe_buf[64];
164 static uint8_t _ehci0_pipe_idx;
165 
_ehci0_pipe_xfer(upipe_t pipe,rt_uint8_t token,void * buffer,int nbytes,int timeouts)166 static int _ehci0_pipe_xfer(upipe_t pipe, rt_uint8_t token, void *buffer, int nbytes, int timeouts)
167 {
168 //    int timeout = timeouts;
169 
170     if (!imxrt_usb_host_obj[USBH0_INDEX].connect_status)
171     {
172         return -1;
173     }
174     usb_host_transfer_t *transfer;
175     if (imxrt_usb_host_obj[USBH0_INDEX].pipes[pipe->pipe_index].pipe_handle == NULL)
176     {
177         LOG_D("error operation on null pipe");
178         return -1;
179     }
180     if (USB_HostMallocTransfer(imxrt_usb_host_obj[USBH0_INDEX].host_handle, &transfer) != kStatus_USB_Success)
181     {
182         LOG_D("error to get transfer");
183         return -1;
184     }
185     transfer->transferBuffer      = buffer;
186     transfer->transferLength      = nbytes;
187     transfer->transferSofar       = 0;
188     transfer->callbackFn          = _imxrt_usb_host_send_callback;
189     transfer->callbackParam       = &(imxrt_usb_host_obj[USBH0_INDEX].pipes[pipe->pipe_index]);
190     transfer->direction         = (pipe->ep.bEndpointAddress & USB_DIR_IN) ? USB_IN : USB_OUT;
191     if (pipe->ep.bmAttributes == USB_ENDPOINT_CONTROL)
192     {
193         if (token == USBH_PID_SETUP)
194         {
195             struct urequest *setup = (struct urequest *)buffer;
196             transfer->setupStatus = 0;
197             transfer->setupPacket->bmRequestType = setup->request_type;
198             transfer->setupPacket->bRequest = setup->bRequest;
199             transfer->setupPacket->wIndex = setup->wIndex;
200             transfer->setupPacket->wLength = setup->wLength;
201             transfer->setupPacket->wValue = setup->wValue;
202             transfer->transferBuffer    = RT_NULL;
203             transfer->transferLength    = 0;
204             transfer->next = RT_NULL;
205             if ((transfer->setupPacket->bmRequestType & USB_REQUEST_TYPE_DIR_MASK) == USB_REQUEST_TYPE_DIR_IN)
206             {
207                 transfer->direction = USB_IN;
208                 transfer->transferBuffer = _ehci0_pipe_buf;
209                 transfer->transferLength = setup->wLength;
210                 _ehci0_pipe_idx = 0;
211             }
212             else
213             {
214                 transfer->direction = USB_OUT;
215             }
216         }
217         else
218         {
219             rt_memcpy(buffer, _ehci0_pipe_buf + _ehci0_pipe_idx, nbytes);
220             imxrt_usb_host_obj[USBH0_INDEX].pipes[pipe->pipe_index].transfer_status = kStatus_USB_Success;
221             transfer->transferSofar = nbytes;
222             _ehci0_pipe_idx += nbytes;
223             if (_ehci0_pipe_idx >= 64)
224             {
225                 _ehci0_pipe_idx = 0;
226             }
227             goto _ehci0_pipe_xfer_finish;
228         }
229 
230     }
231     rt_completion_init(&(imxrt_usb_host_obj[USBH0_INDEX].pipes[pipe->pipe_index].urb_completion));
232     if (USB_HostEhciWritePipe(((usb_host_instance_t *)imxrt_usb_host_obj[USBH0_INDEX].host_handle)->controllerHandle, imxrt_usb_host_obj[USBH0_INDEX].pipes[pipe->pipe_index].pipe_handle, transfer) != kStatus_USB_Success)
233     {
234         LOG_D("usb host failed to send");
235         (void)USB_HostFreeTransfer(imxrt_usb_host_obj[USBH0_INDEX].host_handle, transfer);
236         return -1;
237     }
238     if (-RT_ETIMEOUT == rt_completion_wait(&(imxrt_usb_host_obj[USBH0_INDEX].pipes[pipe->pipe_index].urb_completion), RT_WAITING_FOREVER))
239     {
240         LOG_D("usb transfer timeout");
241         (void)USB_HostFreeTransfer(imxrt_usb_host_obj[USBH0_INDEX].host_handle, transfer);
242         return -1;
243     }
244     _ehci0_pipe_xfer_finish:
245     switch (imxrt_usb_host_obj[USBH0_INDEX].pipes[pipe->pipe_index].transfer_status)
246     {
247     case kStatus_USB_Success:
248     {
249         LOG_D("ok");
250         pipe->status = UPIPE_STATUS_OK;
251         if (pipe->callback != RT_NULL)
252         {
253             pipe->callback(pipe);
254         }
255         size_t size = transfer->transferSofar;
256         (void)USB_HostFreeTransfer(imxrt_usb_host_obj[USBH0_INDEX].host_handle, transfer);
257         if (pipe->ep.bEndpointAddress & 0x80)
258         {
259             return size;
260         }
261         else if (pipe->ep.bEndpointAddress & 0x00)
262         {
263             return size;
264         }
265         return nbytes;
266         break;
267     }
268     case kStatus_USB_TransferStall:
269     {
270         LOG_D("stall");
271         pipe->status = UPIPE_STATUS_STALL;
272         if (pipe->callback != RT_NULL)
273         {
274             pipe->callback(pipe);
275         }
276         (void)USB_HostFreeTransfer(imxrt_usb_host_obj[USBH0_INDEX].host_handle, transfer);
277         return -1;
278         break;
279     }
280     case kStatus_USB_TransferFailed:
281     default:
282     {
283         LOG_D("error");
284         pipe->status = UPIPE_STATUS_ERROR;
285         if (pipe->callback != RT_NULL)
286         {
287             pipe->callback(pipe);
288         }
289         (void)USB_HostFreeTransfer(imxrt_usb_host_obj[USBH0_INDEX].host_handle, transfer);
290         return -1;
291         break;
292     }
293     }
294 }
295 
296 static rt_uint16_t _ehci0_pipe_index = 0;
_ehci0_get_free_pipe_index(void)297 static rt_uint8_t  _ehci0_get_free_pipe_index(void)
298 {
299     rt_uint8_t idx;
300     for (idx = 1; idx < 16; idx++)
301     {
302         if (!(_ehci0_pipe_index & (0x01 << idx)))
303         {
304             _ehci0_pipe_index |= (0x01 << idx);
305             return idx;
306         }
307     }
308     return 0xff;
309 }
310 
_ehci0_free_pipe_index(rt_uint8_t index)311 static void _ehci0_free_pipe_index(rt_uint8_t index)
312 {
313     _ehci0_pipe_index &= ~(0x01 << index);
314 }
315 
_ehci0_open_pipe(upipe_t pipe)316 static rt_err_t _ehci0_open_pipe(upipe_t pipe)
317 {
318     pipe->pipe_index = _ehci0_get_free_pipe_index();
319     if (pipe->pipe_index == 0xFF)
320     {
321         return -RT_ERROR;
322     }
323     usb_host_pipe_init_t pipe_init =
324     {
325         .devInstance = imxrt_usb_host_obj[USBH0_INDEX].device_handle,
326         .pipeType = pipe->ep.bmAttributes,
327         .direction = (pipe->ep.bEndpointAddress & USB_DIR_IN) ? USB_IN : USB_OUT,
328         .endpointAddress = (pipe->ep.bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK),
329         .interval = pipe->ep.bInterval,
330         .maxPacketSize = (uint16_t)(pipe->ep.wMaxPacketSize & USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK),
331         .numberPerUframe = (uint8_t)(pipe->ep.wMaxPacketSize & USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_MASK),
332         .nakCount = USB_HOST_CONFIG_MAX_NAK,
333     };
334     USB_HostOpenPipe(imxrt_usb_host_obj[USBH0_INDEX].host_handle, &imxrt_usb_host_obj[USBH0_INDEX].pipes[pipe->pipe_index].pipe_handle, &pipe_init);
335     return RT_EOK;
336 }
337 
_ehci0_close_pipe(upipe_t pipe)338 static rt_err_t _ehci0_close_pipe(upipe_t pipe)
339 {
340     (void)USB_HostClosePipe(imxrt_usb_host_obj[USBH0_INDEX].host_handle, imxrt_usb_host_obj[USBH0_INDEX].pipes[pipe->pipe_index].pipe_handle);
341     _ehci0_free_pipe_index(pipe->pipe_index);
342     return RT_EOK;
343 }
344 
345 static struct uhcd_ops _ehci0_uhcd_ops =
346 {
347     _ehci0_reset_port,
348     _ehci0_pipe_xfer,
349     _ehci0_open_pipe,
350     _ehci0_close_pipe,
351 };
352 
usb0_host_callback(usb_device_handle handle,usb_host_configuration_handle config_handle,rt_uint32_t event_code)353 static usb_status_t usb0_host_callback(usb_device_handle handle, usb_host_configuration_handle config_handle, rt_uint32_t event_code)
354 {
355     usb_status_t status = kStatus_USB_Success;
356 
357     switch (event_code)
358     {
359     case kUSB_HostEventAttach:
360         if (!imxrt_usb_host_obj[USBH0_INDEX].connect_status)
361         {
362             imxrt_usb_host_obj[USBH0_INDEX].connect_status = RT_TRUE;
363             imxrt_usb_host_obj[USBH0_INDEX].device_handle = handle;
364             LOG_D("usb connected");
365             rt_usbh_root_hub_connect_handler(&(imxrt_usb_host_obj[USBH0_INDEX].uhcd), OTG_PORT, RT_TRUE);
366         }
367         break;
368 
369     case kUSB_HostEventNotSupported:
370         LOG_D("usb device not supported");
371         break;
372 
373     case kUSB_HostEventEnumerationDone:
374         LOG_D("enumeration done");
375         break;
376 
377     case kUSB_HostEventDetach:
378         if (imxrt_usb_host_obj[USBH0_INDEX].connect_status)
379         {
380             imxrt_usb_host_obj[USBH0_INDEX].connect_status = RT_FALSE;
381             imxrt_usb_host_obj[USBH0_INDEX].device_handle = handle;
382             LOG_D("usb disconnnect");
383             rt_usbh_root_hub_disconnect_handler(&(imxrt_usb_host_obj[USBH0_INDEX].uhcd), OTG_PORT);
384             (void)USB_HostCloseDeviceInterface(handle, NULL);
385         }
386         break;
387 
388     default:
389         break;
390     }
391     return status;
392 }
393 
394 rt_thread_t usbh0_thread;
395 
_ehci0_usbh_thread(void * param)396 static void _ehci0_usbh_thread(void* param)
397 {
398     while (1)
399     {
400         USB_HostEhciTaskFunction(imxrt_usb_host_obj[USBH0_INDEX].host_handle);
401     }
402 }
403 
_ehci0_usbh_init(rt_device_t device)404 static rt_err_t _ehci0_usbh_init(rt_device_t device)
405 {
406     USB_HostClockInit(kUSB_ControllerEhci0);
407 
408     if (kStatus_USB_Success == USB_HostInit(kUSB_ControllerEhci0, &imxrt_usb_host_obj[USBH0_INDEX].host_handle, usb0_host_callback))
409     {
410         usbh0_thread = rt_thread_create("ehci0", _ehci0_usbh_thread, RT_NULL, 500, 4, 9999999);
411         rt_thread_startup(usbh0_thread);
412         USB_HostIsrEnable(kUSB_ControllerEhci0);
413     }
414     else
415     {
416         rt_kprintf("USB_HostInit ehci0 error\r\n");
417         return -RT_ERROR;
418     }
419     return RT_EOK;
420 }
421 #endif
422 
423 #ifdef BSP_USB1_HOST
USB_OTG2_IRQHandler(void)424 void USB_OTG2_IRQHandler(void)
425 {
426     /* enter interrupt */
427     rt_interrupt_enter();
428 
429     USB_HostEhciIsrFunction(imxrt_usb_host_obj[USBH1_INDEX].host_handle);
430     /* leave interrupt */
431     rt_interrupt_leave();
432 }
433 
_ehci1_reset_port(rt_uint8_t port)434 static rt_err_t _ehci1_reset_port(rt_uint8_t port)
435 {
436     // No reset port function available
437     return RT_EOK;
438 }
439 
440 static uint8_t _ehci1_pipe_buf[64];
441 static uint8_t _ehci1_pipe_idx;
442 
_ehci1_pipe_xfer(upipe_t pipe,rt_uint8_t token,void * buffer,int nbytes,int timeouts)443 static int _ehci1_pipe_xfer(upipe_t pipe, rt_uint8_t token, void *buffer, int nbytes, int timeouts)
444 {
445     int timeout = timeouts;
446 
447     if (!imxrt_usb_host_obj[USBH1_INDEX].connect_status)
448     {
449         return -1;
450     }
451     usb_host_transfer_t *transfer;
452     if (imxrt_usb_host_obj[USBH1_INDEX].pipes[pipe->pipe_index].pipe_handle == NULL)
453     {
454         LOG_D("error operation on null pipe");
455         return -1;
456     }
457     if (USB_HostMallocTransfer(imxrt_usb_host_obj[USBH1_INDEX].host_handle, &transfer) != kStatus_USB_Success)
458     {
459         LOG_D("error to get transfer");
460         return -1;
461     }
462     transfer->transferBuffer      = buffer;
463     transfer->transferLength      = nbytes;
464     transfer->transferSofar       = 0;
465     transfer->callbackFn          = _imxrt_usb_host_send_callback;
466     transfer->callbackParam       = &(imxrt_usb_host_obj[USBH1_INDEX].pipes[pipe->pipe_index]);
467     transfer->direction         = (pipe->ep.bEndpointAddress & USB_DIR_IN) ? USB_IN : USB_OUT;
468     if (pipe->ep.bmAttributes == USB_ENDPOINT_CONTROL)
469     {
470         if (token == USBH_PID_SETUP)
471         {
472             struct urequest *setup = (struct urequest *)buffer;
473             transfer->setupStatus = 0;
474             transfer->setupPacket->bmRequestType = setup->request_type;
475             transfer->setupPacket->bRequest = setup->bRequest;
476             transfer->setupPacket->wIndex = setup->wIndex;
477             transfer->setupPacket->wLength = setup->wLength;
478             transfer->setupPacket->wValue = setup->wValue;
479             transfer->transferBuffer    = RT_NULL;
480             transfer->transferLength    = 0;
481             transfer->next = RT_NULL;
482             if ((transfer->setupPacket->bmRequestType & USB_REQUEST_TYPE_DIR_MASK) == USB_REQUEST_TYPE_DIR_IN)
483             {
484                 transfer->direction = USB_IN;
485                 transfer->transferBuffer = _ehci1_pipe_buf;
486                 transfer->transferLength = setup->wLength;
487                 _ehci1_pipe_idx = 0;
488             }
489             else
490             {
491                 transfer->direction = USB_OUT;
492             }
493         }
494         else
495         {
496             rt_memcpy(buffer, _ehci1_pipe_buf + _ehci1_pipe_idx, nbytes);
497             imxrt_usb_host_obj[USBH1_INDEX].pipes[pipe->pipe_index].transfer_status = kStatus_USB_Success;
498             transfer->transferSofar = nbytes;
499             _ehci1_pipe_idx += nbytes;
500             if (_ehci1_pipe_idx >= 64)
501             {
502                 _ehci1_pipe_idx = 0;
503             }
504             goto _ehci1_pipe_xfer_finish;
505         }
506 
507     }
508     rt_completion_init(&(imxrt_usb_host_obj[USBH1_INDEX].pipes[pipe->pipe_index].urb_completion));
509     if (USB_HostEhciWritePipe(((usb_host_instance_t *)imxrt_usb_host_obj[USBH1_INDEX].host_handle)->controllerHandle, imxrt_usb_host_obj[USBH1_INDEX].pipes[pipe->pipe_index].pipe_handle, transfer) != kStatus_USB_Success)
510     {
511         LOG_D("usb host failed to send");
512         (void)USB_HostFreeTransfer(imxrt_usb_host_obj[USBH1_INDEX].host_handle, transfer);
513         return -1;
514     }
515     if (-RT_ETIMEOUT == rt_completion_wait(&(imxrt_usb_host_obj[USBH1_INDEX].pipes[pipe->pipe_index].urb_completion), RT_WAITING_FOREVER))
516     {
517         LOG_D("usb transfer timeout");
518         (void)USB_HostFreeTransfer(imxrt_usb_host_obj[USBH1_INDEX].host_handle, transfer);
519         return -1;
520     }
521     // rt_thread_mdelay(1);
522     _ehci1_pipe_xfer_finish:
523     switch (imxrt_usb_host_obj[USBH1_INDEX].pipes[pipe->pipe_index].transfer_status)
524     {
525     case kStatus_USB_Success:
526     {
527         LOG_D("ok");
528         pipe->status = UPIPE_STATUS_OK;
529         if (pipe->callback != RT_NULL)
530         {
531             pipe->callback(pipe);
532         }
533         size_t size = transfer->transferSofar;
534         (void)USB_HostFreeTransfer(imxrt_usb_host_obj[USBH1_INDEX].host_handle, transfer);
535         if (pipe->ep.bEndpointAddress & 0x80)
536         {
537             return size;
538         }
539         else if (pipe->ep.bEndpointAddress & 0x00)
540         {
541             return size;
542         }
543         return nbytes;
544         break;
545     }
546     case kStatus_USB_TransferStall:
547     {
548         LOG_D("stall");
549         pipe->status = UPIPE_STATUS_STALL;
550         if (pipe->callback != RT_NULL)
551         {
552             pipe->callback(pipe);
553         }
554         (void)USB_HostFreeTransfer(imxrt_usb_host_obj[USBH1_INDEX].host_handle, transfer);
555         return -1;
556         break;
557     }
558     case kStatus_USB_TransferFailed:
559     default:
560     {
561         LOG_D("error");
562         pipe->status = UPIPE_STATUS_ERROR;
563         if (pipe->callback != RT_NULL)
564         {
565             pipe->callback(pipe);
566         }
567         (void)USB_HostFreeTransfer(imxrt_usb_host_obj[USBH1_INDEX].host_handle, transfer);
568         return -1;
569         break;
570     }
571     }
572 }
573 
574 static rt_uint16_t _ehci1_pipe_index = 0;
_ehci1_get_free_pipe_index(void)575 static rt_uint8_t  _ehci1_get_free_pipe_index(void)
576 {
577     rt_uint8_t idx;
578     for (idx = 1; idx < 16; idx++)
579     {
580         if (!(_ehci1_pipe_index & (0x01 << idx)))
581         {
582             _ehci1_pipe_index |= (0x01 << idx);
583             return idx;
584         }
585     }
586     return 0xff;
587 }
588 
_ehci1_free_pipe_index(rt_uint8_t index)589 static void _ehci1_free_pipe_index(rt_uint8_t index)
590 {
591     _ehci1_pipe_index &= ~(0x01 << index);
592 }
593 
_ehci1_open_pipe(upipe_t pipe)594 static rt_err_t _ehci1_open_pipe(upipe_t pipe)
595 {
596     pipe->pipe_index = _ehci1_get_free_pipe_index();
597     if (pipe->pipe_index == 0xFF)
598     {
599         return -RT_ERROR;
600     }
601     usb_host_pipe_init_t pipe_init =
602     {
603         .devInstance = imxrt_usb_host_obj[USBH1_INDEX].device_handle,
604         .pipeType = pipe->ep.bmAttributes,
605         .direction = (pipe->ep.bEndpointAddress & USB_DIR_IN) ? USB_IN : USB_OUT,
606         .endpointAddress = (pipe->ep.bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK),
607         .interval = pipe->ep.bInterval,
608         .maxPacketSize = (uint16_t)(pipe->ep.wMaxPacketSize & USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK),
609         .numberPerUframe = (uint8_t)(pipe->ep.wMaxPacketSize & USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_MASK),
610         .nakCount = USB_HOST_CONFIG_MAX_NAK,
611     };
612     USB_HostOpenPipe(imxrt_usb_host_obj[USBH1_INDEX].host_handle, &imxrt_usb_host_obj[USBH1_INDEX].pipes[pipe->pipe_index].pipe_handle, &pipe_init);
613     return RT_EOK;
614 }
615 
_ehci1_close_pipe(upipe_t pipe)616 static rt_err_t _ehci1_close_pipe(upipe_t pipe)
617 {
618     (void)USB_HostClosePipe(imxrt_usb_host_obj[USBH1_INDEX].host_handle, imxrt_usb_host_obj[USBH1_INDEX].pipes[pipe->pipe_index].pipe_handle);
619     _ehci1_free_pipe_index(pipe->pipe_index);
620     return RT_EOK;
621 }
622 
623 static struct uhcd_ops _ehci1_uhcd_ops =
624 {
625     _ehci1_reset_port,
626     _ehci1_pipe_xfer,
627     _ehci1_open_pipe,
628     _ehci1_close_pipe,
629 };
630 
usb1_host_callback(usb_device_handle handle,usb_host_configuration_handle config_handle,rt_uint32_t event_code)631 static usb_status_t usb1_host_callback(usb_device_handle handle, usb_host_configuration_handle config_handle, rt_uint32_t event_code)
632 {
633     usb_status_t status = kStatus_USB_Success;
634 
635     switch (event_code)
636     {
637     case kUSB_HostEventAttach:
638         if (!imxrt_usb_host_obj[USBH1_INDEX].connect_status)
639         {
640             imxrt_usb_host_obj[USBH1_INDEX].connect_status = RT_TRUE;
641             imxrt_usb_host_obj[USBH1_INDEX].device_handle = handle;
642             LOG_D("usb connected");
643             rt_usbh_root_hub_connect_handler(&(imxrt_usb_host_obj[USBH1_INDEX].uhcd), OTG_PORT, RT_TRUE);
644         }
645         break;
646 
647     case kUSB_HostEventNotSupported:
648         LOG_D("usb device not supported");
649         break;
650 
651     case kUSB_HostEventEnumerationDone:
652         LOG_D("enumeration done");
653         break;
654 
655     case kUSB_HostEventDetach:
656         if (imxrt_usb_host_obj[USBH1_INDEX].connect_status)
657         {
658             imxrt_usb_host_obj[USBH1_INDEX].connect_status = RT_FALSE;
659             imxrt_usb_host_obj[USBH1_INDEX].device_handle = handle;
660             LOG_D("usb disconnnect");
661             rt_usbh_root_hub_disconnect_handler(&(imxrt_usb_host_obj[USBH1_INDEX].uhcd), OTG_PORT);
662             (void)USB_HostCloseDeviceInterface(handle, NULL);
663         }
664         break;
665 
666     default:
667         break;
668     }
669     return status;
670 }
671 
672 rt_thread_t usbh1_thread;
673 
_ehci1_usbh_thread(void * param)674 static void _ehci1_usbh_thread(void* param)
675 {
676     while (1)
677     {
678         USB_HostEhciTaskFunction(imxrt_usb_host_obj[USBH1_INDEX].host_handle);
679     }
680 }
681 
_ehci1_usbh_init(rt_device_t device)682 static rt_err_t _ehci1_usbh_init(rt_device_t device)
683 {
684     USB_HostClockInit(kUSB_ControllerEhci1);
685 
686     if (kStatus_USB_Success == USB_HostInit(kUSB_ControllerEhci1, &imxrt_usb_host_obj[USBH1_INDEX].host_handle, usb1_host_callback))
687     {
688         usbh1_thread = rt_thread_create("ehci1", _ehci1_usbh_thread, RT_NULL, 500, 4, 9999999);
689         rt_thread_startup(usbh1_thread);
690         USB_HostIsrEnable(kUSB_ControllerEhci1);
691     }
692     else
693     {
694         rt_kprintf("USB_HostInit ehci1 error\r\n");
695         return -RT_ERROR;
696     }
697     return RT_EOK;
698 }
699 #endif
700 
imxrt_usbh_register(void)701 int imxrt_usbh_register(void)
702 {
703     rt_err_t res = -RT_ERROR;
704     struct imxrt_usb_host *usb_host_obj;
705 
706 #ifdef BSP_USB0_HOST
707     usb_host_obj = &(imxrt_usb_host_obj[USBH0_INDEX]);
708     rt_memset((void *)(&(usb_host_obj->uhcd)), 0, sizeof(struct uhcd));
709     usb_host_obj->uhcd.parent.type = RT_Device_Class_USBHost;
710     usb_host_obj->uhcd.parent.init = _ehci0_usbh_init;
711     usb_host_obj->uhcd.parent.user_data = usb_host_obj;
712     usb_host_obj->uhcd.ops = &_ehci0_uhcd_ops;
713     usb_host_obj->uhcd.num_ports = OTG_PORT;
714     res = rt_device_register(&(usb_host_obj->uhcd.parent), usb_host_obj->name, RT_DEVICE_FLAG_DEACTIVATE);
715     if (res != RT_EOK)
716     {
717         rt_kprintf("register usb0 host failed res = %d\r\n", res);
718         return -RT_ERROR;
719     }
720 
721     rt_usb_host_init(usb_host_obj->name);
722 #endif
723 #ifdef BSP_USB1_HOST
724     usb_host_obj = &(imxrt_usb_host_obj[USBH1_INDEX]);
725     rt_memset((void *)(&(usb_host_obj->uhcd)), 0, sizeof(struct uhcd));
726     usb_host_obj->uhcd.parent.type = RT_Device_Class_USBHost;
727     usb_host_obj->uhcd.parent.init = _ehci1_usbh_init;
728     usb_host_obj->uhcd.parent.user_data = usb_host_obj;
729     usb_host_obj->uhcd.ops = &_ehci1_uhcd_ops;
730     usb_host_obj->uhcd.num_ports = OTG_PORT;
731     res = rt_device_register(&(usb_host_obj->uhcd.parent), usb_host_obj->name, RT_DEVICE_FLAG_DEACTIVATE);
732     if (res != RT_EOK)
733     {
734         rt_kprintf("register usb0 host failed res = %d\r\n", res);
735         return -RT_ERROR;
736     }
737 
738     rt_usb_host_init(usb_host_obj->name);
739 #endif
740     return RT_EOK;
741 }
742 INIT_DEVICE_EXPORT(imxrt_usbh_register);
743 
744 #endif
745