hcd.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528
  1. // Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. // http://www.apache.org/licenses/LICENSE-2.0
  7. //
  8. // Unless required by applicable law or agreed to in writing, software
  9. // distributed under the License is distributed on an "AS IS" BASIS,
  10. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. // See the License for the specific language governing permissions and
  12. // limitations under the License.
  13. #pragma once
  14. #ifdef __cplusplus
  15. extern "C" {
  16. #endif
  17. #include <stdint.h>
  18. #include <stdbool.h>
  19. #include <sys/queue.h>
  20. #include "esp_err.h"
  21. #include "usb_private.h"
  22. #include "usb.h"
  23. // ------------------------------------------------- Macros & Types ----------------------------------------------------
  24. // ----------------------- States --------------------------
  25. /**
  26. * @brief States of the HCD port
  27. *
  28. * @note The port can be thought of as an abstraction of the Root Hub that contains
  29. * a single port.
  30. * @note These states roughly match the port states outlined in 11.5.1 of the
  31. * USB2.0 specification.
  32. */
  33. typedef enum {
  34. HCD_PORT_STATE_NOT_POWERED, /**< The port is not powered */
  35. HCD_PORT_STATE_DISCONNECTED, /**< The port is powered but no device is connected */
  36. HCD_PORT_STATE_DISABLED, /**< A device has connected to the port but has not been reset. SOF/keep alive are not being sent */
  37. HCD_PORT_STATE_RESETTING, /**< The port is issuing a reset condition */
  38. HCD_PORT_STATE_SUSPENDED, /**< The port has been suspended. */
  39. HCD_PORT_STATE_RESUMING, /**< The port is issuing a resume condition */
  40. HCD_PORT_STATE_ENABLED, /**< The port has been enabled. SOF/keep alive are being sent */
  41. HCD_PORT_STATE_RECOVERY, /**< Port needs to be recovered from a fatal error (port error, overcurrent, or sudden disconnection) */
  42. } hcd_port_state_t;
  43. /**
  44. * @brief States of an HCD pipe
  45. *
  46. * Active:
  47. * - Pipe is able to transmit data. URBs can be enqueued.
  48. * - Event if pipe has no URBs enqueued, it can still be in the active state.
  49. * Halted:
  50. * - An error has occurred on the pipe. URBs will no longer be executed.
  51. * - Halt should be cleared using the clear command
  52. * Invalid:
  53. * - The underlying device that the pipe connects is not longer valid, thus making the pipe invalid.
  54. * - Pending URBs should be dequeued and the pipe should be freed.
  55. */
  56. typedef enum {
  57. HCD_PIPE_STATE_ACTIVE, /**< The pipe is active */
  58. HCD_PIPE_STATE_HALTED, /**< The pipe is halted */
  59. HCD_PIPE_STATE_INVALID, /**< The pipe no longer exists and should be freed */
  60. } hcd_pipe_state_t;
  61. // ----------------------- Events --------------------------
  62. /**
  63. * @brief HCD port events
  64. *
  65. * On receiving a port event, hcd_port_handle_event() should be called to handle that event
  66. */
  67. typedef enum {
  68. HCD_PORT_EVENT_NONE, /**< No event has occurred. Or the previous event is no longer valid */
  69. HCD_PORT_EVENT_CONNECTION, /**< A device has been connected to the port */
  70. HCD_PORT_EVENT_DISCONNECTION, /**< A device disconnection has been detected */
  71. HCD_PORT_EVENT_ERROR, /**< A port error has been detected. Port is now HCD_PORT_STATE_RECOVERY */
  72. HCD_PORT_EVENT_OVERCURRENT, /**< Overcurrent detected on the port. Port is now HCD_PORT_STATE_RECOVERY */
  73. HCD_PORT_EVENT_SUDDEN_DISCONN, /**< The port has suddenly disconnected (i.e., there was an enabled device connected
  74. to the port when the disconnection occurred. Port is now HCD_PORT_STATE_RECOVERY. */
  75. } hcd_port_event_t;
  76. /**
  77. * @brief HCD pipe events
  78. *
  79. * @note Pipe error events will put the pipe into the HCD_PIPE_STATE_HALTED state
  80. * @note The HCD_PIPE_EVENT_INVALID will put the pipe in the HCD_PIPE_STATE_INVALID state
  81. */
  82. typedef enum {
  83. HCD_PIPE_EVENT_NONE, /**< The pipe has no events (used to indicate no events when polling) */
  84. HCD_PIPE_EVENT_URB_DONE, /**< The pipe has completed an URB. The URB can be dequeued */
  85. HCD_PIPE_EVENT_INVALID, /**< The pipe is invalid because the underlying device is no longer valid */
  86. HCD_PIPE_EVENT_ERROR_XFER, /**< Excessive (three consecutive) transaction errors (e.g., no ACK, bad CRC etc) */
  87. HCD_PIPE_EVENT_ERROR_URB_NOT_AVAIL, /**< URB was not available */
  88. HCD_PIPE_EVENT_ERROR_OVERFLOW, /**< Received more data than requested. Usually a Packet babble error
  89. (i.e., an IN packet has exceeded the endpoint's MPS) */
  90. HCD_PIPE_EVENT_ERROR_STALL, /**< Pipe received a STALL response received */
  91. } hcd_pipe_event_t;
  92. // ---------------------- Commands -------------------------
  93. /**
  94. * @brief HCD port commands
  95. */
  96. typedef enum {
  97. HCD_PORT_CMD_POWER_ON, /**< Power ON the port */
  98. HCD_PORT_CMD_POWER_OFF, /**< Power OFF the port. If the port is enabled, this will cause a HCD_PORT_EVENT_SUDDEN_DISCONN event.
  99. If the port is disabled, this will cause a HCD_PORT_EVENT_DISCONNECTION event. */
  100. HCD_PORT_CMD_RESET, /**< Issue a reset on the port */
  101. HCD_PORT_CMD_SUSPEND, /**< Suspend the port */
  102. HCD_PORT_CMD_RESUME, /**< Resume the port */
  103. HCD_PORT_CMD_DISABLE, /**< Disable the port (stops the SOFs or keep alive). Any created pipes will receive a HCD_PIPE_EVENT_INVALID event */
  104. } hcd_port_cmd_t;
  105. /**
  106. * @brief HCD pipe commands
  107. *
  108. * The pipe commands represent the list of pipe manipulations outlined in 10.5.2.2. of USB2.0 specification.
  109. */
  110. typedef enum {
  111. HCD_PIPE_CMD_ABORT, /**< Retire all scheduled URBs. Pipe's state remains unchanged */
  112. HCD_PIPE_CMD_RESET, /**< Retire all scheduled URBs. Pipe's state moves to active */
  113. HCD_PIPE_CMD_CLEAR, /**< Pipe's state moves from halted to active */
  114. HCD_PIPE_CMD_HALT /**< Pipe's state moves to halted */
  115. } hcd_pipe_cmd_t;
  116. // -------------------- Object Types -----------------------
  117. /**
  118. * @brief Port handle type
  119. */
  120. typedef void * hcd_port_handle_t;
  121. /**
  122. * @brief Pipe handle type
  123. */
  124. typedef void * hcd_pipe_handle_t;
  125. /**
  126. * @brief Port event callback type
  127. *
  128. * This callback is run when a port event occurs
  129. */
  130. typedef bool (*hcd_port_callback_t)(hcd_port_handle_t port_hdl, hcd_port_event_t port_event, void *user_arg, bool in_isr);
  131. /**
  132. * @brief Pipe event callback
  133. *
  134. * This callback is run when a pipe event occurs
  135. */
  136. typedef bool (*hcd_pipe_callback_t)(hcd_pipe_handle_t pipe_hdl, hcd_pipe_event_t pipe_event, void *user_arg, bool in_isr);
  137. typedef enum {
  138. HCD_PORT_FIFO_BIAS_BALANCED, /**< Balanced FIFO sizing for RX, Non-periodic TX, and periodic TX */
  139. HCD_PORT_FIFO_BIAS_RX, /**< Bias towards a large RX FIFO */
  140. HCD_PORT_FIFO_BIAS_PTX, /**< Bias towards periodic TX FIFO */
  141. } hcd_port_fifo_bias_t;
  142. /**
  143. * @brief HCD configuration structure
  144. */
  145. typedef struct {
  146. int intr_flags; /**< Interrupt flags for HCD interrupt */
  147. } hcd_config_t;
  148. /**
  149. * @brief Port configuration structure
  150. */
  151. typedef struct {
  152. hcd_port_callback_t callback; /**< HCD port event callback */
  153. void *callback_arg; /**< User argument for HCD port callback */
  154. void *context; /**< Context variable used to associate the port with upper layer object */
  155. } hcd_port_config_t;
  156. /**
  157. * @brief Pipe configuration structure
  158. *
  159. * @note The callback can be set to NULL if no callback is required (e.g., using HCD in a polling manner).
  160. */
  161. typedef struct {
  162. hcd_pipe_callback_t callback; /**< HCD pipe event ISR callback */
  163. void *callback_arg; /**< User argument for HCD pipe callback */
  164. void *context; /**< Context variable used to associate the pipe with upper layer object */
  165. const usb_desc_ep_t *ep_desc; /**< Pointer to endpoint descriptor of the pipe */
  166. usb_speed_t dev_speed; /**< Speed of the device */
  167. uint8_t dev_addr; /**< Device address of the pipe */
  168. } hcd_pipe_config_t;
  169. // --------------------------------------------- Host Controller Driver ------------------------------------------------
  170. /**
  171. * @brief Installs the Host Controller Driver
  172. *
  173. * - Allocates memory and interrupt resources for the HCD and underlying ports
  174. * - Setups up HCD to use internal PHY
  175. *
  176. * @note This function must be called before any other HCD function is called
  177. *
  178. * @param config HCD configuration
  179. * @retval ESP_OK: HCD successfully installed
  180. * @retval ESP_ERR_NO_MEM: Insufficient memory
  181. * @retval ESP_ERR_INVALID_STATE: HCD is already installed
  182. * @retval ESP_ERR_NOT_FOUND: HCD could not allocate interrupt
  183. * @retval ESP_ERR_INVALID_ARG: Arguments are invalid
  184. */
  185. esp_err_t hcd_install(const hcd_config_t *config);
  186. /**
  187. * @brief Uninstalls the HCD
  188. *
  189. * Before uninstalling the HCD, the following conditions should be met:
  190. * - All ports must be uninitialized, all pipes freed
  191. *
  192. * @retval ESP_OK: HCD successfully uninstalled
  193. * @retval ESP_ERR_INVALID_STATE: HCD is not in the right condition to be uninstalled
  194. */
  195. esp_err_t hcd_uninstall(void);
  196. // ---------------------------------------------------- HCD Port -------------------------------------------------------
  197. /**
  198. * @brief Initialize a particular port of the HCD
  199. *
  200. * After a port is initialized, it will be put into the HCD_PORT_STATE_NOT_POWERED state.
  201. *
  202. * @note The host controller only has one port, thus the only valid port_number is 1
  203. *
  204. * @param[in] port_number Port number
  205. * @param[in] port_config Port configuration
  206. * @param[out] port_hdl Port handle
  207. * @retval ESP_OK: Port enabled
  208. * @retval ESP_ERR_NO_MEM: Insufficient memory
  209. * @retval ESP_ERR_INVALID_STATE: The port is already enabled
  210. * @retval ESP_ERR_NOT_FOUND: Port number not found
  211. * @retval ESP_ERR_INVALID_ARG: Arguments are invalid
  212. */
  213. esp_err_t hcd_port_init(int port_number, const hcd_port_config_t *port_config, hcd_port_handle_t *port_hdl);
  214. /**
  215. * @brief Deinitialize a particular port
  216. *
  217. * The port must be placed in the HCD_PORT_STATE_NOT_POWERED or HCD_PORT_STATE_RECOVERY state before it can be
  218. * deinitialized.
  219. *
  220. * @param port_hdl Port handle
  221. * @retval ESP_OK: Port disabled
  222. * @retval ESP_ERR_INVALID_STATE: The port is not in a condition to be disabled (not unpowered)
  223. */
  224. esp_err_t hcd_port_deinit(hcd_port_handle_t port_hdl);
  225. /**
  226. * @brief Execute a port command
  227. *
  228. * Call this function to manipulate a port (e.g., powering it ON, sending a reset etc). The following conditions
  229. * must be met when calling this function:
  230. * - The port is in the correct state for the command (e.g., port must be suspend in order to use the resume command)
  231. * - The port does not have any pending events
  232. *
  233. * @note This function is internally protected by a mutex. If multiple threads call this function, this function will
  234. * can block.
  235. * @note For some of the commands that involve a blocking delay (e.g., reset and resume), if the port's state changes
  236. * unexpectedly (e.g., a disconnect during a resume), this function will return ESP_ERR_INVALID_RESPONSE.
  237. *
  238. * @param port_hdl Port handle
  239. * @param command Command for the HCD port
  240. * @retval ESP_OK: Command executed successfully
  241. * @retval ESP_ERR_INVALID_STATE: Conditions have not been met to call this function
  242. * @retval ESP_ERR_INVALID_RESPONSE: The command is no longer valid due to a change in the port's state
  243. */
  244. esp_err_t hcd_port_command(hcd_port_handle_t port_hdl, hcd_port_cmd_t command);
  245. /**
  246. * @brief Get the port's current state
  247. *
  248. * @param port_hdl Port handle
  249. * @return hcd_port_state_t Current port state
  250. */
  251. hcd_port_state_t hcd_port_get_state(hcd_port_handle_t port_hdl);
  252. /**
  253. * @brief Get the speed of the port
  254. *
  255. * The speed of the port is determined by the speed of the device connected to it.
  256. *
  257. * @note This function is only valid after a device directly to the port and has been reset
  258. *
  259. * @param[in port_hdl Port handle
  260. * @param[out] speed Speed of the port
  261. * @retval ESP_OK Device speed obtained
  262. * @retval ESP_ERR_INVALID_STATE: No valid device connected to the port
  263. * @retval ESP_ERR_INVALID_ARG: Invalid arguments
  264. */
  265. esp_err_t hcd_port_get_speed(hcd_port_handle_t port_hdl, usb_speed_t *speed);
  266. /**
  267. * @brief Handle a ports event
  268. *
  269. * When an port event occurs (as indicated by a callback), this function should be called the handle this event. A
  270. * port's event should always be handled before attempting to execute a port command. Note that is actually handled
  271. * may be different than the event reflected in the callback.
  272. *
  273. * If the port has no events, this function will return HCD_PORT_EVENT_NONE.
  274. *
  275. * @note If callbacks are not used, this function can also be used in a polling manner to repeatedly check for and
  276. * handle a port's events.
  277. * @note This function is internally protected by a mutex. If multiple threads call this function, this function will
  278. * can block.
  279. *
  280. * @param port_hdl Port handle
  281. * @return hcd_port_event_t The port event that was handled
  282. */
  283. hcd_port_event_t hcd_port_handle_event(hcd_port_handle_t port_hdl);
  284. /**
  285. * @brief Recover a port after a fatal error has occurred on it
  286. *
  287. * The port must be in the HCD_PORT_STATE_RECOVERY state to be called. Recovering the port will involve issuing a soft
  288. * reset on the underlying USB controller. The port will be returned to the HCD_PORT_STATE_NOT_POWERED state.
  289. *
  290. * @param port_hdl Port handle
  291. * @retval ESP_OK Port recovered successfully
  292. * @retval ESP_ERR_INVALID_STATE Port is not in the HCD_PORT_STATE_RECOVERY state
  293. */
  294. esp_err_t hcd_port_recover(hcd_port_handle_t port_hdl);
  295. /**
  296. * @brief Get the context variable of a port
  297. *
  298. * @param port_hdl Port handle
  299. * @return void* Context variable
  300. */
  301. void *hcd_port_get_context(hcd_port_handle_t port_hdl);
  302. /**
  303. * @brief Set the bias of the HCD port's internal FIFO
  304. *
  305. * @note This function can only be called when the following conditions are met:
  306. * - Port is initialized
  307. * - Port does not have any pending events
  308. * - Port does not have any allocated pipes
  309. *
  310. * @param port_hdl Port handle
  311. * @param bias Fifo bias
  312. * @retval ESP_OK FIFO sizing successfully set
  313. * @retval ESP_ERR_INVALID_STATE Incorrect state for FIFO sizes to be set
  314. */
  315. esp_err_t hcd_port_set_fifo_bias(hcd_port_handle_t port_hdl, hcd_port_fifo_bias_t bias);
  316. // --------------------------------------------------- HCD Pipes -------------------------------------------------------
  317. /**
  318. * @brief Allocate a pipe
  319. *
  320. * When allocating a pipe, the HCD will assess whether there are sufficient resources (i.e., bus time, and controller
  321. * channels). If sufficient, the pipe will be allocated.
  322. *
  323. * @note Currently, Interrupt and Isochronous pipes are not supported yet
  324. * @note The host port must be in the enabled state before a pipe can be allcoated
  325. *
  326. * @param[in] port_hdl Handle of the port this pipe will be routed through
  327. * @param[in] pipe_config Pipe configuration
  328. * @param[out] pipe_hdl Pipe handle
  329. *
  330. * @retval ESP_OK: Pipe successfully allocated
  331. * @retval ESP_ERR_NO_MEM: Insufficient memory
  332. * @retval ESP_ERR_INVALID_ARG: Arguments are invalid
  333. * @retval ESP_ERR_INVALID_STATE: Host port is not in the correct state to allocate a pipe
  334. * @retval ESP_ERR_NOT_SUPPORTED: The pipe's configuration cannot be supported
  335. */
  336. esp_err_t hcd_pipe_alloc(hcd_port_handle_t port_hdl, const hcd_pipe_config_t *pipe_config, hcd_pipe_handle_t *pipe_hdl);
  337. /**
  338. * @brief Free a pipe
  339. *
  340. * Frees the resources used by an HCD pipe. The pipe's handle should be discarded after calling this function. The pipe
  341. * must be in following condition before it can be freed:
  342. * - All URBs have been dequeued
  343. *
  344. * @param pipe_hdl Pipe handle
  345. *
  346. * @retval ESP_OK: Pipe successfully freed
  347. * @retval ESP_ERR_INVALID_STATE: Pipe is not in a condition to be freed
  348. */
  349. esp_err_t hcd_pipe_free(hcd_pipe_handle_t pipe_hdl);
  350. /**
  351. * @brief Update a pipe's maximum packet size
  352. *
  353. * This function is intended to be called on default pipes during enumeration in order to update the pipe's maximum
  354. * packet size. This function can only be called on a pipe that has met the following conditions:
  355. * - Pipe is still valid (i.e., not in the HCD_PIPE_STATE_INVALID state)
  356. * - Pipe is not currently processing a command
  357. * - All URBs have been dequeued from the pipe
  358. *
  359. * @param pipe_hdl Pipe handle
  360. * @param mps New Maximum Packet Size
  361. *
  362. * @retval ESP_OK: Pipe successfully updated
  363. * @retval ESP_ERR_INVALID_STATE: Pipe is not in a condition to be updated
  364. */
  365. esp_err_t hcd_pipe_update_mps(hcd_pipe_handle_t pipe_hdl, int mps);
  366. /**
  367. * @brief Update a pipe's device address
  368. *
  369. * This function is intended to be called on default pipes during enumeration in order to update the pipe's device
  370. * address. This function can only be called on a pipe that has met the following conditions:
  371. * - Pipe is still valid (i.e., not in the HCD_PIPE_STATE_INVALID state)
  372. * - Pipe is not currently processing a command
  373. * - All URBs have been dequeued from the pipe
  374. *
  375. * @param pipe_hdl Pipe handle
  376. * @param dev_addr New device address
  377. *
  378. * @retval ESP_OK: Pipe successfully updated
  379. * @retval ESP_ERR_INVALID_STATE: Pipe is not in a condition to be updated
  380. */
  381. esp_err_t hcd_pipe_update_dev_addr(hcd_pipe_handle_t pipe_hdl, uint8_t dev_addr);
  382. /**
  383. * @brief Make a pipe persist through a run time reset
  384. *
  385. * Normally when a HCD_PORT_CMD_RESET is called, all pipes should already have been freed. However There may be cases
  386. * (such as during enumeration) when a pipe must persist through a reset. This function will mark a pipe as
  387. * persistent allowing it to survive a reset. When HCD_PORT_CMD_RESET is called, the pipe can continue to be used after
  388. * the reset.
  389. *
  390. * @param pipe_hdl Pipe handle
  391. * @retval ESP_OK: Pipe successfully marked as persistent
  392. * @retval ESP_ERR_INVALID_STATE: Pipe is not in a condition to be made persistent
  393. */
  394. esp_err_t hcd_pipe_set_persist_reset(hcd_pipe_handle_t pipe_hdl);
  395. /**
  396. * @brief Get the context variable of a pipe from its handle
  397. *
  398. * @param pipe_hdl Pipe handle
  399. * @return void* Context variable
  400. */
  401. void *hcd_pipe_get_context(hcd_pipe_handle_t pipe_hdl);
  402. /**
  403. * @brief Get the current sate of the pipe
  404. *
  405. * @param pipe_hdl Pipe handle
  406. * @return hcd_pipe_state_t Current state of the pipe
  407. */
  408. hcd_pipe_state_t hcd_pipe_get_state(hcd_pipe_handle_t pipe_hdl);
  409. /**
  410. * @brief Execute a command on a particular pipe
  411. *
  412. * Pipe commands allow a pipe to be manipulated (such as clearing a halt, retiring all URBs etc). The following
  413. * conditions must for a pipe command to be issued:
  414. * - Pipe is still valid (i.e., not in the HCD_PIPE_STATE_INVALID)
  415. * - No other thread/task processing a command on the pipe concurrently (will return)
  416. *
  417. * @note Some pipe commands will block until the pipe's current in-flight URB is complete. If the pipe's state
  418. * changes unexpectedly, this function will return ESP_ERR_INVALID_RESPONSE
  419. *
  420. * @param pipe_hdl Pipe handle
  421. * @param command Pipe command
  422. * @retval ESP_OK: Command executed successfully
  423. * @retval ESP_ERR_INVALID_STATE: The pipe is not in the correct state/condition too execute the command
  424. * @retval ESP_ERR_INVALID_RESPONSE: The pipe's state changed unexpectedly
  425. */
  426. esp_err_t hcd_pipe_command(hcd_pipe_handle_t pipe_hdl, hcd_pipe_cmd_t command);
  427. /**
  428. * @brief Get the last event that occurred on a pipe
  429. *
  430. * This function allows a pipe to be polled for events (i.e., when callbacks are not used). Once an event has been
  431. * obtained, this function reset the last event of the pipe to HCD_PIPE_EVENT_NONE.
  432. *
  433. * @param pipe_hdl Pipe handle
  434. * @return hcd_pipe_event_t Last pipe event to occur
  435. */
  436. hcd_pipe_event_t hcd_pipe_get_event(hcd_pipe_handle_t pipe_hdl);
  437. // ---------------------------------------------------- HCD URBs -------------------------------------------------------
  438. /**
  439. * @brief Enqueue an URB to a particular pipe
  440. *
  441. * The following conditions must be met before an URB can be enqueued:
  442. * - The URB is properly initialized (data buffer and transfer length are set)
  443. * - The URB must not already be enqueued
  444. * - The pipe must be in the HCD_PIPE_STATE_ACTIVE state
  445. *
  446. * @param pipe_hdl Pipe handle
  447. * @param urb URB to enqueue
  448. * @retval ESP_OK: URB enqueued successfully
  449. * @retval ESP_ERR_INVALID_STATE: Conditions not met to enqueue URB
  450. */
  451. esp_err_t hcd_urb_enqueue(hcd_pipe_handle_t pipe_hdl, urb_t *urb);
  452. /**
  453. * @brief Dequeue an URB from a particular pipe
  454. *
  455. * This function should be called on a pipe after a pipe receives a HCD_PIPE_EVENT_URB_DONE event. If a pipe has
  456. * multiple URBs that can be dequeued, this function should be called repeatedly until all URBs are dequeued. If a pipe
  457. * has no more URBs to dequeue, this function will return NULL.
  458. *
  459. * @param pipe_hdl Pipe handle
  460. * @return urb_t* Dequeued URB, or NULL if no more URBs to dequeue
  461. */
  462. urb_t *hcd_urb_dequeue(hcd_pipe_handle_t pipe_hdl);
  463. /**
  464. * @brief Abort an enqueued URB
  465. *
  466. * This function will attempt to abort an URB that is already enqueued. If the URB has yet to be executed, it will be
  467. * "cancelled" and can then be dequeued. If the URB is currenty in-flight or has already completed, the URB will not be
  468. * affected by this function.
  469. *
  470. * @param urb URB to abort
  471. * @retval ESP_OK: URB successfully aborted, or was not affected by this function
  472. * @retval ESP_ERR_INVALID_STATE: URB was never enqueued
  473. */
  474. esp_err_t hcd_urb_abort(urb_t *urb);
  475. #ifdef __cplusplus
  476. }
  477. #endif