1 /* 2 * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 #pragma once 8 9 #include <stdint.h> 10 #include <sys/queue.h> 11 #include "freertos/FreeRTOS.h" 12 #include "freertos/task.h" 13 #include "hcd.h" 14 #include "usb/usb_types_ch9.h" 15 #include "usb/usb_types_stack.h" 16 17 #ifdef __cplusplus 18 extern "C" { 19 #endif 20 21 // ------------------------------------------------------ Types -------------------------------------------------------- 22 23 // ----------------------- Events -------------------------- 24 25 typedef enum { 26 USBH_EVENT_DEV_NEW, /**< A new device has been enumerated and added to the device pool */ 27 USBH_EVENT_DEV_GONE, /**< A device is gone. Clients should close the device */ 28 USBH_EVENT_DEV_ALL_FREE, /**< All devices have been freed */ 29 } usbh_event_t; 30 31 /** 32 * @brief Hub driver requests 33 * 34 * Various requests of the Hub driver that the USBH can make. 35 */ 36 typedef enum { 37 USBH_HUB_REQ_PORT_DISABLE, /**< Request that the Hub driver disable a particular port (occurs after a device 38 has been freed). Hub driver should respond with a USBH_HUB_EVENT_PORT_DISABLED */ 39 USBH_HUB_REQ_PORT_RECOVER, /**< Request that the Hub driver recovers a particular port (occurs after a gone 40 device has been freed). */ 41 } usbh_hub_req_t; 42 43 /** 44 * @brief Hub driver events for the USBH 45 * 46 * These events as passed by the Hub driver to the USBH via usbh_hub_pass_event() 47 * 48 * USBH_HUB_EVENT_PORT_ERROR: 49 * - The port has encountered an error (such as a sudden disconnection). The device connected to that port is no longer valid. 50 * - The USBH should: 51 * - Trigger a USBH_EVENT_DEV_GONE 52 * - Prevent further transfers to the device 53 * - Trigger the device's cleanup if it is already closed 54 * - When the last client closes the device via usbh_dev_close(), free the device object and issue a USBH_HUB_REQ_PORT_RECOVER request 55 * 56 * USBH_HUB_EVENT_PORT_DISABLED: 57 * - A previous USBH_HUB_REQ_PORT_DISABLE has completed. 58 * - The USBH should free the device object 59 */ 60 typedef enum { 61 USBH_HUB_EVENT_PORT_ERROR, /**< The port has encountered an error (such as a sudden disconnection). The device 62 connected to that port should be marked gone. */ 63 USBH_HUB_EVENT_PORT_DISABLED, /**< Previous USBH_HUB_REQ_PORT_DISABLE request completed */ 64 } usbh_hub_event_t; 65 66 // ---------------------- Callbacks ------------------------ 67 68 /** 69 * @brief Callback used to indicate completion of control transfers submitted usbh_dev_submit_ctrl_urb() 70 * @note This callback is called from within usbh_process() 71 */ 72 typedef void (*usbh_ctrl_xfer_cb_t)(usb_device_handle_t dev_hdl, urb_t *urb, void *arg); 73 74 /** 75 * @brief Callback used to indicate that the USBH has an event 76 * 77 * @note This callback is called from within usbh_process() 78 * @note On a USBH_EVENT_DEV_ALL_FREE event, the dev_hdl argument is set to NULL 79 */ 80 typedef void (*usbh_event_cb_t)(usb_device_handle_t dev_hdl, usbh_event_t usbh_event, void *arg); 81 82 /** 83 * @brief Callback used by the USBH to request actions from the Hub driver 84 * 85 * The Hub Request Callback allows the USBH to request the Hub actions on a particular port. Conversely, the Hub driver 86 * will indicate completion of some of these requests to the USBH via the usbh_hub_event() funtion. 87 */ 88 typedef void (*usbh_hub_req_cb_t)(hcd_port_handle_t port_hdl, usbh_hub_req_t hub_req, void *arg); 89 90 // ----------------------- Objects ------------------------- 91 92 /** 93 * @brief Configuration for an endpoint being allocated using usbh_ep_alloc() 94 */ 95 typedef struct { 96 const usb_ep_desc_t *ep_desc; /**< Endpoint descriptor */ 97 hcd_pipe_callback_t pipe_cb; /**< Endpoint's pipe callback */ 98 void *pipe_cb_arg; /**< Pipe callback argument */ 99 void *context; /**< Pipe context */ 100 } usbh_ep_config_t; 101 102 /** 103 * @brief USBH configuration used in usbh_install() 104 */ 105 typedef struct { 106 usb_notif_cb_t notif_cb; /**< Notification callback */ 107 void *notif_cb_arg; /**< Notification callback argument */ 108 usbh_ctrl_xfer_cb_t ctrl_xfer_cb; /**< Control transfer callback */ 109 void *ctrl_xfer_cb_arg; /**< Control transfer callback argument */ 110 usbh_event_cb_t event_cb; /**< USBH event callback */ 111 void *event_cb_arg; /**< USBH event callback argument */ 112 hcd_config_t hcd_config; /**< HCD configuration */ 113 } usbh_config_t; 114 115 // ------------------------------------------------- USBH Functions ---------------------------------------------------- 116 117 /** 118 * @brief Installs the USBH driver 119 * 120 * - This function will internally install the HCD 121 * - This must be called before calling any Hub driver functions 122 * 123 * @note Before calling this function, the Host Controller must already be un-clock gated and reset. The USB PHY 124 * (internal or external, and associated GPIOs) must already be configured. 125 * @param usbh_config USBH driver configuration 126 * @return esp_err_t 127 */ 128 esp_err_t usbh_install(const usbh_config_t *usbh_config); 129 130 /** 131 * @brief Uninstall the USBH driver 132 * 133 * - This function will uninstall the HCD 134 * - The Hub driver must be uninstalled before calling this function 135 * 136 * @note This function will simply free the resources used by the USBH. The underlying Host Controller and USB PHY will 137 * not be disabled. 138 * @return esp_err_t 139 */ 140 esp_err_t usbh_uninstall(void); 141 142 /** 143 * @brief USBH processing function 144 * 145 * - USBH processing function that must be called repeatedly to process USBH events 146 * - If blocking, the caller can block until a USB_NOTIF_SOURCE_USBH notification is received before running this 147 * function 148 * 149 * @note This function can block 150 * @return esp_err_t 151 */ 152 esp_err_t usbh_process(void); 153 154 /** 155 * @brief Get the current number of devices 156 * 157 * @note This function can block 158 * @param[out] num_devs_ret Current number of devices 159 * @return esp_err_t 160 */ 161 esp_err_t usbh_num_devs(int *num_devs_ret); 162 163 // ------------------------------------------------ Device Functions --------------------------------------------------- 164 165 // --------------------- Device Pool ----------------------- 166 167 /** 168 * @brief Fill list with address of currently connected devices 169 * 170 * - This function fills the provided list with the address of current connected devices 171 * - Device address can then be used in usbh_dev_open() 172 * - If there are more devices than the list_len, this function will only fill 173 * up to list_len number of devices. 174 * 175 * @param[in] list_len Length of empty list 176 * @param[inout] dev_addr_list Empty list to be filled 177 * @param[out] num_dev_ret Number of devices filled into list 178 * @return esp_err_t 179 */ 180 esp_err_t usbh_dev_addr_list_fill(int list_len, uint8_t *dev_addr_list, int *num_dev_ret); 181 182 /** 183 * @brief Open a device by address 184 * 185 * A device must be opened before it can be used 186 * 187 * @param[in] dev_addr Device address 188 * @param[out] dev_hdl Device handle 189 * @return esp_err_t 190 */ 191 esp_err_t usbh_dev_open(uint8_t dev_addr, usb_device_handle_t *dev_hdl); 192 193 /** 194 * @brief CLose a device 195 * 196 * Device can be opened by calling usbh_dev_open() 197 * 198 * @param[in] dev_hdl Device handle 199 * @return esp_err_t 200 */ 201 esp_err_t usbh_dev_close(usb_device_handle_t dev_hdl); 202 203 /** 204 * @brief Mark that all devices should be freed at the next possible opportunity 205 * 206 * A device marked as free will not be freed until the last client using the device has called usbh_dev_close() 207 * 208 * @return 209 * - ESP_OK: There were no devices to free to begin with. Current state is all free 210 * - ESP_ERR_NOT_FINISHED: One or more devices still need to be freed (but have been marked "to be freed") 211 */ 212 esp_err_t usbh_dev_mark_all_free(void); 213 214 // ------------------- Single Device ---------------------- 215 216 /** 217 * @brief Get a device's address 218 * 219 * @note Can be called without opening the device 220 * 221 * @param[in] dev_hdl Device handle 222 * @param[out] dev_addr Device's address 223 * @return esp_err_t 224 */ 225 esp_err_t usbh_dev_get_addr(usb_device_handle_t dev_hdl, uint8_t *dev_addr); 226 227 /** 228 * @brief Get a device's information 229 * 230 * @note This function can block 231 * @param[in] dev_hdl Device handle 232 * @param[out] dev_info Device information 233 * @return esp_err_t 234 */ 235 esp_err_t usbh_dev_get_info(usb_device_handle_t dev_hdl, usb_device_info_t *dev_info); 236 237 /** 238 * @brief Get a device's device descriptor 239 * 240 * - The device descriptor is cached when the device is created by the Hub driver 241 * 242 * @param[in] dev_hdl Device handle 243 * @param[out] dev_desc_ret Device descriptor 244 * @return esp_err_t 245 */ 246 esp_err_t usbh_dev_get_desc(usb_device_handle_t dev_hdl, const usb_device_desc_t **dev_desc_ret); 247 248 /** 249 * @brief Get a device's active configuration descriptor 250 * 251 * Simply returns a reference to the internally cached configuration descriptor 252 * 253 * @note This function can block 254 * @param[in] dev_hdl Device handle 255 * @param config_desc_ret 256 * @return esp_err_t 257 */ 258 esp_err_t usbh_dev_get_config_desc(usb_device_handle_t dev_hdl, const usb_config_desc_t **config_desc_ret); 259 260 /** 261 * @brief Submit a control transfer (URB) to a device 262 * 263 * @param[in] dev_hdl Device handle 264 * @param[in] urb URB 265 * @return esp_err_t 266 */ 267 esp_err_t usbh_dev_submit_ctrl_urb(usb_device_handle_t dev_hdl, urb_t *urb); 268 269 // ----------------------------------------------- Endpoint Functions ------------------------------------------------- 270 271 /** 272 * @brief Allocate an endpoint on a device 273 * 274 * Clients that have opened a device must call this function to allocate all endpoints in an interface that is claimed. 275 * The pipe handle of the endpoint is returned so that clients can use and control the pipe directly. 276 * 277 * @note This function can block 278 * @note Default pipes are owned by the USBH. For control transfers, use usbh_dev_submit_ctrl_urb() instead 279 * @note Device must be opened by the client first 280 * 281 * @param[in] dev_hdl Device handle 282 * @param[in] ep_config 283 * @param[out] pipe_hdl_ret Pipe handle 284 * @return esp_err_t 285 */ 286 esp_err_t usbh_ep_alloc(usb_device_handle_t dev_hdl, usbh_ep_config_t *ep_config, hcd_pipe_handle_t *pipe_hdl_ret); 287 288 /** 289 * @brief Free and endpoint on a device 290 * 291 * Free an endpoint previously opened by usbh_ep_alloc() 292 * 293 * @note This function can block 294 * @param[in] dev_hdl Device handle 295 * @param[in] bEndpointAddress Endpoint's address 296 * @return esp_err_t 297 */ 298 esp_err_t usbh_ep_free(usb_device_handle_t dev_hdl, uint8_t bEndpointAddress); 299 300 /** 301 * @brief Get the context of an endpoint 302 * 303 * Get the context variable assigned to and endpoint on allocation. 304 * 305 * @note This function can block 306 * @param[in] dev_hdl Device handle 307 * @param[in] bEndpointAddress Endpoint's address 308 * @param[out] context_ret Context variable 309 * @return esp_err_t 310 */ 311 esp_err_t usbh_ep_get_context(usb_device_handle_t dev_hdl, uint8_t bEndpointAddress, void **context_ret); 312 313 // -------------------------------------------------- Hub Functions ---------------------------------------------------- 314 315 // ------------------- Device Related ---------------------- 316 317 /** 318 * @brief Indicates to USBH that the Hub driver is installed 319 * 320 * - The Hub driver must call this function in its installation to indicate the the USBH that it has been installed. 321 * - This should only be called after the USBH has already be installed 322 * 323 * @note Hub Driver only 324 * @param[in] hub_req_callback Hub request callback 325 * @param[in] callback_arg Callback argument 326 * @return esp_err_t 327 */ 328 esp_err_t usbh_hub_is_installed(usbh_hub_req_cb_t hub_req_callback, void *callback_arg); 329 330 /** 331 * @brief Indicates to USBH the start of enumeration for a device 332 * 333 * - The Hub driver calls this function before it starts enumerating a new device. 334 * - The USBH will allocate a new device that will be initialized by the Hub driver using the remaining hub enumeration 335 * functions. 336 * - The new device's default pipe handle is returned to all the Hub driver to be used during enumeration. 337 * 338 * @note Hub Driver only 339 * @param[in] port_hdl Handle of the port that the device is connected to 340 * @param[in] dev_speed Device's speed 341 * @param[out] new_dev_hdl Device's handle 342 * @param[out] default_pipe_hdl Device's default pipe handle 343 * @return esp_err_t 344 */ 345 esp_err_t usbh_hub_add_dev(hcd_port_handle_t port_hdl, usb_speed_t dev_speed, usb_device_handle_t *new_dev_hdl, hcd_pipe_handle_t *default_pipe_hdl); 346 347 /** 348 * @brief Indicates to the USBH that a hub event has occurred for a particular device 349 * 350 * @param dev_hdl Device handle 351 * @param hub_event Hub event 352 * @return esp_err_t 353 */ 354 esp_err_t usbh_hub_pass_event(usb_device_handle_t dev_hdl, usbh_hub_event_t hub_event); 355 356 // ----------------- Enumeration Related ------------------- 357 358 /** 359 * @brief Assign the enumerating device's address 360 * 361 * @note Hub Driver only 362 * @note Must call in sequence 363 * @param[in] dev_hdl Device handle 364 * @param dev_addr 365 * @return esp_err_t 366 */ 367 esp_err_t usbh_hub_enum_fill_dev_addr(usb_device_handle_t dev_hdl, uint8_t dev_addr); 368 369 /** 370 * @brief Fill the enumerating device's descriptor 371 * 372 * @note Hub Driver only 373 * @note Must call in sequence 374 * @param[in] dev_hdl Device handle 375 * @param device_desc 376 * @return esp_err_t 377 */ 378 esp_err_t usbh_hub_enum_fill_dev_desc(usb_device_handle_t dev_hdl, const usb_device_desc_t *device_desc); 379 380 /** 381 * @brief Fill the enumerating device's active configuration descriptor 382 * 383 * @note Hub Driver only 384 * @note Must call in sequence 385 * @note This function can block 386 * @param[in] dev_hdl Device handle 387 * @param config_desc_full 388 * @return esp_err_t 389 */ 390 esp_err_t usbh_hub_enum_fill_config_desc(usb_device_handle_t dev_hdl, const usb_config_desc_t *config_desc_full); 391 392 /** 393 * @brief Fill one of the string descriptors of the enumerating device 394 * 395 * @note Hub Driver only 396 * @note Must call in sequence 397 * @param dev_hdl Device handle 398 * @param str_desc Pointer to string descriptor 399 * @param select Select which string descriptor. 0/1/2 for Manufacturer/Product/Serial Number string descriptors respecitvely 400 * @return esp_err_t 401 */ 402 esp_err_t usbh_hub_enum_fill_str_desc(usb_device_handle_t dev_hdl, const usb_str_desc_t *str_desc, int select); 403 404 /** 405 * @brief Indicate the device enumeration is completed 406 * 407 * This will all the device to be opened by clients, and also trigger a USBH_EVENT_DEV_NEW event. 408 * 409 * @note Hub Driver only 410 * @note Must call in sequence 411 * @note This function can block 412 * @param[in] dev_hdl Device handle 413 * @return esp_err_t 414 */ 415 esp_err_t usbh_hub_enum_done(usb_device_handle_t dev_hdl); 416 417 /** 418 * @brief Indicate that device enumeration has failed 419 * 420 * This will cause the enumerating device's resources to be cleaned up 421 * The Hub Driver must guarantee that the enumerating device's default pipe is already halted, flushed, and dequeued. 422 * 423 * @note Hub Driver only 424 * @note Must call in sequence 425 * @note This function can block 426 * @param[in] dev_hdl Device handle 427 * @return esp_err_t 428 */ 429 esp_err_t usbh_hub_enum_failed(usb_device_handle_t dev_hdl); 430 431 #ifdef __cplusplus 432 } 433 #endif 434