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 28The device stack and :ref:`usb_dc_api` have some limitations, such as not being 29able to support more than one controller instance at runtime and only supporting 30one USB device configuration. We are actively working on new USB support, which 31means we will continue to maintain the device stack described here until all 32supported USB classes are ported, but do not expect any new features or enhancements. 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 :ref:`bluetooth-hci-usb-sample` 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 86The devicetree compatible property for CDC ACM UART is 87:dtcompatible:`zephyr,cdc-acm-uart`. 88CDC ACM support is automatically selected when USB device support is enabled 89and a compatible node in the devicetree sources is present. If necessary, 90CDC ACM support can be explicitly disabled by :kconfig:option:`CONFIG_USB_CDC_ACM`. 91About four CDC ACM UART instances can be defined and used, 92limited by the maximum number of supported endpoints on the controller. 93 94CDC ACM UART node is supposed to be child of a USB device controller node. 95Since the designation of the controller nodes varies from vendor to vendor, 96and our samples and application should be as generic as possible, 97the default USB device controller is usually assigned an ``zephyr_udc0`` 98node label. Often, CDC ACM UART is described in a devicetree overlay file 99and looks like this: 100 101.. code-block:: devicetree 102 103 &zephyr_udc0 { 104 cdc_acm_uart0: cdc_acm_uart0 { 105 compatible = "zephyr,cdc-acm-uart"; 106 label = "CDC_ACM_0"; 107 }; 108 }; 109 110Samples :zephyr:code-sample:`usb-cdc-acm` and :zephyr:code-sample:`usb-hid-cdc` have similar overlay files. 111And since no special properties are present, it may seem overkill to use 112devicetree to describe CDC ACM UART. The motivation behind using devicetree 113is the easy interchangeability of a real UART controller and CDC ACM UART 114in applications. 115 116Console over CDC ACM UART 117------------------------- 118 119With the CDC ACM UART node from above and ``zephyr,console`` property of the 120chosen node, we can describe that CDC ACM UART is to be used with the console. 121A similar overlay file is used by the :zephyr:code-sample:`usb-cdc-acm-console` sample. 122 123.. code-block:: devicetree 124 125 / { 126 chosen { 127 zephyr,console = &cdc_acm_uart0; 128 }; 129 }; 130 131 &zephyr_udc0 { 132 cdc_acm_uart0: cdc_acm_uart0 { 133 compatible = "zephyr,cdc-acm-uart"; 134 label = "CDC_ACM_0"; 135 }; 136 }; 137 138Before the application uses the console, it is recommended to wait for 139the DTR signal: 140 141.. code-block:: c 142 143 const struct device *const dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_console)); 144 uint32_t dtr = 0; 145 146 if (usb_enable(NULL)) { 147 return; 148 } 149 150 while (!dtr) { 151 uart_line_ctrl_get(dev, UART_LINE_CTRL_DTR, &dtr); 152 k_sleep(K_MSEC(100)); 153 } 154 155 printk("nuqneH\n"); 156 157CDC ACM UART as backend 158----------------------- 159 160As for the console sample, it is possible to configure CDC ACM UART as 161backend for other subsystems by setting :ref:`devicetree-chosen-nodes` 162properties. 163 164List of few Zephyr specific chosen properties which can be used to select 165CDC ACM UART as backend for a subsystem or application: 166 167* ``zephyr,bt-c2h-uart`` used in Bluetooth, 168 for example see :ref:`bluetooth-hci-uart-sample` 169* ``zephyr,ot-uart`` used in OpenThread, 170 for example see :zephyr:code-sample:`coprocessor` 171* ``zephyr,shell-uart`` used by shell for serial backend, 172 for example see :zephyr_file:`samples/subsys/shell/shell_module` 173* ``zephyr,uart-mcumgr`` used by :zephyr:code-sample:`smp-svr` sample 174 175DFU 176=== 177 178USB DFU class implementation is tightly coupled to :ref:`dfu` and :ref:`mcuboot_api`. 179This means that the target platform must support the :ref:`flash_img_api` API. 180 181See :zephyr:code-sample:`usb-dfu` sample for reference. 182 183USB Human Interface Devices (HID) support 184========================================= 185 186HID support abuses :ref:`device_model_api` simply to allow applications to use 187the :c:func:`device_get_binding`. Note that there is no HID device API as such, 188instead the interface is provided by :c:struct:`hid_ops`. 189The default instance name is ``HID_n``, where n can be {0, 1, 2, ...} depending on 190the :kconfig:option:`CONFIG_USB_HID_DEVICE_COUNT`. 191 192Each HID instance requires a HID report descriptor. The interface to the core 193and the report descriptor must be registered using :c:func:`usb_hid_register_device`. 194 195As the USB HID specification is not only used by the USB subsystem, the USB HID API 196reference is split into two parts, :ref:`usb_hid_common` and :ref:`usb_hid_device`. 197HID helper macros from :ref:`usb_hid_common` should be used to compose a 198HID report descriptor. Macro names correspond to those used in the USB HID specification. 199 200For the HID class interface, an IN interrupt endpoint is required for each instance, 201an OUT interrupt endpoint is optional. Thus, the minimum implementation requirement 202for :c:struct:`hid_ops` is to provide ``int_in_ready`` callback. 203 204.. code-block:: c 205 206 #define REPORT_ID 1 207 static bool configured; 208 static const struct device *hdev; 209 210 static void int_in_ready_cb(const struct device *dev) 211 { 212 static uint8_t report[2] = {REPORT_ID, 0}; 213 214 if (hid_int_ep_write(hdev, report, sizeof(report), NULL)) { 215 LOG_ERR("Failed to submit report"); 216 } else { 217 report[1]++; 218 } 219 } 220 221 static void status_cb(enum usb_dc_status_code status, const uint8_t *param) 222 { 223 if (status == USB_DC_RESET) { 224 configured = false; 225 } 226 227 if (status == USB_DC_CONFIGURED && !configured) { 228 int_in_ready_cb(hdev); 229 configured = true; 230 } 231 } 232 233 static const uint8_t hid_report_desc[] = { 234 HID_USAGE_PAGE(HID_USAGE_GEN_DESKTOP), 235 HID_USAGE(HID_USAGE_GEN_DESKTOP_UNDEFINED), 236 HID_COLLECTION(HID_COLLECTION_APPLICATION), 237 HID_LOGICAL_MIN8(0x00), 238 HID_LOGICAL_MAX16(0xFF, 0x00), 239 HID_REPORT_ID(REPORT_ID), 240 HID_REPORT_SIZE(8), 241 HID_REPORT_COUNT(1), 242 HID_USAGE(HID_USAGE_GEN_DESKTOP_UNDEFINED), 243 HID_INPUT(0x02), 244 HID_END_COLLECTION, 245 }; 246 247 static const struct hid_ops my_ops = { 248 .int_in_ready = int_in_ready_cb, 249 }; 250 251 int main(void) 252 { 253 int ret; 254 255 hdev = device_get_binding("HID_0"); 256 if (hdev == NULL) { 257 return -ENODEV; 258 } 259 260 usb_hid_register_device(hdev, hid_report_desc, sizeof(hid_report_desc), 261 &my_ops); 262 263 ret = usb_hid_init(hdev); 264 if (ret) { 265 return ret; 266 } 267 268 return usb_enable(status_cb); 269 } 270 271 272If the application wishes to receive output reports via the OUT interrupt endpoint, 273it must enable :kconfig:option:`CONFIG_ENABLE_HID_INT_OUT_EP` and provide 274``int_out_ready`` callback. 275The disadvantage of this is that Kconfig options such as 276:kconfig:option:`CONFIG_ENABLE_HID_INT_OUT_EP` or 277:kconfig:option:`CONFIG_HID_INTERRUPT_EP_MPS` apply to all instances. This design 278issue will be fixed in the HID class implementation for the new USB support. 279 280See :zephyr:code-sample:`usb-hid` or :zephyr:code-sample:`usb-hid-mouse` sample for reference. 281 282Mass Storage Class 283================== 284 285MSC follows Bulk-Only Transport specification and uses :ref:`disk_access_api` to 286access and expose a RAM disk, emulated block device on a flash partition, 287or SD Card to the host. Only one disk instance can be exported at a time. 288 289The disc to be used by the implementation is set by the 290:kconfig:option:`CONFIG_MASS_STORAGE_DISK_NAME` and should be the same as the name 291used by the disc access driver that the application wants to expose to the host. 292SD card disk drivers use options :kconfig:option:`CONFIG_MMC_VOLUME_NAME` or 293:kconfig:option:`CONFIG_SDMMC_VOLUME_NAME`, and flash and RAM disk drivers use 294node property ``disk-name`` to set the disk name. 295 296For the emulated block device on a flash partition, the flash partition and 297flash disk to be used must be described in the devicetree. If a storage partition 298is already described at the board level, application devicetree overlay must also 299delete ``storage_partition`` node first. :kconfig:option:`CONFIG_MASS_STORAGE_DISK_NAME` 300should be the same as ``disk-name`` property. 301 302.. code-block:: devicetree 303 304 /delete-node/ &storage_partition; 305 306 &mx25r64 { 307 partitions { 308 compatible = "fixed-partitions"; 309 #address-cells = <1>; 310 #size-cells = <1>; 311 312 storage_partition: partition@0 { 313 label = "storage"; 314 reg = <0x00000000 0x00020000>; 315 }; 316 }; 317 }; 318 319 / { 320 msc_disk0 { 321 compatible = "zephyr,flash-disk"; 322 partition = <&storage_partition>; 323 disk-name = "NAND"; 324 cache-size = <4096>; 325 }; 326 }; 327 328The ``disk-property`` "NAND" may be confusing, but it is simply how some file 329systems identifies the disc. Therefore, if the application also accesses the 330file system on the exposed disc, default names should be used, see 331:zephyr:code-sample:`usb-mass` sample for reference. 332 333Networking 334========== 335 336There are three implementations that work in a similar way, providing a virtual 337Ethernet connection between the remote (USB host) and Zephyr network support. 338 339* CDC ECM class, enabled with :kconfig:option:`CONFIG_USB_DEVICE_NETWORK_ECM` 340* CDC EEM class, enabled with :kconfig:option:`CONFIG_USB_DEVICE_NETWORK_EEM` 341* RNDIS support, enabled with :kconfig:option:`CONFIG_USB_DEVICE_NETWORK_RNDIS` 342 343See :zephyr:code-sample:`zperf` or :zephyr:code-sample:`socket-dumb-http-server` for reference. 344Typically, users will need to add a configuration file overlay to the build, 345such as :zephyr_file:`samples/net/zperf/overlay-netusb.conf`. 346 347Applications using RNDIS support should enable :kconfig:option:`CONFIG_USB_DEVICE_OS_DESC` 348for a better user experience on a host running Microsoft Windows OS. 349 350Binary Device Object Store (BOS) support 351**************************************** 352 353BOS handling can be enabled with Kconfig option :kconfig:option:`CONFIG_USB_DEVICE_BOS`. 354This option also has the effect of changing device descriptor ``bcdUSB`` to ``0210``. 355The application should register descriptors such as Capability Descriptor 356using :c:func:`usb_bos_register_cap`. Registered descriptors are added to the root 357BOS descriptor and handled by the stack. 358 359See :zephyr:code-sample:`webusb` sample for reference. 360 361Implementing a non-standard USB class 362************************************* 363 364The configuration of USB device is done in the stack layer. 365 366The following structures and callbacks need to be defined: 367 368* Part of USB Descriptor table 369* USB Endpoint configuration table 370* USB Device configuration structure 371* Endpoint callbacks 372* Optionally class, vendor and custom handlers 373 374For example, for the USB loopback application: 375 376.. literalinclude:: ../../../../subsys/usb/device/class/loopback.c 377 :language: c 378 :start-after: usb.rst config structure start 379 :end-before: usb.rst config structure end 380 :linenos: 381 382Endpoint configuration: 383 384.. literalinclude:: ../../../../subsys/usb/device/class/loopback.c 385 :language: c 386 :start-after: usb.rst endpoint configuration start 387 :end-before: usb.rst endpoint configuration end 388 :linenos: 389 390USB Device configuration structure: 391 392.. literalinclude:: ../../../../subsys/usb/device/class/loopback.c 393 :language: c 394 :start-after: usb.rst device config data start 395 :end-before: usb.rst device config data end 396 :linenos: 397 398 399The vendor device requests are forwarded by the USB stack core driver to the 400class driver through the registered vendor handler. 401 402For the loopback class driver, :c:func:`loopback_vendor_handler` processes 403the vendor requests: 404 405.. literalinclude:: ../../../../subsys/usb/device/class/loopback.c 406 :language: c 407 :start-after: usb.rst vendor handler start 408 :end-before: usb.rst vendor handler end 409 :linenos: 410 411The class driver waits for the :makevar:`USB_DC_CONFIGURED` device status code 412before transmitting any data. 413 414.. _testing_USB_native_posix: 415 416Testing over USPIP in native_posix 417*********************************** 418 419A virtual USB controller implemented through USBIP might be used to test the USB 420device stack. Follow the general build procedure to build the USB sample for 421the native_posix configuration. 422 423Run built sample with: 424 425.. code-block:: console 426 427 west build -t run 428 429In a terminal window, run the following command to list USB devices: 430 431.. code-block:: console 432 433 $ usbip list -r localhost 434 Exportable USB devices 435 ====================== 436 - 127.0.0.1 437 1-1: unknown vendor : unknown product (2fe3:0100) 438 : /sys/devices/pci0000:00/0000:00:01.2/usb1/1-1 439 : (Defined at Interface level) (00/00/00) 440 : 0 - Vendor Specific Class / unknown subclass / unknown protocol (ff/00/00) 441 442In a terminal window, run the following command to attach the USB device: 443 444.. code-block:: console 445 446 $ sudo usbip attach -r localhost -b 1-1 447 448The USB device should be connected to your Linux host, and verified with the 449following commands: 450 451.. code-block:: console 452 453 $ sudo usbip port 454 Imported USB devices 455 ==================== 456 Port 00: <Port in Use> at Full Speed(12Mbps) 457 unknown vendor : unknown product (2fe3:0100) 458 7-1 -> usbip://localhost:3240/1-1 459 -> remote bus/dev 001/002 460 $ lsusb -d 2fe3:0100 461 Bus 007 Device 004: ID 2fe3:0100 462 463USB Vendor and Product identifiers 464********************************** 465 466The USB Vendor ID for the Zephyr project is ``0x2FE3``. 467This USB Vendor ID must not be used when a vendor 468integrates Zephyr USB device support into its own product. 469 470Each USB :ref:`sample<usb-samples>` has its own unique Product ID. 471The USB maintainer, if one is assigned, or otherwise the Zephyr Technical 472Steering Committee, may allocate other USB Product IDs based on well-motivated 473and documented requests. 474 475The following Product IDs are currently used: 476 477+----------------------------------------------------+--------+ 478| Sample | PID | 479+====================================================+========+ 480| :zephyr:code-sample:`usb-cdc-acm` | 0x0001 | 481+----------------------------------------------------+--------+ 482| :zephyr:code-sample:`usb-cdc-acm-composite` | 0x0002 | 483+----------------------------------------------------+--------+ 484| :zephyr:code-sample:`usb-hid-cdc` | 0x0003 | 485+----------------------------------------------------+--------+ 486| :zephyr:code-sample:`usb-cdc-acm-console` | 0x0004 | 487+----------------------------------------------------+--------+ 488| :zephyr:code-sample:`usb-dfu` | 0x0005 | 489+----------------------------------------------------+--------+ 490| :zephyr:code-sample:`usb-hid` | 0x0006 | 491+----------------------------------------------------+--------+ 492| :zephyr:code-sample:`usb-hid-mouse` | 0x0007 | 493+----------------------------------------------------+--------+ 494| :zephyr:code-sample:`usb-mass` | 0x0008 | 495+----------------------------------------------------+--------+ 496| :zephyr:code-sample:`testusb-app` | 0x0009 | 497+----------------------------------------------------+--------+ 498| :zephyr:code-sample:`webusb` | 0x000A | 499+----------------------------------------------------+--------+ 500| :ref:`bluetooth-hci-usb-sample` | 0x000B | 501+----------------------------------------------------+--------+ 502| :ref:`bluetooth-hci-usb-h4-sample` | 0x000C | 503+----------------------------------------------------+--------+ 504| :zephyr:code-sample:`wpan-usb` | 0x000D | 505+----------------------------------------------------+--------+ 506 507The USB device descriptor field ``bcdDevice`` (Device Release Number) represents 508the Zephyr kernel major and minor versions as a binary coded decimal value. 509