drv_usbhost.c 22 KB

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