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