drv_usbhost.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956
  1. /**************************************************************************//**
  2. *
  3. * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0
  6. *
  7. * Change Logs:
  8. * Date Author Notes
  9. * 2020-12-30 Wayne First version
  10. *
  11. ******************************************************************************/
  12. #include <rtconfig.h>
  13. #if defined(BSP_USING_USBH)
  14. #include <rtdevice.h>
  15. #include <rthw.h>
  16. #include "NuMicro.h"
  17. #include "usb.h"
  18. #include "usbh_lib.h"
  19. #if !defined(NU_USBHOST_HUB_POLLING_INTERVAL)
  20. #define NU_USBHOST_HUB_POLLING_INTERVAL (100)
  21. #endif
  22. #define NU_MAX_USBH_PORT 2 //2* USB2.0 port
  23. #define NU_MAX_USBH_PIPE 16
  24. #define NU_USBH_THREAD_STACK_SIZE 2048
  25. #define NU_MAX_USBH_HUB_PORT_DEV USB_HUB_PORT_NUM
  26. #define NU_USBHOST_MUTEX_INIT() { \
  27. s_sUSBHDev.lock = rt_mutex_create("usbhost_lock", RT_IPC_FLAG_PRIO); \
  28. RT_ASSERT(s_sUSBHDev.lock != RT_NULL); \
  29. }
  30. #define NU_USBHOST_LOCK() { \
  31. rt_err_t result = rt_mutex_take(s_sUSBHDev.lock, RT_WAITING_FOREVER); \
  32. RT_ASSERT(result == RT_EOK); \
  33. }
  34. #define NU_USBHOST_UNLOCK() { \
  35. rt_err_t result = rt_mutex_release(s_sUSBHDev.lock); \
  36. RT_ASSERT(result == RT_EOK); \
  37. }
  38. /* Private typedef --------------------------------------------------------------*/
  39. typedef struct nu_port_dev
  40. {
  41. rt_bool_t bRHParent;
  42. UDEV_T *pUDev;
  43. EP_INFO_T *apsEPInfo[NU_MAX_USBH_PIPE];
  44. struct urequest asSetupReq[NU_MAX_USBH_PIPE];
  45. struct rt_completion utr_completion;
  46. int port_num;
  47. rt_bool_t bEnumDone;
  48. #if defined(BSP_USING_MMU)
  49. void *asPipePktBuf[NU_MAX_USBH_PIPE];
  50. #endif
  51. } S_NU_PORT_DEV;
  52. typedef struct nu_port_ctrl
  53. {
  54. S_NU_PORT_DEV sRHPortDev;
  55. S_NU_PORT_DEV asHubPortDev[NU_MAX_USBH_HUB_PORT_DEV];
  56. } S_NU_RH_PORT_CTRL;
  57. struct nu_usbh_dev
  58. {
  59. struct uhcd uhcd;
  60. E_SYS_IPRST rstidx;
  61. E_SYS_IPCLK clkidx;
  62. rt_thread_t polling_thread;
  63. rt_mutex_t lock;
  64. S_NU_RH_PORT_CTRL asPortCtrl[NU_MAX_USBH_PORT];
  65. };
  66. /* Private variables ------------------------------------------------------------*/
  67. static struct nu_usbh_dev s_sUSBHDev =
  68. {
  69. .rstidx = USBHRST,
  70. .clkidx = USBHCKEN,
  71. };
  72. static S_NU_RH_PORT_CTRL *
  73. GetRHPortControlFromPipe(
  74. upipe_t pipe)
  75. {
  76. uinst_t inst;
  77. int port;
  78. if (pipe->inst->parent_hub->is_roothub)
  79. {
  80. //case: device ---> root hub
  81. inst = pipe->inst;
  82. port = inst->port;
  83. }
  84. else
  85. {
  86. //case: device ---> hub ---> root hub
  87. inst = pipe->inst->parent_hub->self;
  88. port = inst->port;
  89. }
  90. if (port > NU_MAX_USBH_PORT)
  91. {
  92. RT_DEBUG_LOG(RT_DEBUG_USB, ("nu_open_pipe ERROR: port index over NU_MAX_USBH_PORT\n"));
  93. return RT_NULL;
  94. }
  95. return &s_sUSBHDev.asPortCtrl[port - 1];;
  96. }
  97. static S_NU_PORT_DEV *
  98. GetPortDevFromPipe(
  99. upipe_t pipe)
  100. {
  101. S_NU_RH_PORT_CTRL *psRHPortCtrl = GetRHPortControlFromPipe(pipe);
  102. int i;
  103. if (psRHPortCtrl == RT_NULL)
  104. return RT_NULL;
  105. if (pipe->inst->parent_hub->is_roothub)
  106. {
  107. //case: device ---> root hub
  108. return &psRHPortCtrl->sRHPortDev;
  109. }
  110. //case: device ---> hub ---> root hub
  111. for (i = 0 ; i < NU_MAX_USBH_HUB_PORT_DEV; i ++)
  112. {
  113. if (psRHPortCtrl->asHubPortDev[i].port_num == pipe->inst->port)
  114. break;
  115. }
  116. if (i >= NU_MAX_USBH_HUB_PORT_DEV)
  117. return RT_NULL;
  118. return &psRHPortCtrl->asHubPortDev[i];
  119. }
  120. static rt_err_t nu_reset_port(rt_uint8_t port)
  121. {
  122. S_NU_RH_PORT_CTRL *psPortCtrl;
  123. if (port > NU_MAX_USBH_PORT)
  124. {
  125. RT_DEBUG_LOG(RT_DEBUG_USB, ("%s ERROR: port index over NU_MAX_USBH_PORT\n", __func__));
  126. return RT_EIO;
  127. }
  128. psPortCtrl = &s_sUSBHDev.asPortCtrl[port - 1];
  129. if (psPortCtrl->sRHPortDev.pUDev == NULL)
  130. {
  131. RT_DEBUG_LOG(RT_DEBUG_USB, ("%s ERROR: udev not found\n", __func__));
  132. return RT_EIO;
  133. }
  134. usbh_reset_port(psPortCtrl->sRHPortDev.pUDev);
  135. return RT_EOK;
  136. }
  137. static EP_INFO_T *GetFreePipe(
  138. S_NU_RH_PORT_CTRL *psPortCtrl,
  139. S_NU_PORT_DEV *psPortDev,
  140. rt_uint8_t *pu8PipeIndex)
  141. {
  142. if (psPortCtrl != NULL)
  143. {
  144. int i;
  145. /* Find free Pipe */
  146. for (i = 0; i < NU_MAX_USBH_PIPE; i ++)
  147. {
  148. if (psPortDev->apsEPInfo[i] == NULL)
  149. break;
  150. }
  151. if (i < NU_MAX_USBH_PIPE)
  152. {
  153. EP_INFO_T *psEPInfo = (EP_INFO_T *)rt_malloc_align(sizeof(EP_INFO_T), CACHE_LINE_SIZE);
  154. if (psEPInfo != RT_NULL)
  155. {
  156. #if defined(BSP_USING_MMU)
  157. psPortDev->apsEPInfo[i] = (EP_INFO_T *)((uint32_t)psEPInfo | NON_CACHE_MASK);
  158. #else
  159. psPortDev->apsEPInfo[i] = psEPInfo;
  160. #endif
  161. *pu8PipeIndex = i;
  162. return psPortDev->apsEPInfo[i];
  163. }
  164. }
  165. }
  166. return RT_NULL;
  167. }
  168. static void FreePipe(
  169. S_NU_RH_PORT_CTRL *psPortCtrl,
  170. S_NU_PORT_DEV *psPortDev,
  171. rt_uint8_t u8PipeIndex)
  172. {
  173. if ((psPortCtrl != RT_NULL) &&
  174. (u8PipeIndex < NU_MAX_USBH_PIPE) &&
  175. (psPortDev->apsEPInfo[u8PipeIndex] != RT_NULL))
  176. {
  177. EP_INFO_T *psEPInfo = psPortDev->apsEPInfo[u8PipeIndex];
  178. #if defined(BSP_USING_MMU)
  179. psEPInfo = (EP_INFO_T *)((uint32_t)psEPInfo & ~NON_CACHE_MASK);
  180. #endif
  181. rt_free_align(psEPInfo);
  182. psPortDev->apsEPInfo[u8PipeIndex] = RT_NULL;
  183. }
  184. }
  185. static S_NU_PORT_DEV *
  186. AllocateNewUDev(
  187. S_NU_RH_PORT_CTRL *psRHPortCtrl)
  188. {
  189. if (psRHPortCtrl != RT_NULL)
  190. {
  191. int i;
  192. /* Find free Dev */
  193. for (i = 0 ; i < NU_MAX_USBH_HUB_PORT_DEV; i ++)
  194. {
  195. if (psRHPortCtrl->asHubPortDev[i].pUDev == NULL)
  196. break;
  197. }
  198. if (i < NU_MAX_USBH_HUB_PORT_DEV)
  199. {
  200. psRHPortCtrl->asHubPortDev[i].pUDev = alloc_device();
  201. if (psRHPortCtrl->asHubPortDev[i].pUDev == NULL)
  202. {
  203. return RT_NULL;
  204. }
  205. else
  206. {
  207. return &psRHPortCtrl->asHubPortDev[i];
  208. }
  209. }
  210. }
  211. return RT_NULL;
  212. }
  213. static rt_err_t nu_open_pipe(upipe_t pipe)
  214. {
  215. S_NU_RH_PORT_CTRL *psPortCtrl;
  216. S_NU_PORT_DEV *psPortDev;
  217. psPortCtrl = GetRHPortControlFromPipe(pipe);
  218. if (psPortCtrl == RT_NULL)
  219. {
  220. RT_DEBUG_LOG(RT_DEBUG_USB, ("%s ERROR: RHPort not found\n", __func__));
  221. goto exit_nu_open_pipe;
  222. }
  223. if (psPortCtrl->sRHPortDev.pUDev == NULL)
  224. {
  225. RT_DEBUG_LOG(RT_DEBUG_USB, ("%s ERROR: udev not found\n", __func__));
  226. goto exit_nu_open_pipe;
  227. }
  228. psPortDev = GetPortDevFromPipe(pipe);
  229. if ((psPortDev == NULL) || (psPortDev->pUDev == NULL))
  230. {
  231. //allocate new dev for hub device
  232. psPortDev = AllocateNewUDev(psPortCtrl);
  233. if (psPortDev == RT_NULL)
  234. {
  235. RT_DEBUG_LOG(RT_DEBUG_USB, ("nu_open_pipe ERROR: udev allocate failed\n"));
  236. goto exit_nu_open_pipe;
  237. }
  238. if (pipe->inst->speed)
  239. {
  240. psPortDev->pUDev->speed = SPEED_FULL;
  241. }
  242. else
  243. {
  244. psPortDev->pUDev->speed = SPEED_HIGH;
  245. }
  246. psPortDev->pUDev->parent = NULL;
  247. psPortDev->pUDev->hc_driver = psPortCtrl->sRHPortDev.pUDev->hc_driver;
  248. psPortDev->port_num = pipe->inst->port;
  249. psPortDev->pUDev->port_num = pipe->inst->port;
  250. psPortDev->bEnumDone = FALSE;
  251. }
  252. //For ep0 control transfer
  253. if ((pipe->ep.bEndpointAddress & 0x7F) == 0)
  254. {
  255. pipe->pipe_index = 0;
  256. }
  257. else
  258. {
  259. int pksz;
  260. EP_INFO_T *psEPInfo = GetFreePipe(psPortCtrl, psPortDev, &pipe->pipe_index);
  261. if (psEPInfo == RT_NULL)
  262. {
  263. RT_DEBUG_LOG(RT_DEBUG_USB, ("%s ERROR: get free pipe failed\n", __func__));
  264. goto exit_nu_open_pipe;
  265. }
  266. psEPInfo->bEndpointAddress = pipe->ep.bEndpointAddress;
  267. psEPInfo->bmAttributes = pipe->ep.bmAttributes;
  268. pksz = pipe->ep.wMaxPacketSize;
  269. pksz = (pksz & 0x07ff) * (1 + ((pksz >> 11) & 3));
  270. psEPInfo->wMaxPacketSize = pksz;
  271. psEPInfo->bInterval = pipe->ep.bInterval;
  272. psEPInfo->hw_pipe = NULL;
  273. psEPInfo->bToggle = 0;
  274. }
  275. #if defined(BSP_USING_MMU)
  276. if (!psPortDev->asPipePktBuf[pipe->pipe_index])
  277. {
  278. void *paddr = rt_malloc_align(512ul, CACHE_LINE_SIZE);
  279. RT_ASSERT(paddr != RT_NULL);
  280. psPortDev->asPipePktBuf[pipe->pipe_index] = (void *)((uint32_t)paddr | NON_CACHE_MASK);
  281. }
  282. #endif
  283. return RT_EOK;
  284. exit_nu_open_pipe:
  285. return -RT_ERROR;
  286. }
  287. static rt_err_t nu_close_pipe(upipe_t pipe)
  288. {
  289. S_NU_RH_PORT_CTRL *psPortCtrl;
  290. S_NU_PORT_DEV *psPortDev;
  291. psPortCtrl = GetRHPortControlFromPipe(pipe);
  292. if (psPortCtrl == RT_NULL)
  293. {
  294. return RT_EIO;
  295. }
  296. psPortDev = GetPortDevFromPipe(pipe);
  297. //For ep0 control transfer
  298. if ((pipe->ep.bEndpointAddress & 0x7F) == 0)
  299. {
  300. if ((psPortDev) && (psPortDev->bRHParent == FALSE) && (psPortDev->bEnumDone == TRUE))
  301. {
  302. if (psPortDev->pUDev)
  303. {
  304. int i;
  305. for (i = 0; i < NU_MAX_USBH_PIPE; i++)
  306. {
  307. if (psPortDev->apsEPInfo[i] != NULL)
  308. {
  309. usbh_quit_xfer(psPortDev->pUDev, psPortDev->apsEPInfo[i]);
  310. }
  311. }
  312. free_device(psPortDev->pUDev);
  313. psPortDev->pUDev = NULL;
  314. }
  315. }
  316. }
  317. if (psPortDev != NULL)
  318. {
  319. #if defined(BSP_USING_MMU)
  320. if (psPortDev->asPipePktBuf[pipe->pipe_index])
  321. {
  322. void *paddr = psPortDev->asPipePktBuf[pipe->pipe_index];
  323. paddr = (void *)((uint32_t)paddr & ~NON_CACHE_MASK);
  324. rt_free_align(paddr);
  325. psPortDev->asPipePktBuf[pipe->pipe_index] = RT_NULL;
  326. }
  327. #endif
  328. FreePipe(psPortCtrl, psPortDev, pipe->pipe_index);
  329. }
  330. return RT_EOK;
  331. }
  332. static int nu_ctrl_xfer(
  333. S_NU_PORT_DEV *psPortDev,
  334. struct urequest *psSetup,
  335. void *buffer,
  336. int timeouts)
  337. {
  338. uint32_t xfer_len = 0;
  339. int ret;
  340. ret = usbh_ctrl_xfer(psPortDev->pUDev, psSetup->request_type, psSetup->bRequest, psSetup->wValue, psSetup->wIndex, psSetup->wLength, buffer, &xfer_len, timeouts * 10);
  341. if (ret < 0)
  342. {
  343. RT_DEBUG_LOG(RT_DEBUG_USB, ("nu_ctrl_xfer ERROR: xfer failed %d\n", ret));
  344. return ret;
  345. }
  346. if (xfer_len != psSetup->wLength)
  347. {
  348. RT_DEBUG_LOG(RT_DEBUG_USB, ("nu_ctrl_xfer ERROR: xfer length %d %d\n", psSetup->wLength, xfer_len));
  349. }
  350. if ((psSetup->bRequest == USB_REQ_SET_ADDRESS) && ((psSetup->request_type & 0x60) == REQ_TYPE_STD_DEV))
  351. psPortDev->pUDev->dev_num = psSetup->wValue;
  352. if ((psSetup->bRequest == USB_REQ_SET_CONFIGURATION) && ((psSetup->request_type & 0x60) == REQ_TYPE_STD_DEV))
  353. {
  354. psPortDev->pUDev->cur_conf = psSetup->wValue;
  355. psPortDev->bEnumDone = TRUE;
  356. }
  357. return xfer_len;
  358. }
  359. static int nu_bulk_xfer(
  360. S_NU_PORT_DEV *psPortDev,
  361. UTR_T *psUTR,
  362. int timeouts)
  363. {
  364. #define TIMEOUT_RETRY 3
  365. int retry = TIMEOUT_RETRY;
  366. int ret = usbh_bulk_xfer(psUTR);
  367. if (ret < 0)
  368. {
  369. rt_kprintf("usbh_bulk_xfer %x\n", ret);
  370. return ret;
  371. }
  372. while (retry > 0)
  373. {
  374. if (rt_completion_wait(&(psPortDev->utr_completion), timeouts) != 0)
  375. {
  376. rt_uint32_t level;
  377. rt_kprintf("Request %d Timeout in %d ms!!\n", psUTR->data_len, timeouts);
  378. rt_completion_init(&(psPortDev->utr_completion));
  379. rt_thread_mdelay(1);
  380. // Workaround: To fix timeout case, this way is traveling qh's linking-list again.
  381. level = rt_hw_interrupt_disable();
  382. extern void scan_asynchronous_list();
  383. extern void iaad_remove_qh();
  384. scan_asynchronous_list();
  385. iaad_remove_qh();
  386. rt_hw_interrupt_enable(level);
  387. }
  388. else
  389. break;
  390. retry--;
  391. }
  392. return (retry > 0) ? 0 : -1;
  393. }
  394. static int nu_int_xfer(
  395. upipe_t pipe,
  396. S_NU_PORT_DEV *psPortDev,
  397. UTR_T *psUTR,
  398. int timeouts)
  399. {
  400. int ret;
  401. int retry = 3;
  402. while (retry > 0)
  403. {
  404. ret = usbh_int_xfer(psUTR);
  405. if (ret == 0)
  406. break;
  407. RT_DEBUG_LOG(RT_DEBUG_USB, ("nu_int_xfer ERROR: failed to submit interrupt request\n"));
  408. rt_thread_delay((pipe->ep.bInterval * RT_TICK_PER_SECOND / 1000) > 0 ? (pipe->ep.bInterval * RT_TICK_PER_SECOND / 1000) : 1);
  409. retry --;
  410. }
  411. if (ret < 0)
  412. return ret;
  413. return 0;
  414. }
  415. static void xfer_done_cb(UTR_T *psUTR)
  416. {
  417. S_NU_PORT_DEV *psPortDev = (S_NU_PORT_DEV *)psUTR->context;
  418. //transfer done, signal utr_completion
  419. rt_completion_done(&(psPortDev->utr_completion));
  420. }
  421. static void int_xfer_done_cb(UTR_T *psUTR)
  422. {
  423. upipe_t pipe = (upipe_t)psUTR->context;
  424. if (psUTR->status != 0)
  425. {
  426. RT_DEBUG_LOG(RT_DEBUG_USB, ("Interrupt xfer failed %d\n", psUTR->status));
  427. goto exit_int_xfer_done_cb;
  428. }
  429. if (pipe->callback != RT_NULL)
  430. {
  431. struct uhost_msg msg;
  432. msg.type = USB_MSG_CALLBACK;
  433. msg.content.cb.function = pipe->callback;
  434. msg.content.cb.context = pipe;
  435. rt_usbh_event_signal(&s_sUSBHDev.uhcd, &msg);
  436. }
  437. exit_int_xfer_done_cb:
  438. free_utr(psUTR);
  439. }
  440. static int nu_pipe_xfer(upipe_t pipe, rt_uint8_t token, void *buffer, int nbytes, int timeouts)
  441. {
  442. S_NU_RH_PORT_CTRL *psPortCtrl;
  443. S_NU_PORT_DEV *psPortDev;
  444. UTR_T *psUTR = NULL;
  445. int i32XferLen = -1;
  446. void *buffer_nonch = buffer;
  447. NU_USBHOST_LOCK();
  448. psPortCtrl = GetRHPortControlFromPipe(pipe);
  449. if (psPortCtrl == RT_NULL)
  450. {
  451. goto exit_nu_pipe_xfer;
  452. }
  453. psPortDev = GetPortDevFromPipe(pipe);
  454. if (psPortDev->pUDev == NULL)
  455. {
  456. RT_DEBUG_LOG(RT_DEBUG_USB, ("nu_pipe_xfer ERROR: udev not found\n"));
  457. goto exit_nu_pipe_xfer;
  458. }
  459. #if defined(BSP_USING_MMU)
  460. if (buffer_nonch && nbytes)
  461. {
  462. buffer_nonch = psPortDev->asPipePktBuf[pipe->pipe_index];
  463. if ((pipe->ep.bEndpointAddress & USB_DIR_MASK) == USB_DIR_OUT)
  464. {
  465. rt_memcpy(buffer_nonch, buffer, nbytes);
  466. }
  467. }
  468. #endif
  469. //ctrl xfer
  470. if (pipe->ep.bmAttributes == USB_EP_ATTR_CONTROL)
  471. {
  472. int ret;
  473. if (token == USBH_PID_SETUP)
  474. {
  475. struct urequest *psSetup = (struct urequest *)buffer_nonch;
  476. RT_ASSERT(buffer_nonch != RT_NULL);
  477. /* Read data from USB device. */
  478. if (psSetup->request_type & USB_REQ_TYPE_DIR_IN)
  479. {
  480. //Store setup request
  481. rt_memcpy(&psPortCtrl->asHubPortDev->asSetupReq[pipe->pipe_index], psSetup, sizeof(struct urequest));
  482. }
  483. else
  484. {
  485. /* Write data to USB device. */
  486. //Trigger USBHostLib Ctrl_Xfer
  487. ret = nu_ctrl_xfer(psPortDev, psSetup, NULL, timeouts);
  488. if (ret != psSetup->wLength)
  489. goto exit_nu_pipe_xfer;
  490. }
  491. }
  492. else
  493. {
  494. //token == USBH_PID_DATA
  495. if (buffer_nonch && ((pipe->ep.bEndpointAddress & USB_DIR_MASK) == USB_DIR_IN))
  496. {
  497. /* Read data from USB device. */
  498. //Trigger USBHostLib Ctril_Xfer
  499. ret = nu_ctrl_xfer(psPortDev, &psPortCtrl->asHubPortDev->asSetupReq[pipe->pipe_index], buffer_nonch, timeouts);
  500. if (ret != nbytes)
  501. goto exit_nu_pipe_xfer;
  502. }
  503. else
  504. {
  505. RT_DEBUG_LOG(RT_DEBUG_USB, ("%d == USBH_PID_DATA, nil buf-%d \n", token, nbytes));
  506. }
  507. } //else
  508. i32XferLen = nbytes;
  509. goto exit_nu_pipe_xfer;
  510. } // if ( pipe->ep.bmAttributes == USB_EP_ATTR_CONTROL )
  511. else
  512. {
  513. psUTR = alloc_utr(psPortDev->pUDev);
  514. if (!psUTR)
  515. {
  516. RT_DEBUG_LOG(RT_DEBUG_USB, ("nu_pipe_xfer ERROR: unable alloc UTR\n"));
  517. goto exit_nu_pipe_xfer;
  518. }
  519. psUTR->ep = psPortDev->apsEPInfo[pipe->pipe_index];
  520. psUTR->buff = buffer_nonch;
  521. psUTR->data_len = nbytes;
  522. psUTR->xfer_len = 0;
  523. psUTR->func = xfer_done_cb;
  524. psUTR->context = psPortDev;
  525. psUTR->bIsTransferDone = 0;
  526. psUTR->status = 0;
  527. //others xfer
  528. rt_completion_init(&(psPortDev->utr_completion));
  529. if (pipe->ep.bmAttributes == USB_EP_ATTR_BULK)
  530. {
  531. if (nu_bulk_xfer(psPortDev, psUTR, timeouts) < 0)
  532. {
  533. RT_DEBUG_LOG(RT_DEBUG_USB, ("nu_pipe_xfer ERROR: bulk transfer failed\n"));
  534. goto failreport_nu_pipe_xfer;
  535. }
  536. }
  537. else if (pipe->ep.bmAttributes == USB_EP_ATTR_INT)
  538. {
  539. psUTR->func = int_xfer_done_cb;
  540. psUTR->context = pipe;
  541. if (nu_int_xfer(pipe, psPortDev, psUTR, timeouts) < 0)
  542. {
  543. RT_DEBUG_LOG(RT_DEBUG_USB, ("nu_pipe_xfer ERROR: int transfer failed\n"));
  544. //goto exit_nu_pipe_xfer;
  545. }
  546. else
  547. {
  548. i32XferLen = nbytes;
  549. }
  550. goto exit2_nu_pipe_xfer;
  551. }
  552. else if (pipe->ep.bmAttributes == USB_EP_ATTR_ISOC)
  553. {
  554. //TODO: ISO transfer
  555. RT_DEBUG_LOG(RT_DEBUG_USB, ("nu_pipe_xfer ERROR: isoc transfer not support\n"));
  556. goto exit_nu_pipe_xfer;
  557. }
  558. } //else
  559. failreport_nu_pipe_xfer:
  560. if (psUTR->bIsTransferDone == 0)
  561. {
  562. //Timeout
  563. RT_DEBUG_LOG(RT_DEBUG_USB, ("nu_pipe_xfer ERROR: timeout\n"));
  564. pipe->status = UPIPE_STATUS_ERROR;
  565. usbh_quit_utr(psUTR);
  566. }
  567. else
  568. {
  569. // Transfer Done. Get status
  570. if (psUTR->status == 0)
  571. {
  572. pipe->status = UPIPE_STATUS_OK;
  573. }
  574. else if (psUTR->status == USBH_ERR_STALL)
  575. {
  576. pipe->status = UPIPE_STATUS_STALL;
  577. }
  578. else
  579. {
  580. pipe->status = UPIPE_STATUS_ERROR;
  581. }
  582. }
  583. i32XferLen = psUTR->xfer_len;
  584. //Call callback
  585. if (pipe->callback != RT_NULL)
  586. {
  587. pipe->callback(pipe);
  588. }
  589. exit_nu_pipe_xfer:
  590. if (psUTR)
  591. free_utr(psUTR);
  592. exit2_nu_pipe_xfer:
  593. #if defined(BSP_USING_MMU)
  594. if ((nbytes) &&
  595. (buffer_nonch != buffer))
  596. {
  597. if ((pipe->ep.bEndpointAddress & USB_DIR_MASK) == USB_DIR_IN)
  598. {
  599. rt_memcpy(buffer, buffer_nonch, nbytes);
  600. }
  601. }
  602. #endif
  603. NU_USBHOST_UNLOCK();
  604. return i32XferLen;
  605. }
  606. /* Polling USB root hub status task */
  607. static void nu_usbh_rh_thread_entry(void *parameter)
  608. {
  609. while (1)
  610. {
  611. NU_USBHOST_LOCK();
  612. usbh_polling_root_hubs();
  613. NU_USBHOST_UNLOCK();
  614. rt_thread_mdelay(NU_USBHOST_HUB_POLLING_INTERVAL);
  615. }
  616. }
  617. static void nu_hcd_connect_callback(
  618. struct udev_t *udev,
  619. int param)
  620. {
  621. int i;
  622. int port_index;
  623. S_NU_RH_PORT_CTRL *psPortCtrl;
  624. /* Igrone event if role is USBD*/
  625. if (nu_sys_usb0_role() == USB0_ID_HOST)
  626. {
  627. SYS_UnlockReg();
  628. outpw(REG_SYS_MISCFCR, (inpw(REG_SYS_MISCFCR) | (1 << 11))); /* Set USRHDSEN as 1; USB host/device role selection decided by USBID (SYS_PWRON[16]) */
  629. outpw(REG_SYS_PWRON, (inpw(REG_SYS_PWRON) | (1 << 16))); /* Set USB port 0 used for Host */
  630. SYS_LockReg();
  631. }
  632. for (i = 0; i < NU_MAX_USBH_PORT; i++)
  633. {
  634. psPortCtrl = &s_sUSBHDev.asPortCtrl[i];
  635. if (psPortCtrl->sRHPortDev.pUDev == NULL)
  636. break;
  637. }
  638. if (i >= NU_MAX_USBH_PORT)
  639. {
  640. RT_DEBUG_LOG(RT_DEBUG_USB, ("ERROR: port connect slot is full\n"));
  641. return;
  642. }
  643. port_index = i + 1;
  644. psPortCtrl->sRHPortDev.pUDev = udev;
  645. psPortCtrl->sRHPortDev.bRHParent = TRUE;
  646. RT_DEBUG_LOG(RT_DEBUG_USB, ("usb connected\n"));
  647. if (udev->speed == SPEED_HIGH)
  648. rt_usbh_root_hub_connect_handler(&s_sUSBHDev.uhcd, port_index, RT_TRUE);
  649. else
  650. rt_usbh_root_hub_connect_handler(&s_sUSBHDev.uhcd, port_index, RT_FALSE);
  651. }
  652. static void nu_hcd_disconnect_callback(
  653. struct udev_t *udev,
  654. int param)
  655. {
  656. int i;
  657. int port_index;
  658. S_NU_RH_PORT_CTRL *psPortCtrl;
  659. for (i = 0; i < NU_MAX_USBH_PORT; i++)
  660. {
  661. psPortCtrl = &s_sUSBHDev.asPortCtrl[i];
  662. if (psPortCtrl->sRHPortDev.pUDev == udev)
  663. break;
  664. }
  665. if (i >= NU_MAX_USBH_PORT)
  666. {
  667. RT_DEBUG_LOG(RT_DEBUG_USB, ("ERROR: udev not found\n"));
  668. return;
  669. }
  670. port_index = i + 1;
  671. for (i = 0; i < NU_MAX_USBH_PIPE; i++)
  672. {
  673. if (psPortCtrl->sRHPortDev.apsEPInfo[i] != NULL)
  674. {
  675. usbh_quit_xfer(psPortCtrl->sRHPortDev.pUDev, psPortCtrl->sRHPortDev.apsEPInfo[i]);
  676. }
  677. }
  678. psPortCtrl->sRHPortDev.pUDev = NULL;
  679. RT_DEBUG_LOG(RT_DEBUG_USB, ("usb disconnect\n"));
  680. rt_usbh_root_hub_disconnect_handler(&s_sUSBHDev.uhcd, port_index);
  681. if (nu_sys_usb0_role() != USB0_ID_HOST)
  682. {
  683. SYS_UnlockReg();
  684. outpw(REG_SYS_MISCFCR, (inpw(REG_SYS_MISCFCR) & (~(1 << 11))));
  685. outpw(REG_SYS_PWRON, (inpw(REG_SYS_PWRON) & (~(1 << 16))));
  686. SYS_LockReg();
  687. }
  688. }
  689. /* USB host operations -----------------------------------------------------------*/
  690. static struct uhcd_ops nu_uhcd_ops =
  691. {
  692. nu_reset_port,
  693. nu_pipe_xfer,
  694. nu_open_pipe,
  695. nu_close_pipe,
  696. };
  697. static rt_err_t nu_hcd_init(rt_device_t device)
  698. {
  699. struct nu_usbh_dev *pNuUSBHDev = (struct nu_usbh_dev *)device;
  700. usbh_core_init();
  701. //install connect/disconnect callback
  702. usbh_install_conn_callback(nu_hcd_connect_callback, nu_hcd_disconnect_callback);
  703. //create thread for polling usbh port status
  704. /* create usb hub thread */
  705. pNuUSBHDev->polling_thread = rt_thread_create("usbh_drv", nu_usbh_rh_thread_entry, RT_NULL,
  706. NU_USBH_THREAD_STACK_SIZE, 8, 20);
  707. RT_ASSERT(pNuUSBHDev->polling_thread != RT_NULL);
  708. /* startup usb host thread */
  709. rt_thread_startup(pNuUSBHDev->polling_thread);
  710. return RT_EOK;
  711. }
  712. /* global function for USB host library -----------------------------*/
  713. uint32_t usbh_get_ticks(void)
  714. {
  715. return rt_tick_get();
  716. }
  717. void usbh_delay_ms(int msec)
  718. {
  719. rt_thread_mdelay(msec);
  720. }
  721. uint32_t usbh_tick_from_millisecond(uint32_t msec)
  722. {
  723. return rt_tick_from_millisecond(msec);
  724. }
  725. #if defined(RT_USING_PM)
  726. /* device pm suspend() entry. */
  727. static int usbhost_pm_suspend(const struct rt_device *device, rt_uint8_t mode)
  728. {
  729. rt_err_t result;
  730. struct nu_usbh_dev *pNuUSBHDev = (struct nu_usbh_dev *)device;
  731. RT_ASSERT(pNuUSBHDev != RT_NULL);
  732. switch (mode)
  733. {
  734. case PM_SLEEP_MODE_LIGHT:
  735. case PM_SLEEP_MODE_DEEP:
  736. pNuUSBHDev->polling_thread->stat = RT_THREAD_READY;
  737. result = rt_thread_suspend(pNuUSBHDev->polling_thread);
  738. RT_ASSERT(result == RT_EOK);
  739. break;
  740. default:
  741. break;
  742. }
  743. return (int)RT_EOK;
  744. }
  745. /* device pm resume() entry. */
  746. static void usbhost_pm_resume(const struct rt_device *device, rt_uint8_t mode)
  747. {
  748. rt_err_t result;
  749. struct nu_usbh_dev *pNuUSBHDev = (struct nu_usbh_dev *)device;
  750. RT_ASSERT(pNuUSBHDev != RT_NULL);
  751. switch (mode)
  752. {
  753. case PM_SLEEP_MODE_LIGHT:
  754. case PM_SLEEP_MODE_DEEP:
  755. result = rt_thread_resume(pNuUSBHDev->polling_thread);
  756. RT_ASSERT(result == RT_EOK);
  757. break;
  758. default:
  759. break;
  760. }
  761. }
  762. static struct rt_device_pm_ops device_pm_ops =
  763. {
  764. .suspend = usbhost_pm_suspend,
  765. .resume = usbhost_pm_resume,
  766. .frequency_change = RT_NULL
  767. };
  768. #endif
  769. int nu_usbh_register(void)
  770. {
  771. rt_err_t res;
  772. uhcd_t psUHCD;
  773. psUHCD = (uhcd_t)&s_sUSBHDev.uhcd;
  774. psUHCD->parent.type = RT_Device_Class_USBHost;
  775. psUHCD->parent.init = nu_hcd_init;
  776. psUHCD->parent.user_data = &s_sUSBHDev;
  777. psUHCD->ops = &nu_uhcd_ops;
  778. psUHCD->num_ports = NU_MAX_USBH_PORT;
  779. NU_USBHOST_MUTEX_INIT();
  780. res = rt_device_register(&psUHCD->parent, "usbh", RT_DEVICE_FLAG_DEACTIVATE);
  781. RT_ASSERT(res == RT_EOK);
  782. nu_sys_ipclk_enable(s_sUSBHDev.clkidx);
  783. nu_sys_ip_reset(s_sUSBHDev.rstidx);
  784. /*initialize the usb host function */
  785. res = rt_usb_host_init("usbh");
  786. RT_ASSERT(res == RT_EOK);
  787. #if defined(RT_USING_PM)
  788. rt_pm_device_register(&psUHCD->parent, &device_pm_ops);
  789. #endif
  790. return 0;
  791. }
  792. INIT_DEVICE_EXPORT(nu_usbh_register);
  793. #endif