1.. _usb_device_stack: 2 3USB device support 4################## 5 6.. contents:: 7 :local: 8 :depth: 3 9 10Overview 11******** 12 13The USB device stack is a hardware independent interface between USB 14device controller driver and USB device class drivers or customer applications. 15It is a port of the LPCUSB device stack and has been modified and expanded 16over time. It provides the following functionalities: 17 18* Uses the :ref:`usb_dc_api` provided by the device controller drivers to interact with 19 the USB device controller. 20* Responds to standard device requests and returns standard descriptors, 21 essentially handling 'Chapter 9' processing, specifically the standard 22 device requests in table 9-3 from the universal serial bus specification 23 revision 2.0. 24* Provides a programming interface to be used by USB device classes or 25 customer applications. The APIs is described in 26 :zephyr_file:`include/zephyr/usb/usb_device.h` 27 28.. note:: 29 It is planned to deprecate all APIs listed in :ref:`usb_api` and the 30 functions that depend on them between Zephyr v4.0.0 and v4.1.0, and remove 31 them in v4.3.0. The new USB device support, represented by the APIs in 32 :ref:`usb_device_next_api`, will become the default in Zephyr v4.1.0. 33 34Supported USB classes 35********************* 36 37Audio 38===== 39 40There is an experimental implementation of the Audio class. It follows specification 41version 1.00 (``bcdADC 0x0100``) and supports synchronous synchronisation type only. 42See :zephyr:code-sample:`usb-audio-headphones-microphone` and 43:zephyr:code-sample:`usb-audio-headset` samples for reference. 44 45Bluetooth HCI USB transport layer 46================================= 47 48Bluetooth HCI USB transport layer implementation uses :ref:`bt_hci_raw` 49to expose HCI interface to the host. It is not fully in line with the description 50in the Bluetooth specification and consists only of an interface with the endpoint 51configuration: 52 53* HCI commands through control endpoint (host-to-device only) 54* HCI events through interrupt IN endpoint 55* ACL data through one bulk IN and one bulk OUT endpoints 56 57A second interface for the voice channels has not been implemented as there is 58no support for this type in :ref:`bluetooth`. It is not a big problem under Linux 59if HCI USB transport layer is the only interface that appears in the configuration, 60the btusb driver would not try to claim a second (isochronous) interface. 61The consequence is that if HCI USB is used in a composite configuration and is 62the first interface, then the Linux btusb driver will claim both the first and 63the next interface, preventing other composite functions from working. 64Because of this problem, HCI USB should not be used in a composite configuration. 65This problem is fixed in the implementation for new USB support. 66 67See :zephyr:code-sample:`bluetooth_hci_usb` sample for reference. 68 69.. _usb_device_cdc_acm: 70 71CDC ACM 72======= 73 74The CDC ACM class is used as backend for different subsystems in Zephyr. 75However, its configuration may not be easy for the inexperienced user. 76Below is a description of the different use cases and some pitfalls. 77 78The interface for CDC ACM user is :ref:`uart_api` driver API. 79But there are two important differences in behavior to a real UART controller: 80 81* Data transfer is only possible after the USB device stack has been 82 initialized and started, until then any data is discarded 83* If device is connected to the host, it still needs an application 84 on the host side which requests the data 85* The CDC ACM poll out implementation follows the API and blocks when the TX 86 ring buffer is full only if the hw-flow-control property is enabled and 87 called from a non-ISR context. 88 89The devicetree compatible property for CDC ACM UART is 90:dtcompatible:`zephyr,cdc-acm-uart`. 91CDC ACM support is automatically selected when USB device support is enabled 92and a compatible node in the devicetree sources is present. If necessary, 93CDC ACM support can be explicitly disabled by :kconfig:option:`CONFIG_USB_CDC_ACM`. 94About four CDC ACM UART instances can be defined and used, 95limited by the maximum number of supported endpoints on the controller. 96 97CDC ACM UART node is supposed to be child of a USB device controller node. 98Since the designation of the controller nodes varies from vendor to vendor, 99and our samples and application should be as generic as possible, 100the default USB device controller is usually assigned an ``zephyr_udc0`` 101node label. Often, CDC ACM UART is described in a devicetree overlay file 102and looks like this: 103 104.. code-block:: devicetree 105 106 &zephyr_udc0 { 107 cdc_acm_uart0: cdc_acm_uart0 { 108 compatible = "zephyr,cdc-acm-uart"; 109 label = "CDC_ACM_0"; 110 }; 111 }; 112 113Sample :zephyr:code-sample:`usb-cdc-acm` has similar overlay files. 114And since no special properties are present, it may seem overkill to use 115devicetree to describe CDC ACM UART. The motivation behind using devicetree 116is the easy interchangeability of a real UART controller and CDC ACM UART 117in applications. 118 119Console over CDC ACM UART 120------------------------- 121 122With the CDC ACM UART node from above and ``zephyr,console`` property of the 123chosen node, we can describe that CDC ACM UART is to be used with the console. 124A similar overlay file is used by the :zephyr:code-sample:`usb-cdc-acm-console` sample. 125 126.. code-block:: devicetree 127 128 / { 129 chosen { 130 zephyr,console = &cdc_acm_uart0; 131 }; 132 }; 133 134 &zephyr_udc0 { 135 cdc_acm_uart0: cdc_acm_uart0 { 136 compatible = "zephyr,cdc-acm-uart"; 137 label = "CDC_ACM_0"; 138 }; 139 }; 140 141Before the application uses the console, it is recommended to wait for 142the DTR signal: 143 144.. code-block:: c 145 146 const struct device *const dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_console)); 147 uint32_t dtr = 0; 148 149 if (usb_enable(NULL)) { 150 return; 151 } 152 153 while (!dtr) { 154 uart_line_ctrl_get(dev, UART_LINE_CTRL_DTR, &dtr); 155 k_sleep(K_MSEC(100)); 156 } 157 158 printk("nuqneH\n"); 159 160CDC ACM UART as backend 161----------------------- 162 163As for the console sample, it is possible to configure CDC ACM UART as 164backend for other subsystems by setting :ref:`devicetree-chosen-nodes` 165properties. 166 167List of few Zephyr specific chosen properties which can be used to select 168CDC ACM UART as backend for a subsystem or application: 169 170* ``zephyr,bt-c2h-uart`` used in Bluetooth, 171 for example see :zephyr:code-sample:`bluetooth_hci_uart` 172* ``zephyr,ot-uart`` used in OpenThread, 173 for example see :zephyr:code-sample:`openthread-coprocessor` 174* ``zephyr,shell-uart`` used by shell for serial backend, 175 for example see :zephyr_file:`samples/subsys/shell/shell_module` 176* ``zephyr,uart-mcumgr`` used by :zephyr:code-sample:`smp-svr` sample 177 178POSIX default tty ECHO mitigation 179--------------------------------- 180 181POSIX systems, like Linux, default to enabling ECHO on tty devices. Host side 182application can disable ECHO by calling ``open()`` on the tty device and issuing 183``ioctl()`` (preferably via ``tcsetattr()``) to disable echo if it is not desired. 184Unfortunately, there is an inherent race between the ``open()`` and ``ioctl()`` 185where the ECHO is enabled and any characters received (even if host application 186does not call ``read()``) will be echoed back. This issue is especially visible 187when the CDC ACM port is used without any real UART on the other side because 188there is no arbitrary delay due to baud rate. 189 190To mitigate the issue, Zephyr CDC ACM implementation arms IN endpoint with ZLP 191after device is configured. When the host reads the ZLP, which is pretty much 192the best indication that host application has opened the tty device, Zephyr will 193force :kconfig:option:`CONFIG_CDC_ACM_TX_DELAY_MS` millisecond delay before real 194payload is sent. This should allow sufficient time for first, and only first, 195application that opens the tty device to disable ECHO if ECHO is not desired. 196If ECHO is not desired at all from CDC ACM device it is best to set up udev rule 197to disable ECHO as soon as device is connected. 198 199ECHO is particurarly unwanted when CDC ACM instance is used for Zephyr shell, 200because the control characters to set color sent back to shell are interpreted 201as (invalid) command and user will see garbage as a result. While minicom does 202disable ECHO by default, on exit with reset it will restore the termios settings 203to whatever was set on entry. Therefore, if minicom is the first application to 204open the tty device, the exit with reset will enable ECHO back and thus set up 205a problem for the next application (which cannot be mitigated at Zephyr side). 206To prevent the issue it is recommended either to leave minicom without reset or 207to disable ECHO before minicom is started. 208 209DFU 210=== 211 212USB DFU class implementation is tightly coupled to :ref:`dfu` and :ref:`mcuboot_api`. 213This means that the target platform must support the :ref:`flash_img_api` API. 214 215See :zephyr:code-sample:`usb-dfu` sample for reference. 216 217USB Human Interface Devices (HID) support 218========================================= 219 220HID support abuses :ref:`device_model_api` simply to allow applications to use 221the :c:func:`device_get_binding`. Note that there is no HID device API as such, 222instead the interface is provided by :c:struct:`hid_ops`. 223The default instance name is ``HID_n``, where n can be {0, 1, 2, ...} depending on 224the :kconfig:option:`CONFIG_USB_HID_DEVICE_COUNT`. 225 226Each HID instance requires a HID report descriptor. The interface to the core 227and the report descriptor must be registered using :c:func:`usb_hid_register_device`. 228 229As the USB HID specification is not only used by the USB subsystem, the USB HID API 230reference is split into two parts, :ref:`usb_hid_common` and :ref:`usb_hid_device`. 231HID helper macros from :ref:`usb_hid_common` should be used to compose a 232HID report descriptor. Macro names correspond to those used in the USB HID specification. 233 234For the HID class interface, an IN interrupt endpoint is required for each instance, 235an OUT interrupt endpoint is optional. Thus, the minimum implementation requirement 236for :c:struct:`hid_ops` is to provide ``int_in_ready`` callback. 237 238.. code-block:: c 239 240 #define REPORT_ID 1 241 static bool configured; 242 static const struct device *hdev; 243 244 static void int_in_ready_cb(const struct device *dev) 245 { 246 static uint8_t report[2] = {REPORT_ID, 0}; 247 248 if (hid_int_ep_write(hdev, report, sizeof(report), NULL)) { 249 LOG_ERR("Failed to submit report"); 250 } else { 251 report[1]++; 252 } 253 } 254 255 static void status_cb(enum usb_dc_status_code status, const uint8_t *param) 256 { 257 if (status == USB_DC_RESET) { 258 configured = false; 259 } 260 261 if (status == USB_DC_CONFIGURED && !configured) { 262 int_in_ready_cb(hdev); 263 configured = true; 264 } 265 } 266 267 static const uint8_t hid_report_desc[] = { 268 HID_USAGE_PAGE(HID_USAGE_GEN_DESKTOP), 269 HID_USAGE(HID_USAGE_GEN_DESKTOP_UNDEFINED), 270 HID_COLLECTION(HID_COLLECTION_APPLICATION), 271 HID_LOGICAL_MIN8(0x00), 272 HID_LOGICAL_MAX16(0xFF, 0x00), 273 HID_REPORT_ID(REPORT_ID), 274 HID_REPORT_SIZE(8), 275 HID_REPORT_COUNT(1), 276 HID_USAGE(HID_USAGE_GEN_DESKTOP_UNDEFINED), 277 HID_INPUT(0x02), 278 HID_END_COLLECTION, 279 }; 280 281 static const struct hid_ops my_ops = { 282 .int_in_ready = int_in_ready_cb, 283 }; 284 285 int main(void) 286 { 287 int ret; 288 289 hdev = device_get_binding("HID_0"); 290 if (hdev == NULL) { 291 return -ENODEV; 292 } 293 294 usb_hid_register_device(hdev, hid_report_desc, sizeof(hid_report_desc), 295 &my_ops); 296 297 ret = usb_hid_init(hdev); 298 if (ret) { 299 return ret; 300 } 301 302 return usb_enable(status_cb); 303 } 304 305 306If the application wishes to receive output reports via the OUT interrupt endpoint, 307it must enable :kconfig:option:`CONFIG_ENABLE_HID_INT_OUT_EP` and provide 308``int_out_ready`` callback. 309The disadvantage of this is that Kconfig options such as 310:kconfig:option:`CONFIG_ENABLE_HID_INT_OUT_EP` or 311:kconfig:option:`CONFIG_HID_INTERRUPT_EP_MPS` apply to all instances. This design 312issue will be fixed in the HID class implementation for the new USB support. 313 314See :zephyr:code-sample:`usb-hid-mouse` sample for reference. 315 316Mass Storage Class 317================== 318 319MSC follows Bulk-Only Transport specification and uses :ref:`disk_access_api` to 320access and expose a RAM disk, emulated block device on a flash partition, 321or SD Card to the host. Only one disk instance can be exported at a time. 322 323The disc to be used by the implementation is set by the 324:kconfig:option:`CONFIG_MASS_STORAGE_DISK_NAME` and should be the same as the 325name used by the disc access driver that the application wants to expose to the 326host. Flash, RAM, and SDMMC/MMC disk drivers use node property ``disk-name`` to 327set the disk name. 328 329For the emulated block device on a flash partition, the flash partition and 330flash disk to be used must be described in the devicetree. If a storage partition 331is already described at the board level, application devicetree overlay must also 332delete ``storage_partition`` node first. :kconfig:option:`CONFIG_MASS_STORAGE_DISK_NAME` 333should be the same as ``disk-name`` property. 334 335.. code-block:: devicetree 336 337 /delete-node/ &storage_partition; 338 339 &mx25r64 { 340 partitions { 341 compatible = "fixed-partitions"; 342 #address-cells = <1>; 343 #size-cells = <1>; 344 345 storage_partition: partition@0 { 346 label = "storage"; 347 reg = <0x00000000 0x00020000>; 348 }; 349 }; 350 }; 351 352 / { 353 msc_disk0 { 354 compatible = "zephyr,flash-disk"; 355 partition = <&storage_partition>; 356 disk-name = "NAND"; 357 cache-size = <4096>; 358 }; 359 }; 360 361The ``disk-property`` "NAND" may be confusing, but it is simply how some file 362systems identifies the disc. Therefore, if the application also accesses the 363file system on the exposed disc, default names should be used, see 364:zephyr:code-sample:`usb-mass` sample for reference. 365 366Networking 367========== 368 369There are three implementations that work in a similar way, providing a virtual 370Ethernet connection between the remote (USB host) and Zephyr network support. 371 372* CDC ECM class, enabled with :kconfig:option:`CONFIG_USB_DEVICE_NETWORK_ECM` 373* CDC EEM class, enabled with :kconfig:option:`CONFIG_USB_DEVICE_NETWORK_EEM` 374* RNDIS support, enabled with :kconfig:option:`CONFIG_USB_DEVICE_NETWORK_RNDIS` 375 376See :zephyr:code-sample:`zperf` or :zephyr:code-sample:`socket-dumb-http-server` for reference. 377Typically, users will need to add a configuration file overlay to the build, 378such as :zephyr_file:`samples/net/zperf/overlay-netusb.conf`. 379 380Applications using RNDIS support should enable :kconfig:option:`CONFIG_USB_DEVICE_OS_DESC` 381for a better user experience on a host running Microsoft Windows OS. 382 383Binary Device Object Store (BOS) support 384**************************************** 385 386BOS handling can be enabled with Kconfig option :kconfig:option:`CONFIG_USB_DEVICE_BOS`. 387This option also has the effect of changing device descriptor ``bcdUSB`` to ``0210``. 388The application should register descriptors such as Capability Descriptor 389using :c:func:`usb_bos_register_cap`. Registered descriptors are added to the root 390BOS descriptor and handled by the stack. 391 392See :zephyr:code-sample:`webusb` sample for reference. 393 394Implementing a non-standard USB class 395************************************* 396 397The configuration of USB device is done in the stack layer. 398 399The following structures and callbacks need to be defined: 400 401* Part of USB Descriptor table 402* USB Endpoint configuration table 403* USB Device configuration structure 404* Endpoint callbacks 405* Optionally class, vendor and custom handlers 406 407For example, for the USB loopback application: 408 409.. literalinclude:: ../../../../subsys/usb/device/class/loopback.c 410 :language: c 411 :start-after: usb.rst config structure start 412 :end-before: usb.rst config structure end 413 :linenos: 414 415Endpoint configuration: 416 417.. literalinclude:: ../../../../subsys/usb/device/class/loopback.c 418 :language: c 419 :start-after: usb.rst endpoint configuration start 420 :end-before: usb.rst endpoint configuration end 421 :linenos: 422 423USB Device configuration structure: 424 425.. literalinclude:: ../../../../subsys/usb/device/class/loopback.c 426 :language: c 427 :start-after: usb.rst device config data start 428 :end-before: usb.rst device config data end 429 :linenos: 430 431 432The vendor device requests are forwarded by the USB stack core driver to the 433class driver through the registered vendor handler. 434 435For the loopback class driver, :c:func:`loopback_vendor_handler` processes 436the vendor requests: 437 438.. literalinclude:: ../../../../subsys/usb/device/class/loopback.c 439 :language: c 440 :start-after: usb.rst vendor handler start 441 :end-before: usb.rst vendor handler end 442 :linenos: 443 444The class driver waits for the :makevar:`USB_DC_CONFIGURED` device status code 445before transmitting any data. 446 447.. _testing_USB_native_sim: 448 449Interface number and endpoint address assignment 450************************************************ 451 452In USB terminology, a ``function`` is a device that provides a capability to the 453host, such as a HID class device that implements a keyboard. A function 454contains a collection of ``interfaces``; at least one interface is required. An 455interface may contain device ``endpoints``; for example, at least one input 456endpoint is required to implement a HID class device, and no endpoints are 457required to implement a USB DFU class. A USB device that combines functions is 458a multifunction USB device, for example, a combination of a HID class device 459and a CDC ACM device. 460 461With Zephyr RTOS USB support, various combinations are possible with built-in USB 462classes/functions or custom user implementations. The limitation is the number 463of available device endpoints. Each device endpoint is uniquely addressable. 464The endpoint address is a combination of endpoint direction and endpoint 465number, a four-bit value. Endpoint number zero is used for the default control 466method to initialize and configure a USB device. By specification, a maximum of 467``15 IN`` and ``15 OUT`` device endpoints are also available for use in functions. 468The actual number depends on the device controller used. Not all controllers 469support the maximum number of endpoints and all endpoint types. For example, a 470device controller might support one IN and one OUT isochronous endpoint, but 471only for endpoint number 8, resulting in endpoint addresses 0x88 and 0x08. 472Also, one controller may be able to have IN/OUT endpoints on the same endpoint 473number, interrupt IN endpoint 0x81 and bulk OUT endpoint 0x01, while the other 474may only be able to handle one endpoint per endpoint number. Information about 475the number of interfaces, interface associations, endpoint types, and addresses 476is provided to the host by the interface, interface specific, and endpoint 477descriptors. 478 479Host driver for specific function, uses interface and endpoint descriptor to 480obtain endpoint addresses, types, and other properties. This allows function 481host drivers to be generic, for example, a multi-function device consisting of 482one or more CDC ACM and one or more CDC ECM class implementations is possible 483and no specific drivers are required. 484 485Interface and endpoint descriptors of built-in USB class/function 486implementations in Zephyr RTOS typically have default interface numbers and 487endpoint addresses assigned in ascending order. During initialization, 488default interface numbers may be reassigned based on the number of interfaces in 489a given configuration. Endpoint addresses are reassigned based on controller 490capabilities, since certain endpoint combinations are not possible with every 491controller, and the number of interfaces in a given configuration. This also 492means that the device side class/function in the Zephyr RTOS must check the 493actual interface and endpoint descriptor values at runtime. 494This mechanism also allows as to provide generic samples and generic 495multifunction samples that are limited only by the resources provided by the 496controller, such as the number of endpoints and the size of the endpoint FIFOs. 497 498There may be host drivers for a specific function, for example in the Linux 499Kernel, where the function driver does not read interface and endpoint 500descriptors to check interface numbers or endpoint addresses, but instead uses 501hardcoded values. Therefore, the host driver cannot be used in a generic way, 502meaning it cannot be used with different device controllers and different 503device configurations in combination with other functions. This may also be 504because the driver is designed for a specific hardware and is not intended to 505be used with a clone of this specific hardware. On the contrary, if the driver 506is generic in nature and should work with different hardware variants, then it 507must not use hardcoded interface numbers and endpoint addresses. 508It is not possible to disable endpoint reassignment in Zephyr RTOS, which may 509prevent you from implementing a hardware-clone firmware. Instead, if possible, 510the host driver implementation should be fixed to use values from the interface 511and endpoint descriptor. 512 513Testing over USBIP in native_sim 514******************************** 515 516A virtual USB controller implemented through USBIP might be used to test the USB 517device stack. Follow the general build procedure to build the USB sample for 518the :ref:`native_sim <native_sim>` configuration. 519 520Run built sample with: 521 522.. code-block:: console 523 524 west build -t run 525 526In a terminal window, run the following command to list USB devices: 527 528.. code-block:: console 529 530 $ usbip list -r localhost 531 Exportable USB devices 532 ====================== 533 - 127.0.0.1 534 1-1: unknown vendor : unknown product (2fe3:0100) 535 : /sys/devices/pci0000:00/0000:00:01.2/usb1/1-1 536 : (Defined at Interface level) (00/00/00) 537 : 0 - Vendor Specific Class / unknown subclass / unknown protocol (ff/00/00) 538 539In a terminal window, run the following command to attach the USB device: 540 541.. code-block:: console 542 543 $ sudo usbip attach -r localhost -b 1-1 544 545The USB device should be connected to your Linux host, and verified with the 546following commands: 547 548.. code-block:: console 549 550 $ sudo usbip port 551 Imported USB devices 552 ==================== 553 Port 00: <Port in Use> at Full Speed(12Mbps) 554 unknown vendor : unknown product (2fe3:0100) 555 7-1 -> usbip://localhost:3240/1-1 556 -> remote bus/dev 001/002 557 $ lsusb -d 2fe3:0100 558 Bus 007 Device 004: ID 2fe3:0100 559 560USB Vendor and Product identifiers 561********************************** 562 563The USB Vendor ID for the Zephyr project is ``0x2FE3``. 564This USB Vendor ID must not be used when a vendor 565integrates Zephyr USB device support into its own product. 566 567Each USB :zephyr:code-sample-category:`sample<usb>` has its own unique Product ID. 568The USB maintainer, if one is assigned, or otherwise the Zephyr Technical 569Steering Committee, may allocate other USB Product IDs based on well-motivated 570and documented requests. 571 572The following Product IDs are currently used: 573 574+----------------------------------------------------+--------+ 575| Sample | PID | 576+====================================================+========+ 577| :zephyr:code-sample:`usb-cdc-acm` | 0x0001 | 578+----------------------------------------------------+--------+ 579| Reserved (previously: usb-cdc-acm-composite) | 0x0002 | 580+----------------------------------------------------+--------+ 581| Reserved (previously: usb-hid-cdc) | 0x0003 | 582+----------------------------------------------------+--------+ 583| :zephyr:code-sample:`usb-cdc-acm-console` | 0x0004 | 584+----------------------------------------------------+--------+ 585| :zephyr:code-sample:`usb-dfu` (Run-Time) | 0x0005 | 586+----------------------------------------------------+--------+ 587| Reserved (previously: usb-hid) | 0x0006 | 588+----------------------------------------------------+--------+ 589| :zephyr:code-sample:`usb-hid-mouse` | 0x0007 | 590+----------------------------------------------------+--------+ 591| :zephyr:code-sample:`usb-mass` | 0x0008 | 592+----------------------------------------------------+--------+ 593| :zephyr:code-sample:`testusb-app` | 0x0009 | 594+----------------------------------------------------+--------+ 595| :zephyr:code-sample:`webusb` | 0x000A | 596+----------------------------------------------------+--------+ 597| :zephyr:code-sample:`bluetooth_hci_usb` | 0x000B | 598+----------------------------------------------------+--------+ 599| Reserved (previously: bluetooth_hci_usb_h4) | 0x000C | 600+----------------------------------------------------+--------+ 601| Reserved (previously: wpan-usb) | 0x000D | 602+----------------------------------------------------+--------+ 603| :zephyr:code-sample:`uac2-explicit-feedback` | 0x000E | 604+----------------------------------------------------+--------+ 605| :zephyr:code-sample:`uac2-implicit-feedback` | 0x000F | 606+----------------------------------------------------+--------+ 607| :zephyr:code-sample:`usb-dfu` (DFU Mode) | 0xFFFF | 608+----------------------------------------------------+--------+ 609 610The USB device descriptor field ``bcdDevice`` (Device Release Number) represents 611the Zephyr kernel major and minor versions as a binary coded decimal value. 612