usbh_ctrl.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612
  1. /*!
  2. \file usbh_ctrl.c
  3. \brief this file implements the functions for the control transmit process
  4. */
  5. /*
  6. Copyright (C) 2017 GigaDevice
  7. 2017-02-10, V1.0.0, firmware for GD32F30x
  8. */
  9. #include "usbh_core.h"
  10. #include "usbh_std.h"
  11. #include "usbh_ctrl.h"
  12. uint8_t ctrl_polling_handle_flag = 0U;
  13. uint8_t ctrl_setup_wait_flag = 0U;
  14. uint8_t ctrl_data_wait_flag = 0U;
  15. uint8_t ctrl_status_wait_flag = 0U;
  16. static uint16_t timeout = 0U;
  17. static void ctrl_idle_handle (usb_core_handle_struct *pudev, usbh_host_struct *puhost, usbh_state_handle_struct *pustate);
  18. static void ctrl_setup_handle (usb_core_handle_struct *pudev, usbh_host_struct *puhost, usbh_state_handle_struct *pustate);
  19. static void ctrl_data_handle (usb_core_handle_struct *pudev, usbh_host_struct *puhost, usbh_state_handle_struct *pustate);
  20. static void ctrl_status_handle (usb_core_handle_struct *pudev, usbh_host_struct *puhost, usbh_state_handle_struct *pustate);
  21. static void ctrl_error_handle (usb_core_handle_struct *pudev, usbh_host_struct *puhost, usbh_state_handle_struct *pustate);
  22. static void ctrl_stalled_handle (usb_core_handle_struct *pudev, usbh_host_struct *puhost, usbh_state_handle_struct *pustate);
  23. static void ctrl_complete_handle (usb_core_handle_struct *pudev, usbh_host_struct *puhost, usbh_state_handle_struct *pustate);
  24. /* the ctrl state handle function array */
  25. void (*ctrl_state_handle[]) (usb_core_handle_struct *pudev,
  26. usbh_host_struct *puhost,
  27. usbh_state_handle_struct *pustate) =
  28. {
  29. ctrl_idle_handle,
  30. ctrl_setup_handle,
  31. ctrl_data_handle,
  32. ctrl_status_handle,
  33. ctrl_error_handle,
  34. ctrl_stalled_handle,
  35. ctrl_complete_handle,
  36. };
  37. /* the ctrl state handle table */
  38. state_table_struct ctrl_handle_table[CTRL_HANDLE_TABLE_SIZE] =
  39. {
  40. /* the current state the current event the next state the event function */
  41. {CTRL_IDLE, CTRL_EVENT_SETUP, CTRL_SETUP, only_state_move },
  42. {CTRL_SETUP, CTRL_EVENT_DATA, CTRL_DATA, only_state_move },
  43. {CTRL_SETUP, CTRL_EVENT_STATUS, CTRL_STATUS, only_state_move },
  44. {CTRL_SETUP, CTRL_EVENT_ERROR, CTRL_ERROR, only_state_move },
  45. {CTRL_DATA, CTRL_EVENT_STATUS, CTRL_STATUS, only_state_move },
  46. {CTRL_DATA, CTRL_EVENT_ERROR, CTRL_ERROR, only_state_move },
  47. {CTRL_DATA, CTRL_EVENT_STALLED, CTRL_STALLED, only_state_move },
  48. {CTRL_STATUS, CTRL_EVENT_COMPLETE, CTRL_COMPLETE, only_state_move },
  49. {CTRL_STATUS, CTRL_EVENT_ERROR, CTRL_ERROR, only_state_move },
  50. {CTRL_STATUS, CTRL_EVENT_STALLED, CTRL_STALLED, only_state_move },
  51. {CTRL_ERROR, GO_TO_UP_STATE_EVENT, UP_STATE, goto_up_state_fun },
  52. {CTRL_STALLED, GO_TO_UP_STATE_EVENT, UP_STATE, goto_up_state_fun },
  53. {CTRL_COMPLETE, GO_TO_UP_STATE_EVENT, UP_STATE, goto_up_state_fun },
  54. };
  55. /*!
  56. \brief the polling function of CTRL state
  57. \param[in] pudev: pointer to usb device
  58. \param[in] puhost: pointer to usb host
  59. \param[in] pustate: pointer to usb state driver
  60. \param[out] none
  61. \retval none
  62. */
  63. usbh_status_enum ctrl_state_polling_fun (usb_core_handle_struct *pudev,
  64. usbh_host_struct *puhost,
  65. void *pustate)
  66. {
  67. usbh_status_enum exe_state = USBH_BUSY;
  68. usbh_state_handle_struct *p_state;
  69. p_state = (usbh_state_handle_struct *)pustate;
  70. /* if first enter this function, begin the ctrl state */
  71. if (0U == ctrl_polling_handle_flag) {
  72. ctrl_polling_handle_flag = 1U;
  73. scd_table_push(p_state);
  74. scd_state_move(p_state, CTRL_IDLE);
  75. }
  76. /* base on the current state to handle the ctrl state */
  77. scd_begin(p_state, CTRL_FSM_ID);
  78. ctrl_state_handle[p_state->usbh_current_state](pudev, puhost, p_state);
  79. /* determine the control transfer whether to complete */
  80. switch (puhost->usbh_backup_state.ctrl_backup_state) {
  81. case CTRL_COMPLETE:
  82. ctrl_polling_handle_flag = 0U;
  83. puhost->usbh_backup_state.ctrl_backup_state = CTRL_IDLE;
  84. exe_state = USBH_OK;
  85. break;
  86. case CTRL_STALLED:
  87. ctrl_polling_handle_flag = 0U;
  88. puhost->usbh_backup_state.ctrl_backup_state = CTRL_IDLE;
  89. exe_state = USBH_NOT_SUPPORTED;
  90. break;
  91. case CTRL_ERROR:
  92. ctrl_polling_handle_flag = 0U;
  93. puhost->usbh_backup_state.ctrl_backup_state = CTRL_IDLE;
  94. exe_state = USBH_FAIL;
  95. break;
  96. default:
  97. exe_state = USBH_BUSY;
  98. break;
  99. }
  100. return exe_state;
  101. }
  102. /*!
  103. \brief the handle function of CTRL_IDLE state
  104. \param[in] pudev: pointer to usb device
  105. \param[in] puhost: pointer to usb host
  106. \param[in] pustate: pointer to usb state driver
  107. \param[out] none
  108. \retval none
  109. */
  110. static void ctrl_idle_handle (usb_core_handle_struct *pudev,
  111. usbh_host_struct *puhost,
  112. usbh_state_handle_struct *pustate)
  113. {
  114. puhost->usbh_backup_state.ctrl_backup_state = CTRL_IDLE;
  115. scd_event_handle(pudev, puhost, pustate, CTRL_EVENT_SETUP, pustate->usbh_current_state);
  116. }
  117. /*!
  118. \brief the handle function of CTRL_SETUP state
  119. \param[in] pudev: pointer to usb device
  120. \param[in] puhost: pointer to usb host
  121. \param[in] pustate: pointer to usb state driver
  122. \param[out] none
  123. \retval none
  124. */
  125. static void ctrl_setup_handle (usb_core_handle_struct *pudev,
  126. usbh_host_struct *puhost,
  127. usbh_state_handle_struct *pustate)
  128. {
  129. urb_state_enum urb_status = URB_IDLE;
  130. puhost->usbh_backup_state.ctrl_backup_state = CTRL_SETUP;
  131. if (0U == ctrl_setup_wait_flag) {
  132. ctrl_setup_wait_flag = 1U;
  133. /* send a setup packet */
  134. usbh_ctltx_setup (pudev,
  135. puhost->control.setup.data,
  136. puhost->control.hc_out_num);
  137. } else {
  138. urb_status = hcd_urb_state_get(pudev, puhost->control.hc_out_num);
  139. /* case setup packet sent successfully */
  140. if (URB_DONE == urb_status) {
  141. /* check if there is a data stage */
  142. if (0U != puhost->control.setup.b.wLength) {
  143. ctrl_setup_wait_flag = 0U;
  144. timeout = DATA_STAGE_TIMEOUT;
  145. scd_event_handle(pudev, puhost, pustate, CTRL_EVENT_DATA, pustate->usbh_current_state);
  146. /* no data stage */
  147. } else {
  148. timeout = NODATA_STAGE_TIMEOUT;
  149. ctrl_setup_wait_flag = 0U;
  150. scd_event_handle(pudev,
  151. puhost,
  152. pustate,
  153. CTRL_EVENT_STATUS,
  154. pustate->usbh_current_state);
  155. }
  156. /* set the delay timer to enable timeout for data stage completion */
  157. puhost->control.timer = (uint16_t)USB_CURRENT_FRAME_GET();
  158. } else if (URB_ERROR == urb_status) {
  159. ctrl_setup_wait_flag = 0U;
  160. scd_event_handle(pudev, puhost, pustate, CTRL_EVENT_ERROR, pustate->usbh_current_state);
  161. } else {
  162. /* no operation */
  163. }
  164. }
  165. }
  166. /*!
  167. \brief the handle function of CTRL_DATA state
  168. \param[in] pudev: pointer to usb device
  169. \param[in] puhost: pointer to usb host
  170. \param[in] pustate: pointer to usb state driver
  171. \param[out] none
  172. \retval none
  173. */
  174. static void ctrl_data_handle (usb_core_handle_struct *pudev,
  175. usbh_host_struct *puhost,
  176. usbh_state_handle_struct *pustate)
  177. {
  178. uint8_t direction;
  179. urb_state_enum urb_status = URB_IDLE;
  180. puhost->usbh_backup_state.ctrl_backup_state = CTRL_DATA;
  181. direction = (puhost->control.setup.b.bmRequestType & USB_DIR_MASK);
  182. if (USB_DIR_IN == direction) {
  183. if (0U == ctrl_data_wait_flag) {
  184. ctrl_data_wait_flag = 1U;
  185. /* issue an IN token */
  186. usbh_xfer(pudev,
  187. puhost->control.buff,
  188. puhost->control.hc_in_num,
  189. puhost->control.length);
  190. } else {
  191. urb_status = hcd_urb_state_get(pudev, puhost->control.hc_in_num);
  192. /* check is data packet transfered successfully */
  193. switch (urb_status) {
  194. case URB_DONE:
  195. ctrl_data_wait_flag = 0U;
  196. scd_event_handle(pudev,
  197. puhost,
  198. pustate,
  199. CTRL_EVENT_STATUS,
  200. pustate->usbh_current_state);
  201. break;
  202. case URB_STALL:
  203. ctrl_data_wait_flag = 0U;
  204. scd_event_handle(pudev,
  205. puhost,
  206. pustate,
  207. CTRL_EVENT_STALLED,
  208. pustate->usbh_current_state);
  209. break;
  210. case URB_ERROR:
  211. ctrl_data_wait_flag = 0U;
  212. /* device error */
  213. scd_event_handle(pudev,
  214. puhost,
  215. pustate,
  216. CTRL_EVENT_ERROR,
  217. pustate->usbh_current_state);
  218. break;
  219. default:
  220. if (((uint16_t)USB_CURRENT_FRAME_GET() - puhost->control.timer) > timeout) {
  221. ctrl_data_wait_flag = 0U;
  222. /* timeout for IN transfer */
  223. scd_event_handle(pudev,
  224. puhost,
  225. pustate,
  226. CTRL_EVENT_ERROR,
  227. pustate->usbh_current_state);
  228. }
  229. break;
  230. }
  231. }
  232. } else {
  233. if (0U == ctrl_data_wait_flag) {
  234. ctrl_data_wait_flag = 1U;
  235. /* start DATA out transfer (only one DATA packet)*/
  236. pudev->host.host_channel[puhost->control.hc_out_num].data_tg_out = 1U;
  237. usbh_xfer(pudev,
  238. puhost->control.buff,
  239. puhost->control.hc_out_num,
  240. puhost->control.length);
  241. } else {
  242. urb_status = hcd_urb_state_get(pudev, puhost->control.hc_out_num);
  243. switch (urb_status) {
  244. case URB_DONE:
  245. ctrl_data_wait_flag = 0U;
  246. /* if the setup pkt is sent successful, then change the state */
  247. scd_event_handle(pudev,
  248. puhost,
  249. pustate,
  250. CTRL_EVENT_STATUS,
  251. pustate->usbh_current_state);
  252. break;
  253. case URB_STALL:
  254. ctrl_data_wait_flag = 0U;
  255. scd_event_handle(pudev,
  256. puhost,
  257. pustate,
  258. CTRL_EVENT_STALLED,
  259. pustate->usbh_current_state);
  260. break;
  261. case URB_NOTREADY:
  262. /* nack received from device */
  263. ctrl_data_wait_flag = 0U;
  264. break;
  265. case URB_ERROR:
  266. ctrl_data_wait_flag = 0U;
  267. /* device error */
  268. scd_event_handle(pudev,
  269. puhost,
  270. pustate,
  271. CTRL_EVENT_ERROR,
  272. pustate->usbh_current_state);
  273. break;
  274. default:
  275. break;
  276. }
  277. }
  278. }
  279. }
  280. /*!
  281. \brief the handle function of CTRL_STATUS state
  282. \param[in] pudev: pointer to usb device
  283. \param[in] puhost: pointer to usb host
  284. \param[in] pustate: pointer to usb state driver
  285. \param[out] none
  286. \retval none
  287. */
  288. static void ctrl_status_handle (usb_core_handle_struct *pudev,
  289. usbh_host_struct *puhost,
  290. usbh_state_handle_struct *pustate)
  291. {
  292. uint8_t direction;
  293. urb_state_enum urb_status = URB_IDLE;
  294. puhost->usbh_backup_state.ctrl_backup_state = CTRL_STATUS;
  295. /* get the transfer direction in the data state, but the transfer direction in the status state is opposite */
  296. direction = (puhost->control.setup.b.bmRequestType & USB_DIR_MASK);
  297. if (USB_DIR_OUT == direction) {
  298. /* handle status in */
  299. if (0U == ctrl_status_wait_flag) {
  300. ctrl_status_wait_flag = 1U;
  301. usbh_xfer (pudev, 0U, puhost->control.hc_in_num, 0U);
  302. } else {
  303. urb_status = hcd_urb_state_get(pudev, puhost->control.hc_in_num);
  304. switch (urb_status) {
  305. case URB_DONE:
  306. ctrl_status_wait_flag = 0U;
  307. /* handle URB_DONE status */
  308. scd_event_handle(pudev,
  309. puhost,
  310. pustate,
  311. CTRL_EVENT_COMPLETE,
  312. pustate->usbh_current_state);
  313. break;
  314. case URB_ERROR:
  315. ctrl_status_wait_flag = 0U;
  316. /* handle URB_STALL status*/
  317. scd_event_handle(pudev,
  318. puhost,
  319. pustate,
  320. CTRL_EVENT_ERROR,
  321. pustate->usbh_current_state);
  322. break;
  323. case URB_STALL:
  324. ctrl_status_wait_flag = 0U;
  325. /* handle URB_STALL status */
  326. scd_event_handle(pudev,
  327. puhost,
  328. pustate,
  329. CTRL_EVENT_STALLED,
  330. pustate->usbh_current_state);
  331. break;
  332. default:
  333. if (((uint16_t)USB_CURRENT_FRAME_GET() - puhost->control.timer) > timeout) {
  334. ctrl_status_wait_flag = 0U;
  335. /* handle timeout */
  336. scd_event_handle(pudev,
  337. puhost,
  338. pustate,
  339. CTRL_EVENT_ERROR,
  340. pustate->usbh_current_state);
  341. }
  342. break;
  343. }
  344. }
  345. } else {
  346. /* handle status out */
  347. if (0U == ctrl_status_wait_flag) {
  348. ctrl_status_wait_flag = 1U;
  349. pudev->host.host_channel[puhost->control.hc_out_num].data_tg_out ^= 1U;
  350. usbh_xfer (pudev, 0U, puhost->control.hc_out_num, 0U);
  351. } else {
  352. urb_status = hcd_urb_state_get(pudev, puhost->control.hc_out_num);
  353. switch (urb_status) {
  354. case URB_DONE:
  355. ctrl_status_wait_flag = 0U;
  356. /* handle URB_DONE status */
  357. scd_event_handle(pudev,
  358. puhost,
  359. pustate,
  360. CTRL_EVENT_COMPLETE,
  361. pustate->usbh_current_state);
  362. break;
  363. case URB_NOTREADY:
  364. /* handle URB_NOTREADY status */
  365. ctrl_status_wait_flag = 0U;
  366. break;
  367. case URB_ERROR:
  368. ctrl_status_wait_flag = 0U;
  369. /* handle URB_ERROR status */
  370. scd_event_handle(pudev,
  371. puhost,
  372. pustate,
  373. CTRL_EVENT_ERROR,
  374. pustate->usbh_current_state);
  375. break;
  376. default:
  377. break;
  378. }
  379. }
  380. }
  381. }
  382. /*!
  383. \brief the handle function of CTRL_ERROR state
  384. \param[in] pudev: pointer to usb device
  385. \param[in] puhost: pointer to usb host
  386. \param[in] pustate: pointer to usb state driver
  387. \param[out] none
  388. \retval none
  389. */
  390. static void ctrl_error_handle (usb_core_handle_struct *pudev,
  391. usbh_host_struct *puhost,
  392. usbh_state_handle_struct *pustate)
  393. {
  394. puhost->usbh_backup_state.ctrl_backup_state = CTRL_ERROR;
  395. if (++puhost->control.error_count <= USBH_MAX_ERROR_COUNT) {
  396. /* do the transmission again, starting from SETUP Packet */
  397. scd_event_handle(pudev, puhost, pustate, CTRL_EVENT_SETUP, pustate->usbh_current_state);
  398. } else {
  399. scd_event_handle(pudev, puhost, pustate, GO_TO_UP_STATE_EVENT, pustate->usbh_current_state);
  400. }
  401. }
  402. /*!
  403. \brief the handle function of CTRL_STALLED state
  404. \param[in] pudev: pointer to usb device
  405. \param[in] puhost: pointer to usb host
  406. \param[in] pustate: pointer to usb state driver
  407. \param[out] none
  408. \retval none
  409. */
  410. static void ctrl_stalled_handle (usb_core_handle_struct *pudev,
  411. usbh_host_struct *puhost,
  412. usbh_state_handle_struct *pustate)
  413. {
  414. puhost->usbh_backup_state.ctrl_backup_state = CTRL_STALLED;
  415. scd_event_handle(pudev, puhost, pustate, GO_TO_UP_STATE_EVENT, pustate->usbh_current_state);
  416. }
  417. /*!
  418. \brief the handle function of CTRL_COMPLETE state
  419. \param[in] pudev: pointer to usb device
  420. \param[in] puhost: pointer to usb host
  421. \param[in] pustate: pointer to usb state driver
  422. \param[out] none
  423. \retval none
  424. */
  425. static void ctrl_complete_handle (usb_core_handle_struct *pudev,
  426. usbh_host_struct *puhost,
  427. usbh_state_handle_struct *pustate)
  428. {
  429. puhost->usbh_backup_state.ctrl_backup_state = CTRL_COMPLETE;
  430. scd_event_handle(pudev, puhost, pustate, GO_TO_UP_STATE_EVENT, pustate->usbh_current_state);
  431. }
  432. /*!
  433. \brief send datas from the host channel
  434. \param[in] pudev: pointer to usb device
  435. \param[in] buf: data buffer address to send datas
  436. \param[in] hc_num: the number of the host channel
  437. \param[in] len: length of the send data
  438. \param[out] none
  439. \retval host operation status
  440. */
  441. usbh_status_enum usbh_xfer (usb_core_handle_struct *pudev,
  442. uint8_t *buf,
  443. uint8_t hc_num,
  444. uint16_t len)
  445. {
  446. usb_hostchannel_struct *puhc = &pudev->host.host_channel[hc_num];
  447. puhc->xfer_buff = buf;
  448. puhc->xfer_len = len;
  449. switch (puhc->endp_type) {
  450. case USB_EPTYPE_CTRL:
  451. if (0U == puhc->endp_in) {
  452. if (0U == len) {
  453. /* for status out stage, length = 0, status out pid = 1 */
  454. puhc->data_tg_out = 1U;
  455. }
  456. /* set the data toggle bit as per the flag */
  457. if (0U == puhc->data_tg_out) {
  458. /* put the pid 0 */
  459. puhc->DPID = HC_PID_DATA0;
  460. } else {
  461. /* put the pid 1 */
  462. puhc->DPID = HC_PID_DATA1;
  463. }
  464. } else {
  465. puhc->DPID = HC_PID_DATA1;
  466. }
  467. break;
  468. case USB_EPTYPE_ISOC:
  469. puhc->DPID = HC_PID_DATA0;
  470. break;
  471. case USB_EPTYPE_BULK:
  472. if (0U == puhc->endp_in) {
  473. /* set the data toggle bit as per the flag */
  474. if (0U == puhc->data_tg_out) {
  475. /* put the pid 0 */
  476. puhc->DPID = HC_PID_DATA0;
  477. } else {
  478. /* put the pid 1 */
  479. puhc->DPID = HC_PID_DATA1;
  480. }
  481. } else {
  482. if (0U == puhc->data_tg_in) {
  483. puhc->DPID = HC_PID_DATA0;
  484. } else {
  485. puhc->DPID = HC_PID_DATA1;
  486. }
  487. }
  488. break;
  489. case USB_EPTYPE_INTR:
  490. if (0U == puhc->endp_in) {
  491. if (0U == puhc->data_tg_out) {
  492. puhc->DPID = HC_PID_DATA0;
  493. } else {
  494. puhc->DPID = HC_PID_DATA1;
  495. }
  496. /* toggle data pid */
  497. puhc->data_tg_out ^= 1U;
  498. } else {
  499. if (0U == puhc->data_tg_in) {
  500. puhc->DPID = HC_PID_DATA0;
  501. } else {
  502. puhc->DPID = HC_PID_DATA1;
  503. }
  504. /* toggle data pid */
  505. puhc->data_tg_in ^= 1U;
  506. }
  507. break;
  508. default:
  509. break;
  510. }
  511. hcd_submit_request (pudev, hc_num);
  512. return USBH_OK;
  513. }
  514. /*!
  515. \brief send the setup packet to the device
  516. \param[in] pudev: pointer to usb device
  517. \param[in] buf: buffer pointer from which the data will be send to device
  518. \param[in] hc_num: host channel number
  519. \param[out] none
  520. \retval host operation status
  521. */
  522. usbh_status_enum usbh_ctltx_setup (usb_core_handle_struct *pudev, uint8_t *buf, uint8_t hc_num)
  523. {
  524. usb_hostchannel_struct *puhc = &pudev->host.host_channel[hc_num];
  525. puhc->DPID = HC_PID_SETUP;
  526. puhc->xfer_buff = buf;
  527. puhc->xfer_len = USBH_SETUP_PACKET_SIZE;
  528. return (usbh_status_enum)hcd_submit_request (pudev, hc_num);
  529. }
  530. /*!
  531. \brief this function prepare a hc and start a transfer
  532. \param[in] pudev: pointer to usb device
  533. \param[in] channel_num: host channel number which is in (0..7)
  534. \param[out] none
  535. \retval host operation status
  536. */
  537. uint32_t hcd_submit_request (usb_core_handle_struct *pudev, uint8_t channel_num)
  538. {
  539. usb_hostchannel_struct *puhc = &pudev->host.host_channel[channel_num];
  540. puhc->urb_state = URB_IDLE;
  541. puhc->xfer_count = 0U;
  542. return (uint32_t)usb_hostchannel_startxfer(pudev, channel_num);
  543. }