1USB Host 2======== 3 4.. warning:: 5 The USB Host Library API is a beta version thus is subject to change. 6 7The document provides information regarding the USB Host Library. This document is split into the following sections: 8 9.. contents:: Sections 10 :depth: 2 11 12 13.. ---------------------------------------------------- Overview ------------------------------------------------------- 14 15Overview 16-------- 17 18The USB Host Library (hereinafter referred to as the Host Library) is the lowest public facing API layer of the ESP-IDF USB Host Stack. In most cases, applications that require USB Host functionality will not need to interface with the Host Library directly. Instead, most applications will use the API provided by a host class driver that is implemented on top of the Host Library. 19 20However, users may want to use the Host Library directly for some of (but not limited to) the following reasons: 21 22- The user needs to implement a custom host class driver such as a vendor specific class driver 23- The user has a requirement for a lower level of abstraction due to resource/latency requirements 24 25Features & Limitations 26^^^^^^^^^^^^^^^^^^^^^^ 27 28The Host Library has the following features: 29 30- Supports Full Speed (FS) and Low Speed (LS) Devices 31- Supports all four transfer types (Control, Bulk, Interrupt, and Isochronous) 32- Allows multiple class drivers to run simultaneously (i.e., multiple clients of the Host Library) 33- A single device can be used by multiple clients simultaneously (e.g., composite devices) 34- The Host Library itself (and the underlying Host Stack) does not internally instantiate any OS tasks. The number of tasks are entirely controlled by how the Host Library interface is used. However, a general rule of thumb regarding the number of tasks is ``(the number of host class drivers running + 1)``. 35 36Currently, the Host Library (and the underlying Host Stack) has the following limitations: 37 38- Only supports a single device, but the Host Library's API is designed for multiple device support. 39- Only supports Asynchronous transfers 40- Transfer timeouts are not supported yet 41 42 43.. -------------------------------------------------- Architecture ----------------------------------------------------- 44 45Architecture 46------------ 47 48.. figure:: ../../../_static/usb_host_lib_entities.png 49 :align: center 50 :alt: Diagram of the Key Entities of USB Host Functionality 51 :figclass: align-center 52 53 Diagram of the key entities involved in USB Host functionality 54 55The diagram above shows the key entities that are involved when implementing USB Host functionality. These entities are: 56 57- The **Host Library** 58- **Clients** of the Host Library 59- **Devices** 60- Host Library **Daemon Task** 61 62Host Library 63^^^^^^^^^^^^ 64 65The Host Library is the a lowest public facing layer of the USB Host Stack. Any other IDF component (such as a class driver or a user component) that needs to communicate with a connected USB device can only do so using the Host Library API either directly or indirectly. 66 67The Host Library's API is split into two sub-sets, namely the **Library API** and **Client API**. 68 69- The Client API handles the communication between a client of the Host Library and one or more USB devices. The Client API should only be called by registered clients of the Host Library. 70- The Library API handles all of the Host Library processing that is not specific to a single client (e.g., device enumeration). Usually, the library API is called by a Host Library Daemon Task. 71 72Clients 73^^^^^^^ 74 75A client of the Host Library is a software component (such as a host class driver or user component) that uses the Host Library to communicate with a USB device. Generally each client has a one-to-one relation with a task, meaning that for a particular client, all of its Client API calls should be done from the context of the same task. 76 77By organizing the software components that use the Host Library's into clients, the Host Library can delegate the handling of all client events (i.e., the events specific to that client) to the client's task. In other words, each client task is responsible for all the required processing and event handling associated with the USB communication that the client initiates. 78 79Daemon Task 80^^^^^^^^^^^ 81 82Although the Host Library delegates the handling of client events to the clients themselves, there are still Library events (i.e., events that are not specific to a client) that need to be handled. Library event handling can include things such as: 83 84- Handling USB device connection, enumeration, and disconnection 85- Rerouting control transfers to/from clients 86- Forwarding events to clients 87 88Therefore, in addition to the client tasks, the Host Library also requires a task (usually the Host Library Daemon Task) to handle all of the library events. 89 90Devices 91^^^^^^^ 92 93The Host Library hides the details of device handling (such as connection, memory allocation, and enumeration) from the clients. The clients are provided only with a list of already connected and enumerated devices to choose from. During enumeration, each device is configured to use configuration 1. 94 95It is possible for a two or more clients to simultaneously communicate with the same device as long as they are not communicating to the same interface. However, multiple clients can simultaneously communicate with the same device's default endpoint (EP0), which will result in their control transfers being serialized. 96 97For a client to communicate with a device, the client must: 98 99#. Open the device using the device's address. This lets the Host Library know that the client is using that device. 100#. Claim the interface(s) that will be used for communication. This prevents other clients from claiming the same interface(s). 101#. Send transfers to the endpoints in the claimed interface. The client's task is responsible for handling its own processing and events. 102 103 104.. ------------------------------------------------------ Usage -------------------------------------------------------- 105 106Usage 107----- 108 109The Host Library (and the underlying Host Stack) will not create any tasks. All tasks (i.e., the client tasks and the Daemon Task) will need to be created by the class drivers or the user. Instead, the Host Library provides two event handler functions that will handle all of the required Host Library processing, thus these functions should be called repeatedly from the client tasks and the Daemon Task. Therefore, the implementation of client tasks and the Daemon Task will be the largely centered around the invocation of these event handler functions. 110 111Host Library & Daemon Task 112^^^^^^^^^^^^^^^^^^^^^^^^^^ 113 114Basic Usage 115""""""""""" 116 117The Host Library API provides :cpp:func:`usb_host_lib_handle_events` to handle library events. This function should be called repeatedly, typically from the daemon task. Some notable features regarding :cpp:func:`usb_host_lib_handle_events` are: 118 119- The function can block until a library event needs handling 120- Event flags are returned on each invocation. These event flags are useful for knowing when the Host Library can be uninstalled. 121 122A bare-bones Daemon Task would resemble something like the following code snippet: 123 124.. code-block:: c 125 126 #include "usb/usb_host.h" 127 128 void daemon_task(void *arg) 129 { 130 ... 131 bool exit = false; 132 while (!exit) { 133 uint32_t event_flags; 134 usb_host_lib_handle_events(portMAX_DELAY, &event_flags); 135 if (event_flags & USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS) { 136 ... 137 } 138 if (event_flags & USB_HOST_LIB_EVENT_FLAGS_ALL_FREE) { 139 ... 140 } 141 ... 142 } 143 ... 144 } 145 146.. note:: 147 See the :example:`peripherals/usb/host/usb_host_lib` example for a full implementation of the Daemon Task 148 149Lifecycle 150""""""""" 151 152.. figure:: ../../../_static/usb_host_lib_lifecycle.png 153 :align: center 154 :alt: Graph of Typical USB Host Library Lifecycle 155 :figclass: align-center 156 157 Graph of Typical USB Host Library Lifecycle 158 159The graph above illustrates the typical lifecycle of the Host Library with multiple clients and devices. Specifically, the example involves... 160 161- two registered clients (Client 1 and Client 2) 162- two connected devices (Device 1 and Device 2), where Client 1 communicates with Device 1 and Client 2 communicates with Device 2. 163 164With reference the graph above, the typical lifecycle involves the following key stages. 165 1661. The Host Library is installed by calling :cpp:func:`usb_host_install`. 167 - Installation must be done before any other Host Library API is called. 168 - Where :cpp:func:`usb_host_install` is called (e.g., from the Daemon Task or another task) will depend on the synchronization logic between the Daemon Task, client tasks, and the rest of the system. 1692. Once the Host Library is installed, the clients can be registered by calling :cpp:func:`usb_host_client_register`. 170 - This is typically called from the client task (where the client task waits for a signal from the Daemon Task). 171 - This can be called elsewhere if necessary as long it is called after :cpp:func:`usb_host_install`. 1723. Device 1 connects and is then enumerated. 173 - Each registered client (in this case Client 1 and Client 2) are notified of the new device by way of the :cpp:enumerator:`USB_HOST_CLIENT_EVENT_NEW_DEV` event. 174 - Client 1 opens Device 1 and begins communication with it. 1754. Similarly Device 2 connects and is enumerated. 176 - Client 1 and 2 are notified of a new device (via a :cpp:enumerator:`USB_HOST_CLIENT_EVENT_NEW_DEV` event). 177 - Client 2 opens Device 2 and begins communication with it. 1785. Device 1 suddenly disconnects. 179 - Client 1 is notified by way of :cpp:enumerator:`USB_HOST_CLIENT_EVENT_DEV_GONE` and begins its cleanup. 180 - Client 2 is not notified as it has not opened Device 1. 1816. Client 1 completes its clean up and deregisters by calling :cpp:func:`usb_host_client_deregister`. 182 - This is typically called from the client task before the task exits. 183 - This can be called elsewhere if necessary as long as Client 1 has already completed its clean up. 1847. Client 2 completes its communication with Device 2. Client 2 then closes Device 2 and deregisters itself. 185 - The Daemon Task is notified of the deregistration of all clients by way the :c:macro:`USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS` event flag as Client 2 is the last client to deregister. 186 - Device 2 is still allocated (i.e., not freed) as it is still connected albeit not currently opened by any client. 1878. The Daemon Task decides to cleanup as there are no more clients. 188 - The Daemon Task must free Device 2 first by calling :cpp:func:`usb_host_device_free_all`. 189 - If :cpp:func:`usb_host_device_free_all` was able to free all devices, the function will return `ESP_OK` indicating that all devices have been freed. 190 - If :cpp:func:`usb_host_device_free_all` was unable to free all devices (e.g., because the device is still opened by a client), the function will return `ESP_ERR_NOT_FINISHED`. 191 - The Daemon Task must wait for :cpp:func:`usb_host_lib_handle_events` to return the :c:macro:`USB_HOST_LIB_EVENT_FLAGS_ALL_FREE` event flag in order to know when all devices have been freed. 1929. Once the Daemon Task has verified that all clients have deregistered and all devices have been freed, it can now uninstall the Host Library by calling :cpp:func:`usb_host_uninstall`. 193 194Clients & Class Driver 195^^^^^^^^^^^^^^^^^^^^^^ 196 197Basic Usage 198""""""""""" 199 200The Host Library API provides :cpp:func:`usb_host_client_handle_events` to handle a particular client's events. This function should be called repeatedly, typically from the client's task. Some notable features regarding :cpp:func:`usb_host_client_handle_events` are: 201 202- The function can block until a client event needs handling 203- The function's primary purpose is to call the various event handling callbacks when a client event occurs. 204 205The following callbacks are called from within :cpp:func:`usb_host_client_handle_events` thus allowing the client task to be notified of events. 206 207- The client event callback of type :cpp:type:`usb_host_client_event_cb_t` which delivers client event messages to the client. Client event messages indicate events such as the addition or removal of a device. 208- The USB transfer completion callback of type :cpp:type:`usb_transfer_cb_t` which indicates that a particular USB transfer previously submitted by the client has completed. 209 210.. note:: 211 Given that the callbacks are called from within :cpp:func:`usb_host_client_handle_events`, users should avoid blocking from within the callbacks as this will result in :cpp:func:`usb_host_client_handle_events` being blocked as well, thus preventing other pending client events from being handled. 212 213The following code snippet demonstrates a bare-bones host class driver and its client task. The code snippet contains: 214 215- A simple client task function ``client_task`` that calls :cpp:func:`usb_host_client_handle_events` in a loop. 216- Implementations of a client event callback and transfer completion callbacks. 217- Implementation of a simple state machine for the class driver. The class driver simply opens a device, sends an OUT transfer to EP1, then closes the device. 218 219.. code-block:: c 220 221 #include <string.h> 222 #include "usb/usb_host.h" 223 224 #define CLASS_DRIVER_ACTION_OPEN_DEV 0x01 225 #define CLASS_DRIVER_ACTION_TRANSFER 0x02 226 #define CLASS_DRIVER_ACTION_CLOSE_DEV 0x03 227 228 struct class_driver_control { 229 uint32_t actions; 230 uint8_t dev_addr; 231 usb_host_client_handle_t client_hdl; 232 usb_device_handle_t dev_hdl; 233 }; 234 235 static void client_event_cb(const usb_host_client_event_msg_t *event_msg, void *arg) 236 { 237 //This is function is called from within usb_host_client_handle_events(). Don't block and try to keep it short 238 struct class_driver_control *class_driver_obj = (struct class_driver_control *)arg; 239 switch (event_msg->event) { 240 case USB_HOST_CLIENT_EVENT_NEW_DEV: 241 class_driver_obj->actions |= CLASS_DRIVER_ACTION_OPEN_DEV; 242 class_driver_obj->dev_addr = event_msg->new_dev.address; //Store the address of the new device 243 break; 244 case USB_HOST_CLIENT_EVENT_DEV_GONE: 245 class_driver_obj->actions |= CLASS_DRIVER_ACTION_CLOSE_DEV; 246 break; 247 default: 248 break; 249 } 250 } 251 252 static void transfer_cb(usb_transfer_t *transfer) 253 { 254 //This is function is called from within usb_host_client_handle_events(). Don't block and try to keep it short 255 struct class_driver_control *class_driver_obj = (struct class_driver_control *)transfer->context; 256 printf("Transfer status %d, actual number of bytes transferred %d\n", transfer->status, transfer->actual_num_bytes); 257 class_driver_obj->actions |= CLASS_DRIVER_ACTION_CLOSE_DEV; 258 } 259 260 void client_task(void *arg) 261 { 262 ... //Wait until Host Library is installed 263 //Initialize class driver objects 264 struct class_driver_control class_driver_obj = {0}; 265 //Register the client 266 usb_host_client_config_t client_config = { 267 .is_synchronous = false, 268 .max_num_event_msg = 5, 269 .async = { 270 .client_event_callback = client_event_cb, 271 .callback_arg = &class_driver_obj, 272 } 273 }; 274 usb_host_client_register(&client_config, &class_driver_obj.client_hdl); 275 //Allocate a USB transfer 276 usb_transfer_t *transfer; 277 usb_host_transfer_alloc(1024, 0, &transfer); 278 279 //Event handling loop 280 bool exit = false; 281 while (!exit) { 282 //Call the client event handler function 283 usb_host_client_handle_events(class_driver_obj.client_hdl, portMAX_DELAY); 284 //Execute pending class driver actions 285 if (class_driver_obj.actions & CLASS_DRIVER_ACTION_OPEN_DEV) { 286 //Open the device and claim interface 1 287 usb_host_device_open(class_driver_obj.client_hdl, class_driver_obj.dev_addr, &class_driver_obj.dev_hdl); 288 usb_host_interface_claim(class_driver_obj.client_hdl, class_driver_obj.dev_hdl, 1, 0); 289 } 290 if (class_driver_obj.actions & CLASS_DRIVER_ACTION_TRANSFER) { 291 //Send an OUT transfer to EP1 292 memset(transfer->data_buffer, 0xAA, 1024); 293 transfer->num_bytes = 1024; 294 transfer->device_handle = class_driver_obj.dev_hdl; 295 transfer->bEndpointAddress = 0x01; 296 transfer->callback = transfer_cb; 297 transfer->context = (void *)&class_driver_obj; 298 usb_host_transfer_submit(transfer); 299 } 300 if (class_driver_obj.actions & CLASS_DRIVER_ACTION_CLOSE_DEV) { 301 //Release the interface and close the device 302 usb_host_interface_release(class_driver_obj.client_hdl, class_driver_obj.dev_hdl, 1); 303 usb_host_device_close(class_driver_obj.client_hdl, class_driver_obj.dev_hdl); 304 exit = true; 305 } 306 ... //Handle any other actions required by the class driver 307 } 308 309 //Cleanup class driver 310 usb_host_transfer_free(transfer); 311 usb_host_client_deregister(class_driver_obj.client_hdl); 312 ... //Delete the task and any other signal Daemon Task if required 313 } 314 315.. note:: 316 An actual host class driver will likely supported many more features, thus will have a much more complex state machine. A host class driver will likely also need to: 317 318 - Be able to open multiple devices 319 - Parse an opened device's descriptors to identify if the device is of the target class 320 - Communicate with multiple endpoints of an interface in a particular order 321 - Claim multiple interfaces of a device 322 - Handle various errors 323 324Lifecycle 325""""""""" 326 327The typical life cycle of a client task and class driver will go through the following stages: 328 329#. Wait for some signal regarding the Host Library being installed. 330#. Register the client via :cpp:func:`usb_host_client_register` and allocate any other class driver resources (e.g., allocating transfers using :cpp:func:`usb_host_transfer_alloc`). 331#. For each new device that the class driver needs to communicate with: 332 333 a. Check if the device is already connected via :cpp:func:`usb_host_device_addr_list_fill`. 334 b. If the device is not already connected, wait for a :cpp:enumerator:`USB_HOST_CLIENT_EVENT_NEW_DEV` event from the client event callback. 335 c. Open the device via :cpp:func:`usb_host_device_open`. 336 d. Parse the device and configuration descriptors via :cpp:func:`usb_host_get_device_descriptor` and :cpp:func:`usb_host_get_active_config_descriptor` respectively. 337 e. Claim the necessary interfaces of the device via :cpp:func:`usb_host_interface_claim`. 338 339#. Submit transfers to the device via :cpp:func:`usb_host_transfer_submit` or :cpp:func:`usb_host_transfer_submit_control`. 340#. Once an opened device is no longer needed by the class driver, or has disconnected (as indicated by a :cpp:enumerator:`USB_HOST_CLIENT_EVENT_DEV_GONE` event): 341 342 a. Stop any previously submitted transfers to the device's endpoints by calling :cpp:func:`usb_host_endpoint_halt` and :cpp:func:`usb_host_endpoint_flush` on those endpoints. 343 b. Release all previously claimed interfaces via :cpp:func:`usb_host_interface_release`. 344 c. Close the device via :cpp:func:`usb_host_device_close`. 345 346#. Deregister the client via :cpp:func:`usb_host_client_deregister` and free any other class driver resources. 347#. Delete the client task. Signal the Daemon Task if necessary. 348 349 350.. ---------------------------------------------------- Examples ------------------------------------------------------- 351 352Examples 353-------- 354 355Host Library Examples 356^^^^^^^^^^^^^^^^^^^^^ 357 358The :example:`peripherals/usb/host/usb_host_lib` demonstrates basic usage of the USB Host Library's API to implement a pseudo class driver. 359 360Class Driver Examples 361^^^^^^^^^^^^^^^^^^^^^ 362 363The USB Host Stack provides a number examples that implement host class drivers using the Host Library's API. 364 365CDC-ACM 366""""""" 367 368* A host class driver for the Communication Device Class (Abstract Control Model) is currently implemented as an example component (found via :example:`peripherals/usb/host/cdc/common/cdc_acm_host`). 369* The :example:`peripherals/usb/host/cdc/cdc_acm_host` example uses the CDC-ACM host driver component to communicate with CDC-ACM devices 370* The :example:`peripherals/usb/host/cdc/cdc_acm_bg96` example uses the CDC-ACM host driver component to communicate with non-compliant CDC-ACM devices (i.e., vendor-specific classes that support a subset of CDC-ACM features) such as the Quectel BG96 modem. 371 372MSC 373""" 374 375* A host class driver for the Mass Storage Class (Bulk-Only Transport) is current implemented as an example found via :example:`peripherals/usb/host/msc`. 376 377 378.. -------------------------------------------------- API Reference ---------------------------------------------------- 379 380API Reference 381------------- 382 383The API of the USB Host Library is separated into the following header files. However, it is sufficient for applications to only ``#include "usb/usb_host.h"`` and all of USB Host Library headers will also be included. 384 385- :component_file:`usb/include/usb/usb_host.h` contains the functions and types of the USB Host Library 386- :component_file:`usb/include/usb/usb_helpers.h` contains various helper functions that are related to the USB protocol such as descriptor parsing. 387- :component_file:`usb/include/usb/usb_types_stack.h` contains types that are are used across multiple layers of the USB Host stack. 388- :component_file:`usb/include/usb/usb_types_ch9.h` contains types and macros related to Chapter 9 of the USB2.0 specification (i.e., descriptors and standard requests). 389 390 391.. include-build-file:: inc/usb_host.inc 392 393.. include-build-file:: inc/usb_helpers.inc 394 395.. include-build-file:: inc/usb_types_stack.inc 396 397.. include-build-file:: inc/usb_types_ch9.inc 398