drv_usbh.c 23 KB

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