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