diff options
| author | HiFiPhile <[email protected]> | 2026-08-01 19:22:52 +0200 |
|---|---|---|
| committer | HiFiPhile <[email protected]> | 2026-08-01 19:22:52 +0200 |
| commit | cd9bbed39f5851d5e4dc64271f18b8db777acb53 (patch) | |
| tree | 83866c4127a6d808ba9eb6d543fe5d3787cd3af2 /docs/reference/class | |
| parent | f3021b337fcea154b898489c417d428c92f88e92 (diff) | |
doc: add class docscodex/class-reference-docs
Signed-off-by: HiFiPhile <[email protected]>
Diffstat (limited to 'docs/reference/class')
| -rw-r--r-- | docs/reference/class/audio.rst | 131 | ||||
| -rw-r--r-- | docs/reference/class/bluetooth.rst | 75 | ||||
| -rw-r--r-- | docs/reference/class/cdc.rst | 169 | ||||
| -rw-r--r-- | docs/reference/class/device.rst | 159 | ||||
| -rw-r--r-- | docs/reference/class/dfu.rst | 92 | ||||
| -rw-r--r-- | docs/reference/class/hid.rst | 168 | ||||
| -rw-r--r-- | docs/reference/class/host.rst | 142 | ||||
| -rw-r--r-- | docs/reference/class/index.rst | 96 | ||||
| -rw-r--r-- | docs/reference/class/midi.rst | 214 | ||||
| -rw-r--r-- | docs/reference/class/msc.rst | 125 | ||||
| -rw-r--r-- | docs/reference/class/mtp.rst | 112 | ||||
| -rw-r--r-- | docs/reference/class/network.rst | 121 | ||||
| -rw-r--r-- | docs/reference/class/printer.rst | 91 | ||||
| -rw-r--r-- | docs/reference/class/usbtmc.rst | 110 | ||||
| -rw-r--r-- | docs/reference/class/vendor.rst | 118 | ||||
| -rw-r--r-- | docs/reference/class/video.rst | 104 |
16 files changed, 2027 insertions, 0 deletions
diff --git a/docs/reference/class/audio.rst b/docs/reference/class/audio.rst new file mode 100644 index 000000000..6e86dff8c --- /dev/null +++ b/docs/reference/class/audio.rst @@ -0,0 +1,131 @@ +***** +Audio +***** + +Role: device only. TinyUSB supports USB Audio Class 1.0 and 2.0 streaming. +The descriptors define the topology, formats, channels, rates, controls, and +alternate settings; the application supplies or consumes the audio samples. + +Start from an example +===================== + +Audio descriptors and buffer sizes are tightly coupled. Copy the closest +example, confirm that it enumerates, and then change one property at a time: + +* :doc:`../../examples/device/audio_test` -- one-channel UAC2 microphone; +* :doc:`../../examples/device/audio_4_channel_mic` -- four-channel microphone; +* :doc:`../../examples/device/uac2_speaker_fb` -- speaker with feedback; +* :doc:`../../examples/device/uac2_headset` -- bidirectional headset; +* :doc:`../../examples/device/audio_test_multi_rate` -- UAC1 at full speed, + UAC2 at high speed, with multiple rates. + +Configuration +============= + +Set ``CFG_TUD_AUDIO`` to the number of audio functions. The principal options +are: + +.. list-table:: + :header-rows: 1 + :widths: 37 16 47 + + * - Option + - Default + - What it controls + * - ``CFG_TUD_AUDIO_CTRL_BUF_SZ`` + - ``64`` bytes + - Largest class control payload, such as a RANGE or channel-cluster + response. Increase it to fit the largest advertised control. + * - ``CFG_TUD_AUDIO_ENABLE_EP_IN`` + - ``0`` + - Enables microphone/device-to-host streaming. + * - ``CFG_TUD_AUDIO_ENABLE_EP_OUT`` + - ``0`` + - Enables speaker/host-to-device streaming. + * - ``CFG_TUD_AUDIO_FUNC_n_EP_IN_SZ_MAX`` / + ``CFG_TUD_AUDIO_FUNC_n_EP_OUT_SZ_MAX`` + - Required per enabled direction + - Maximum endpoint packet size across that function's alternate settings. + * - ``CFG_TUD_AUDIO_FUNC_n_EP_IN_SW_BUF_SZ`` / + ``CFG_TUD_AUDIO_FUNC_n_EP_OUT_SW_BUF_SZ`` + - ``0`` + - Software FIFO size. Set it to at least the corresponding maximum + endpoint size when using the FIFO APIs. + * - ``CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL`` + - ``1`` + - Adapts IN packet consumption to the FIFO fill level to reduce + underruns/overruns. + * - ``CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP`` + - ``0`` + - Enables an explicit feedback endpoint, normally required by an + asynchronous speaker. + * - ``CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP`` + - ``0`` + - Enables the AudioControl interrupt endpoint for status notifications. + +For each enabled direction, define the maximum endpoint size used by any +advertised alternate setting, for example +``CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX``. A software FIFO such as +``CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ`` must be at least that large. Use +``TUD_AUDIO_EP_SIZE()`` as the examples do; high-speed audio has more service +intervals per millisecond than full-speed audio. + +Data path +========= + +.. list-table:: + :header-rows: 1 + :widths: 34 66 + + * - Operation + - Main API + * - ``tud_audio_mounted()`` / ``tud_audio_version()`` + - Tests whether function zero is configured and returns its negotiated + Audio Class version. + * - ``tud_audio_available()`` / ``tud_audio_read()`` + - Reports and removes speaker bytes from the OUT software FIFO. The read + count can be shorter than requested. + * - ``tud_audio_write()`` + - Copies microphone bytes into the IN software FIFO and returns the number + accepted. + * - ``tud_audio_clear_ep_*_ff()`` + - Discards queued samples in the selected endpoint FIFO, useful when a + streaming alternate setting closes. + * - ``tud_audio_get_ep_*_ff()`` + - Returns the underlying FIFO object for advanced zero-copy or DMA + integration; the application must preserve its invariants. + * - ``tud_audio_n_fb_set()`` + - Supplies the feedback value for one audio function when application + feedback mode is used. Pass 16.16 samples per frame; TinyUSB converts + it to full-speed 10.14 format when required. + * - ``tud_audio_feedback_update()`` + - Updates internally calculated feedback from elapsed master-clock cycles + and returns the current 16.16 value, or zero on error. + * - ``tud_audio_n_*()`` + - Selects a function explicitly with ``func_id``; helpers without ``n`` + operate on function zero. + +The host starts and stops a stream by selecting interface alternate settings. +Use ``tud_audio_set_itf_cb()`` and ``tud_audio_set_itf_close_ep_cb()`` to start +or stop the application-side I2S/DMA path. Do not produce or consume samples +merely because the device is mounted; wait until the streaming interface is +active. + +Control requests +================ + +Implement the ``tud_audio_get_req_*_cb()`` and ``tud_audio_set_req_*_cb()`` +callbacks for every control advertised by the descriptors, such as clock +frequency, clock validity, mute, and volume. A descriptor that advertises a +control but stalls its normal requests is likely to be rejected or behave +poorly on a host. + +Asynchronous speakers normally need a feedback endpoint. Enable +``CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP`` and either configure the feedback method +through ``tud_audio_feedback_params_cb()`` or provide feedback with +``tud_audio_n_fb_set()``. Begin with the speaker-feedback example; incorrect +feedback causes periodic underruns or overruns even when the nominal sample +rates match. + +Specifications used: *USB Device Class Definition for Audio Devices*, Release +1.0 and Release 2.0, plus *Audio Data Formats*, Release 2.0. diff --git a/docs/reference/class/bluetooth.rst b/docs/reference/class/bluetooth.rst new file mode 100644 index 000000000..26e0ee2a9 --- /dev/null +++ b/docs/reference/class/bluetooth.rst @@ -0,0 +1,75 @@ +************* +Bluetooth HCI +************* + +Role: device only. This driver transports Bluetooth HCI commands, events, and +ACL data over USB. It does not implement a Bluetooth controller, Link Manager, +or host stack; the application must provide that functionality. + +Configuration and descriptors +============================= + +Enable ``CFG_TUD_BTH`` and use ``TUD_BTH_DESCRIPTOR`` in the configuration +descriptor. + +.. list-table:: + :header-rows: 1 + :widths: 38 17 45 + + * - Option + - Default + - What it controls + * - ``CFG_TUD_BTH_ISO_ALT_COUNT`` + - Required + - Number of isochronous voice alternate settings. Pass one paired + IN/OUT packet size per setting to ``TUD_BTH_DESCRIPTOR``. + * - ``CFG_TUD_BTH_EVENT_EPSIZE`` + - ``16`` bytes + - Maximum HCI event interrupt-IN packet. + * - ``CFG_TUD_BTH_DATA_EPSIZE`` + - ``64`` bytes + - ACL bulk endpoint packet size. Keep it consistent with the descriptor + and active bus speed. + * - ``CFG_TUD_BTH_HISTORICAL_COMPATIBLE`` + - ``0`` + - Uses the legacy HCI command request value required by some historical + controller implementations. + +Set ``CFG_TUD_BTH_HISTORICAL_COMPATIBLE`` only for a controller that requires +the legacy ``bRequest = 0xe0`` behavior described by the Bluetooth Core +specification. It is not a general compatibility switch. + +Data path +========= + +.. list-table:: + :header-rows: 1 + :widths: 38 62 + + * - API or callback + - What it does + * - ``tud_bt_hci_cmd_cb()`` + - Delivers one host HCI command to the controller implementation. + * - ``tud_bt_acl_data_received_cb()`` + - Delivers received host-to-controller ACL bytes. + * - ``tud_bt_event_send()`` + - Queues a controller-to-host HCI event; ``false`` means it was not + accepted. + * - ``tud_bt_acl_data_send()`` + - Queues controller-to-host ACL data; ``false`` means it was not accepted. + * - ``tud_bt_event_sent_cb()`` / + ``tud_bt_acl_data_sent_cb()`` + - Reports completion and releases the corresponding application-owned + send buffer. + +The host delivers HCI commands through ``tud_bt_hci_cmd_cb()`` and ACL data +through ``tud_bt_acl_data_received_cb()``. The controller sends HCI events with +``tud_bt_event_send()`` and ACL data with ``tud_bt_acl_data_send()``. + +The send APIs do not copy the whole packet. Keep each buffer valid and +unchanged until ``tud_bt_event_sent_cb()`` or ``tud_bt_acl_data_sent_cb()``. +Check the boolean return value before considering a packet queued. + +There is currently no dedicated Bluetooth device example. Use the public API +in ``src/class/bth/bth_device.h`` together with the Bluetooth Core USB +Transport and HCI packet formats. diff --git a/docs/reference/class/cdc.rst b/docs/reference/class/cdc.rst new file mode 100644 index 000000000..13f0b463d --- /dev/null +++ b/docs/reference/class/cdc.rst @@ -0,0 +1,169 @@ +********** +CDC Serial +********** + +Roles: device and host. The standard driver implements CDC ACM virtual serial +ports. The host driver can also expose FTDI, CP210x, CH34x, and PL2303 USB +serial adapters through the same ``tuh_cdc_*`` API. + +Device +====== + +Enable ``CFG_TUD_CDC`` with the required port count and add one +``TUD_CDC_DESCRIPTOR`` per port. + +.. list-table:: + :header-rows: 1 + :widths: 36 18 46 + + * - Option + - Default + - What it controls + * - ``CFG_TUD_CDC_RX_BUFSIZE`` / ``CFG_TUD_CDC_TX_BUFSIZE`` + - Device bulk maximum + - Software FIFO capacity in each direction. Larger FIFOs absorb longer + application scheduling gaps. + * - ``CFG_TUD_CDC_RX_EPSIZE`` / ``CFG_TUD_CDC_TX_EPSIZE`` + - Device bulk maximum + - Endpoint transfer buffer and descriptor packet size. Use + speed-appropriate values. + * - ``CFG_TUD_CDC_NOTIFY`` + - ``0`` + - Enables the interrupt notification endpoint and serial-state API. + * - ``CFG_TUD_CDC_RX_PERSISTENT`` / ``CFG_TUD_CDC_TX_PERSISTENT`` + - ``0`` + - Keeps the corresponding FIFO contents across disconnect/reconnect. + Enable only when stale bytes are intentional. + * - ``CFG_TUD_CDC_RX_NEED_ZLP`` + - ``0`` + - Enables multi-packet receive transfers terminated by a host-sent + zero-length packet. Enable only when the host side supports this + framing. + * - ``CFG_TUD_CDC_TX_OVERWRITABLE_IF_NOT_CONNECTED`` + - ``1`` + - Allows writes made before DTR connection to replace old queued data + rather than permanently filling the FIFO. + +Use speed-dependent values from an example when the device can enumerate at +high speed. ``CFG_TUD_CDC_NOTIFY`` enables serial-state notifications. + +The common data path is: + +.. code-block:: c + + void tud_cdc_rx_cb(uint8_t itf) { + uint8_t buf[64]; + uint32_t count = tud_cdc_n_available(itf); + uint32_t room = tud_cdc_n_write_available(itf); + if (count > sizeof(buf)) count = sizeof(buf); + if (count > room) count = room; + + count = tud_cdc_n_read(itf, buf, count); + if (count && tud_cdc_n_write(itf, buf, count) == count) { + tud_cdc_n_write_flush(itf); + } + } + +Use ``tud_cdc_n_connected()`` when transmission should depend on DTR. A port +can be mounted while a terminal has not opened it. Handle line settings in +``tud_cdc_line_state_cb()`` and ``tud_cdc_line_coding_cb()`` if they affect the +physical UART; TinyUSB does not configure that UART for you. + +.. list-table:: + :header-rows: 1 + :widths: 39 61 + + * - Device API or callback + - What it does + * - ``tud_cdc_n_connected()`` / ``tud_cdc_n_ready()`` + - Tests DTR connection, or whether the port is connected and can accept + output now. + * - ``tud_cdc_n_available()`` / ``tud_cdc_n_read()`` + - Reports and removes bytes received from the host. + * - ``tud_cdc_n_write_available()`` / ``tud_cdc_n_write()`` + - Reports TX FIFO room and copies as many bytes as fit; preserve any + unwritten remainder. + * - ``tud_cdc_n_write_flush()`` + - Starts transmission of buffered bytes without waiting for the FIFO to + fill. + * - ``tud_cdc_rx_cb()`` / ``tud_cdc_tx_complete_cb()`` + - Announces newly buffered receive data or completion of a transmit + transfer. + * - ``tud_cdc_line_state_cb()`` / ``tud_cdc_line_coding_cb()`` + - Reports host DTR/RTS and baud/data/parity/stop settings so a UART bridge + can apply them. + +See :doc:`../../examples/device/cdc_dual_ports` for multiple ports and +:doc:`../../examples/device/cdc_msc` for a composite device. + +Host +==== + +Set ``CFG_TUH_CDC`` to the required number of serial interfaces. Enable only +the adapter families needed by the product: + +.. code-block:: c + + #define CFG_TUH_CDC 1 + #define CFG_TUH_CDC_FTDI 1 + #define CFG_TUH_CDC_CP210X 1 + #define CFG_TUH_CDC_CH34X 1 + #define CFG_TUH_CDC_PL2303 1 + +The RX/TX software FIFO and endpoint buffers default to +``TUH_EPSIZE_BULK_MAX`` through ``CFG_TUH_CDC_RX_BUFSIZE``, +``CFG_TUH_CDC_TX_BUFSIZE``, ``CFG_TUH_CDC_RX_EPSIZE``, and +``CFG_TUH_CDC_TX_EPSIZE``. Increase FIFO sizes to tolerate application +latency; endpoint sizes normally stay at the host bulk maximum. Optional +``CFG_TUH_CDC_LINE_CODING_ON_ENUM`` and +``CFG_TUH_CDC_LINE_CONTROL_ON_ENUM`` values apply initial serial settings as +part of enumeration. + +``tuh_cdc_mount_cb(idx)`` reports a ready interface. Read data in +``tuh_cdc_rx_cb(idx)`` using ``tuh_cdc_read_available()`` and +``tuh_cdc_read()``. Queue output with ``tuh_cdc_write()`` and call +``tuh_cdc_write_flush()`` when it should leave promptly. + +Line-control functions such as ``tuh_cdc_set_baudrate()`` and +``tuh_cdc_set_line_coding()`` accept a completion callback. Their ``_sync`` +forms block and should only be used where the host task can continue running. +Support varies by adapter family; in particular, the combined line-coding call +is not implemented for every non-CDC adapter. + +.. list-table:: + :header-rows: 1 + :widths: 39 61 + + * - Host API or callback + - What it does + * - ``tuh_cdc_mounted()`` / ``tuh_cdc_itf_get_info()`` + - Tests an interface index and returns its address, interface descriptor, + and serial-driver type. + * - ``tuh_cdc_read_available()`` / ``tuh_cdc_read()`` + - Reports and removes bytes buffered from the serial device. + * - ``tuh_cdc_write()`` / ``tuh_cdc_write_flush()`` + - Copies output into the class FIFO and starts a USB transfer. + * - ``tuh_cdc_set_control_line_state()`` / + ``tuh_cdc_set_line_coding()`` + - Queues DTR/RTS or baud/framing changes and calls the supplied completion + callback. + * - ``tuh_cdc_mount_cb()`` / ``tuh_cdc_umount_cb()`` + - Creates or removes application state for a serial interface index. + * - ``tuh_cdc_rx_cb()`` / ``tuh_cdc_tx_complete_cb()`` + - Announces buffered input or completion of queued class output. + +The :doc:`../../examples/host/cdc_msc_hid` example shows enumeration, 115200 +8N1 setup, and bidirectional I/O. + +Practical notes +=============== + +* USB CDC transfers bytes, not UART timing. Baud rate and framing are host + requests that an application may honor, translate, or ignore. +* A write call can accept fewer bytes than requested. Preserve and retry the + remainder instead of silently dropping it. +* For interactive traffic, flush after a logical message. For throughput, + allow the FIFO to fill and flush less often. + +Specifications used: *Communications Devices Class*, Revision 1.2 (Errata 1), +and *CDC PSTN Subclass*, Revision 1.2, which defines ACM. diff --git a/docs/reference/class/device.rst b/docs/reference/class/device.rst new file mode 100644 index 000000000..8a67a0f45 --- /dev/null +++ b/docs/reference/class/device.rst @@ -0,0 +1,159 @@ +******************** +Using Device Classes +******************** + +A device class needs three matching pieces: a nonzero ``CFG_TUD_*`` instance +count, class descriptors in the configuration descriptor, and the required +application callbacks. Start from the nearest device example instead of +writing descriptors from scratch. + +Setup checklist +=============== + +1. Enable the device stack and each class in ``tusb_config.h``. A class value + is normally the maximum number of simultaneous class instances, not a + boolean. +2. Add the matching ``TUD_*_DESCRIPTOR`` macro to the configuration descriptor + and include its ``TUD_*_DESC_LEN`` in the total length. +3. Assign unique interface numbers and endpoint addresses. Some functions use + more than one interface; for example, CDC ACM normally uses two. +4. Implement the descriptor and class callbacks used by the example. +5. Call ``tud_task()`` regularly, or run it in a dedicated RTOS task. + +For example, one CDC ACM function starts with: + +.. code-block:: c + + // tusb_config.h + #define CFG_TUD_ENABLED 1 + #define CFG_TUD_CDC 1 + + // One entry inside the configuration descriptor + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 0, EPNUM_CDC_NOTIF, 8, + EPNUM_CDC_OUT, EPNUM_CDC_IN, 64), + +See :doc:`../../integration` for stack initialization and the full descriptor +callback pattern. + +Common configuration options +============================ + +These options apply before the class-specific settings described on the other +pages. Defaults come from ``src/tusb_option.h``. + +.. list-table:: + :header-rows: 1 + :widths: 30 18 52 + + * - Option + - Default + - What it controls + * - ``CFG_TUD_ENABLED`` + - Root-port mode + - Enables the device stack. Set it explicitly when the selected root-port + mode does not already select device operation. + * - ``CFG_TUD_MAX_SPEED`` + - Root-port mode + - Highest speed for which the device stack and descriptors are built. + High-speed devices also need valid qualifier and other-speed + descriptors. + * - ``CFG_TUD_ENDPOINT0_SIZE`` + - ``64`` bytes + - Control endpoint maximum packet size. It must match ``bMaxPacketSize0`` + in the device descriptor and the controller's capability. + * - ``CFG_TUD_ENDPOINT0_BUFSIZE`` + - Endpoint 0 size + - Staging space for control transfers. Increase it when a class control + request must hold more than one endpoint packet. + * - ``CFG_TUD_INTERFACE_MAX`` + - ``16`` + - Maximum total USB interfaces across the active configuration, including + every interface used by composite functions. + * - ``CFG_TUD_TASK_EVENTS_PER_RUN`` + - ``16`` + - Maximum events handled by one ``tud_task_ext()`` call. ``0`` removes + the limit; a smaller value reduces one-call latency at the cost of more + task invocations. + * - ``CFG_TUD_ENDPPOINT_MAX`` + - Controller maximum + - Highest endpoint-number pool retained by the stack. Lowering it can + save RAM, but it must cover every configured endpoint number. + * - ``CFG_TUD_MEM_SECTION`` / ``CFG_TUD_MEM_ALIGN`` + - Common USB settings / 4-byte alignment + - Places and aligns controller-facing buffers for DMA. Override these + when the device controller requires a particular RAM region or + alignment. + +``CFG_TUD_ENDPPOINT_MAX`` contains the double ``P`` for compatibility; use the +spelling shown above. + +Core API and callbacks +====================== + +.. list-table:: + :header-rows: 1 + :widths: 36 64 + + * - API or callback + - What it does + * - ``tusb_init()`` + - Initializes a root port with an explicit role and speed. Call it before + the task function and check its boolean result. + * - ``tud_task()`` / ``tud_task_ext()`` + - Dispatches bus, control, class, and completion events. The extended + form selects a wait timeout and states whether the call is from an ISR. + * - ``tud_connected()`` / ``tud_mounted()`` / ``tud_ready()`` + - Reports progressively stronger states: bus activity, configured by the + host, and configured plus not suspended. Use ``tud_ready()`` before + initiating normal traffic. + * - ``tud_suspended()`` / ``tud_remote_wakeup()`` + - Tests suspend state and requests remote wakeup. Wakeup succeeds only + when the host enabled it and the device is suspended. + * - ``tud_disconnect()`` / ``tud_connect()`` + - Controls the USB pull-up to force a logical detach or attach. These + return ``false`` when the controller cannot provide the operation. + * - ``tud_mount_cb()`` / ``tud_umount_cb()`` + - Announces configuration and removal. Initialize or discard + configuration-dependent application state here. + * - ``tud_suspend_cb()`` / ``tud_resume_cb()`` + - Announces bus power-state changes. The suspend callback also reports + whether remote wakeup was enabled by the host. + * - ``tud_descriptor_*_cb()`` + - Supplies device, configuration, string, BOS, and high-speed companion + descriptors on request. Returned storage must remain valid through the + control transfer. + * - ``tud_control_xfer()`` / ``tud_control_status()`` + - Completes the data/status stages of an application-handled control + request. The data length is truncated to the request's ``wLength``. + +Interfaces and instances +======================== + +Single-instance helpers such as ``tud_cdc_read()`` operate on instance zero. +Their ``_n_`` forms, such as ``tud_cdc_n_read(itf, ...)``, select a class +instance when the corresponding ``CFG_TUD_*`` value is greater than one. +Class instance numbers are not necessarily USB ``bInterfaceNumber`` values. + +Endpoint direction is always described from the USB device's point of view: + +* IN sends data from the device to the host. +* OUT receives data from the host at the device. + +Buffers and callbacks +===================== + +Class callbacks run when ``tud_task()`` processes an event, unless a header +explicitly labels a helper as ISR-safe. Keep callbacks short and move lengthy +work to an application task. + +Buffered write APIs return the number of bytes accepted, which can be shorter +than requested. Check the return value and use the class's flush function when +latency matters. Size endpoint and software buffers for the active bus speed; +copy the full-speed/high-speed pattern from an example that supports both. + +Before testing on hardware, verify that: + +* the configuration descriptor's total length and interface count are exact; +* every endpoint address is unique within the configuration; +* descriptor packet sizes agree with the relevant ``CFG_TUD_*_EPSIZE`` values; +* callbacks never retain a pointer whose documented lifetime has ended. diff --git a/docs/reference/class/dfu.rst b/docs/reference/class/dfu.rst new file mode 100644 index 000000000..6a95bbf89 --- /dev/null +++ b/docs/reference/class/dfu.rst @@ -0,0 +1,92 @@ +*** +DFU +*** + +Role: device only. Device Firmware Upgrade (DFU) has two distinct states: +runtime mode, where normal firmware advertises that it can reboot into an +updater, and DFU mode, where firmware images are transferred. + +Runtime mode +============ + +Enable ``CFG_TUD_DFU_RUNTIME`` and add ``TUD_DFU_RT_DESCRIPTOR``. When the +host sends DFU_DETACH, TinyUSB calls ``tud_dfu_runtime_reboot_to_dfu_cb()``. +Store any required boot flag, safely stop the application, and reset into the +DFU image from that callback. + +The descriptor's detach attributes must describe the actual behavior. In +particular, do not set ``bitWillDetach`` unless the callback will initiate the +detach/reset without a USB reset from the host. + +See :doc:`../../examples/device/dfu_runtime`. + +.. list-table:: + :header-rows: 1 + :widths: 38 62 + + * - Descriptor attribute + - Meaning + * - ``DFU_ATTR_CAN_DOWNLOAD`` + - Host may send firmware to the device. + * - ``DFU_ATTR_CAN_UPLOAD`` + - Host may read firmware from the device; omit it when disclosure is not + intended. + * - ``DFU_ATTR_MANIFESTATION_TOLERANT`` + - Device can remain in DFU mode after manifestation without reset. + * - ``DFU_ATTR_WILL_DETACH`` + - Device performs its own detach/reset after DFU_DETACH. Clear it when + the host must issue the USB reset. + +DFU mode +======== + +Enable ``CFG_TUD_DFU`` and set ``CFG_TUD_DFU_XFER_BUFSIZE`` to exactly the +``wTransferSize`` passed to ``TUD_DFU_DESCRIPTOR``. Alternate settings can +represent partitions or targets; their string descriptors should clearly name +the target presented by each ``alt`` value. + +.. list-table:: + :header-rows: 1 + :widths: 38 62 + + * - Callback/API + - Application responsibility + * - ``tud_dfu_download_cb()`` + - Program one downloaded block, then call + ``tud_dfu_finish_flashing()`` when the operation completes. + * - ``tud_dfu_upload_cb()`` + - Fill the buffer with at most the requested number of bytes and return + the count. + * - ``tud_dfu_manifest_cb()`` + - Validate/finalize the image, then call ``tud_dfu_finish_flashing()``. + * - ``tud_dfu_get_timeout_cb()`` + - Return an honest poll timeout for the current target and state. + * - ``tud_dfu_abort_cb()`` + - Cancel pending storage work and return the target to a safe state. + * - ``tud_dfu_detach_cb()`` + - Handles DFU_DETACH while in DFU mode; normally records state and resets + or returns to runtime firmware according to the descriptor attributes. + * - ``tud_dfu_finish_flashing()`` + - Completes a previously started download or manifestation. An error + status moves the state machine into the DFU error state. + +Storage can be asynchronous: retain the operation state, return from the +callback, and call ``tud_dfu_finish_flashing(status)`` later. Pass +``DFU_STATUS_OK`` only after the data is durably written or manifestation is +complete. + +The :doc:`../../examples/device/dfu` example exposes two alternate settings +and can be exercised with ``dfu-util``. + +Production safety +================= + +Treat all DFU fields and image bytes as untrusted. Bounds-check ``alt``, block +number, offset, and length before accessing storage. A production updater +should authenticate the complete image, reject rollback when required, avoid +overwriting its recovery path, and remain bootable after loss of power at any +point. TinyUSB implements the USB transport and DFU state machine; it does not +provide those product-specific security guarantees. + +Specification used: *USB Device Class Specification for Device Firmware +Upgrade*, Version 1.1. diff --git a/docs/reference/class/hid.rst b/docs/reference/class/hid.rst new file mode 100644 index 000000000..567bc54e0 --- /dev/null +++ b/docs/reference/class/hid.rst @@ -0,0 +1,168 @@ +*** +HID +*** + +Roles: device and host. Human Interface Device (HID) transfers input, output, +and feature reports described by a compact HID report descriptor. + +Device +====== + +Enable ``CFG_TUD_HID`` for the required number of HID interfaces and set +``CFG_TUD_HID_EP_BUFSIZE`` to the largest report transferred on an interrupt +endpoint. Use ``TUD_HID_DESCRIPTOR`` for IN-only HID or +``TUD_HID_INOUT_DESCRIPTOR`` when an interrupt OUT endpoint is required. + +``CFG_TUD_HID_EP_BUFSIZE`` defaults to 64 bytes and allocates one endpoint +buffer per enabled HID instance. It must include the report ID byte when the +report descriptor uses IDs. Increasing it permits longer reports but consumes +static RAM; it does not change the report descriptor automatically. + +Define a report descriptor and return it from +``tud_hid_descriptor_report_cb()``. TinyUSB provides templates including +``TUD_HID_REPORT_DESC_KEYBOARD()``, ``TUD_HID_REPORT_DESC_MOUSE()``, and +``TUD_HID_REPORT_DESC_GENERIC_INOUT()``. When several report types share one +interface, give each a distinct ``HID_REPORT_ID()`` and include that ID in API +calls and report handling. + +Send only when the interface is ready: + +.. code-block:: c + + if (tud_hid_ready()) { + tud_hid_keyboard_report(REPORT_ID_KEYBOARD, modifier, keycodes); + } + +Use ``tud_hid_report()`` for a custom layout. Handle host-to-device output or +feature reports in ``tud_hid_set_report_cb()`` and provide requested input or +feature data in ``tud_hid_get_report_cb()``. The bytes and lengths must match +the report descriptor exactly. + +.. list-table:: + :header-rows: 1 + :widths: 40 60 + + * - Device API or callback + - What it does + * - ``tud_hid_n_ready()`` + - Tests whether the interrupt IN endpoint for an instance can accept a + report. + * - ``tud_hid_n_report()`` + - Copies and queues a custom input report. ``false`` means it was not + queued; the caller may reuse its source buffer after the call returns. + * - ``tud_hid_n_keyboard_report()`` / + ``tud_hid_n_mouse_report()`` / + ``tud_hid_n_gamepad_report()`` + - Builds and queues a standard TinyUSB report structure. Its descriptor + template must match the chosen helper. + * - ``tud_hid_descriptor_report_cb()`` + - Returns the report descriptor for an instance. The returned storage + must remain valid. + * - ``tud_hid_get_report_cb()`` + - Fills a control GET_REPORT response and returns its byte count. Returning + zero stalls the request. + * - ``tud_hid_set_report_cb()`` + - Receives an output or feature report from either the control endpoint or + interrupt OUT endpoint. + * - ``tud_hid_set_protocol_cb()`` / ``tud_hid_set_idle_cb()`` + - Applies host boot/report protocol and idle-rate requests. HID idle rate + units are 4 ms. + * - ``tud_hid_report_complete_cb()`` / + ``tud_hid_report_failed_cb()`` + - Announces that the internal endpoint buffer is reusable, or reports the + number of bytes transferred before failure. + +For keyboards and buttons, send a release report as well as the press report; +otherwise the host can retain a stuck key. The +:doc:`../../examples/device/hid_composite` and +:doc:`../../examples/device/hid_generic_inout` examples show both patterns. + +Host +==== + +Set ``CFG_TUH_HID`` to the maximum simultaneous HID interfaces, not merely the +number of physical devices. A keyboard with media controls or a composite +controller can expose several interfaces. Size +``CFG_TUH_HID_EPIN_BUFSIZE`` and ``CFG_TUH_HID_EPOUT_BUFSIZE`` for the largest +reports the application accepts. + +.. list-table:: + :header-rows: 1 + :widths: 39 17 44 + + * - Option + - Default + - What it controls + * - ``CFG_TUH_HID_EPIN_BUFSIZE`` + - ``64`` bytes + - Largest interrupt IN report that can be received per HID instance. + * - ``CFG_TUH_HID_EPOUT_BUFSIZE`` + - ``64`` bytes + - Largest interrupt OUT report that can be sent per HID instance. + * - ``CFG_TUH_HID_SET_PROTOCOL_ON_ENUM`` + - ``1`` + - Sends SET_PROTOCOL during enumeration for boot-capable interfaces. + Set it to ``0`` if the application will select protocol later. + +``tuh_hid_mount_cb()`` supplies ``dev_addr``, interface ``idx``, and the report +descriptor. Parse and retain the information needed to decode later reports, +then queue the first receive: + +.. code-block:: c + + void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t idx, + uint8_t const *desc, uint16_t desc_len) { + parse_report_descriptor(desc, desc_len); + tuh_hid_receive_report(dev_addr, idx); + } + + void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t idx, + uint8_t const *report, uint16_t len) { + process_report(report, len); + tuh_hid_receive_report(dev_addr, idx); // Re-arm interrupt IN. + } + +If a report descriptor is larger than ``CFG_TUH_ENUMERATION_BUFSIZE``, the +mount callback can receive ``desc == NULL`` and ``desc_len == 0``. Increase +the enumeration buffer or handle that case without dereferencing the pointer. + +Use ``tuh_hid_send_report()`` for an interrupt OUT report and +``tuh_hid_get_report()``/``tuh_hid_set_report()`` for control transfers. Boot +keyboards and mice can use boot protocol; all other devices require report +protocol and parsing of their descriptor. + +.. list-table:: + :header-rows: 1 + :widths: 40 60 + + * - Host API or callback + - What it does + * - ``tuh_hid_mounted()`` / ``tuh_hid_itf_get_info()`` + - Tests a device/interface pair and retrieves its cached interface + descriptor information. + * - ``tuh_hid_interface_protocol()`` / ``tuh_hid_get_protocol()`` + - Distinguishes keyboard/mouse/none interface protocol from the active + boot/report transfer protocol. + * - ``tuh_hid_receive_ready()`` / ``tuh_hid_receive_report()`` + - Tests and arms one interrupt IN transfer. Re-arm it after every receive + callback for continuous input. + * - ``tuh_hid_send_ready()`` / ``tuh_hid_send_report()`` + - Tests and queues one interrupt OUT report. The send callback releases + the internal endpoint buffer; the source is copied before return. + * - ``tuh_hid_get_report()`` / ``tuh_hid_set_report()`` + - Starts a control endpoint report request. Completion callbacks report + zero length on a stall or transfer error; keep the caller's report + buffer valid until that callback. + * - ``tuh_hid_set_protocol()`` + - Requests boot or report protocol on boot-capable interfaces; completion + is reported asynchronously. + * - ``tuh_hid_mount_cb()`` / ``tuh_hid_umount_cb()`` + - Supplies the report descriptor at mount and announces when the interface + index is no longer valid. + +See :doc:`../../examples/host/cdc_msc_hid` for keyboard/mouse handling and +:doc:`../../examples/host/hid_controller` for controller input and output. + +Specification used: *Device Class Definition for Human Interface Devices +(HID)*, Version 1.11. HID Usage Tables define the individual usage pages and +codes used inside report descriptors. diff --git a/docs/reference/class/host.rst b/docs/reference/class/host.rst new file mode 100644 index 000000000..ef42e3dfb --- /dev/null +++ b/docs/reference/class/host.rst @@ -0,0 +1,142 @@ +****************** +Using Host Classes +****************** + +TinyUSB provides application-level host drivers for CDC serial, HID, MIDI 1.0, +MIDI 2.0, and Mass Storage. A host application is asynchronous: a mount +callback reports a ready interface, I/O is queued, and completion or receive +callbacks advance the application state. + +Setup checklist +=============== + +1. Enable ``CFG_TUH_ENABLED`` and set each ``CFG_TUH_*`` pool size in + ``tusb_config.h``. HID and MIDI values count interfaces, so allow for more + than one interface per physical device. +2. Set ``CFG_TUH_DEVICE_MAX`` for the number of attached devices and enable + ``CFG_TUH_HUB`` if hubs are required. +3. Initialize a host-capable root port and provide VBUS as required by the + board. +4. Call ``tuh_task()`` continuously, or run it in a dedicated RTOS task. +5. Start class I/O from its mount callback and requeue receive transfers where + the class guide requires it. + +Typical configuration: + +.. code-block:: c + + #define CFG_TUH_ENABLED 1 + #define CFG_TUH_DEVICE_MAX 4 + #define CFG_TUH_HUB 1 + #define CFG_TUH_CDC 1 + #define CFG_TUH_HID (3 * CFG_TUH_DEVICE_MAX) + #define CFG_TUH_MSC 1 + +Common configuration options +============================ + +.. list-table:: + :header-rows: 1 + :widths: 30 18 52 + + * - Option + - Default + - What it controls + * - ``CFG_TUH_ENABLED`` + - Root-port mode + - Enables the host stack. The board must also supply VBUS and a + host-capable controller/PHY. + * - ``CFG_TUH_MAX_SPEED`` + - Root-port mode + - Highest bus speed supported by the host build. It does not make a + full-speed-only controller operate at high speed. + * - ``CFG_TUH_DEVICE_MAX`` + - ``1`` + - Number of USB device addresses tracked simultaneously, including hubs. + * - ``CFG_TUH_HUB`` + - ``0`` + - Number of hubs supported simultaneously. Hub ports can require higher + device and class pool counts. + * - ``CFG_TUH_ENUMERATION_BUFSIZE`` + - ``256`` bytes + - Temporary descriptor buffer used during enumeration. Increase it for + long configuration or HID report descriptors; this consumes static RAM. + * - ``CFG_TUH_TASK_EVENTS_PER_RUN`` + - ``16`` + - Maximum events handled by one ``tuh_task_ext()`` call. ``0`` is + unlimited. + * - ``CFG_TUH_MEM_SECTION`` / ``CFG_TUH_MEM_ALIGN`` + - Common USB settings / 4-byte alignment + - Places and aligns host-controller buffers for DMA-accessible RAM. + * - ``CFG_TUSB_OS`` + - ``OPT_OS_NONE`` + - Selects TinyUSB's synchronization backend. Set the matching OS option + when host APIs and ``tuh_task()`` run in different RTOS tasks. + +Each ``CFG_TUH_<CLASS>`` value sizes a simultaneous interface pool. It is not +a VID/PID allowlist and, for composite devices, may need to exceed +``CFG_TUH_DEVICE_MAX``. + +Core API and callbacks +====================== + +.. list-table:: + :header-rows: 1 + :widths: 36 64 + + * - API or callback + - What it does + * - ``tusb_init()`` + - Initializes a root port with host role and selected speed. Call it + after board/VBUS setup and check its boolean result. + * - ``tuh_task()`` / ``tuh_task_ext()`` + - Advances enumeration and transfers and dispatches callbacks. The + extended form controls wait timeout and ISR context. + * - ``tuh_mount_cb()`` / ``tuh_umount_cb()`` + - Announces a configured device or detachment. Class mount callbacks + provide the interface-specific indices used for I/O. + * - ``tuh_mounted()`` / ``tuh_ready()`` / ``tuh_connected()`` + - Tests whether an address is configured/ready or has merely shown bus + activity. Do not start class I/O based only on ``tuh_connected()``. + * - ``tuh_vid_pid_get()`` / ``tuh_speed_get()`` / ``tuh_bus_info_get()`` + - Returns cached identity, speed, and hub/root-port location for an + enumerated address. + * - ``tuh_descriptor_get_device_local()`` + - Copies the cached device descriptor without issuing a USB transfer. + Other ``tuh_descriptor_get_*()`` calls queue or perform control + transfers to fetch descriptors. + * - ``tuh_control_xfer()`` + - Submits a control transfer described by ``tuh_xfer_t``. A non-null + completion callback makes it asynchronous; a null callback blocks. + * - ``tuh_edpt_xfer()`` + - Submits a bulk or interrupt endpoint transfer. Application class + drivers normally use their class-specific wrappers instead. + +Synchronous host control calls are forbidden from the host task when +``CFG_TUSB_OS_HAS_SCHEDULER`` is true: that task is needed to make the same +transfer complete. Prefer callbacks for portable application code. + +Addresses and indices +===================== + +``dev_addr`` identifies an enumerated USB device. Classes that may expose +multiple interfaces also use a class ``idx``. Preserve both values supplied by +the mount callback and use the same pair for later API calls. An index can be +reused after unmount, so discard associated application state in the unmount +callback. + +Transfer lifetime +================= + +Unless an API explicitly documents a copy, keep a transfer buffer valid and +unchanged until its completion callback. Buffers used directly by a host +controller may also require alignment, cache maintenance, or placement in +DMA-accessible memory; follow the board's HCD requirements. + +Do not block ``tuh_task()`` while waiting for a callback that only it can +dispatch. Prefer the asynchronous APIs. Where a class provides a synchronous +helper, use it only from a context in which the host task can still run. + +Start with :doc:`../../examples/host/cdc_msc_hid` for CDC, HID, and MSC, +:doc:`../../examples/host/midi_rx` for MIDI 1.0, or +:doc:`../../examples/host/midi2_host` for MIDI 2.0. diff --git a/docs/reference/class/index.rst b/docs/reference/class/index.rst new file mode 100644 index 000000000..2f8e577d0 --- /dev/null +++ b/docs/reference/class/index.rst @@ -0,0 +1,96 @@ +************* +Class Drivers +************* + +Class drivers implement USB protocols such as CDC serial, HID, mass storage, +and MIDI. Enable only the classes your product uses: device APIs start with +``tud_`` and host APIs start with ``tuh_``. + +Start with :doc:`device` or :doc:`host`, then use the class page for its +configuration, data flow, callbacks, and examples. The API lists below focus +on the calls normally needed by an application; the public headers remain the +complete API reference. + +Support matrix +============== + +.. list-table:: + :header-rows: 1 + :widths: 24 18 18 40 + + * - Class + - Device + - Host + - Guide + * - Audio 1.0/2.0 + - Yes + - No + - :doc:`audio` + * - Bluetooth HCI + - Yes + - No + - :doc:`bluetooth` + * - CDC serial + - Yes + - Yes + - :doc:`cdc` + * - DFU 1.1 + - Yes + - No + - :doc:`dfu` + * - HID 1.11 + - Yes + - Yes + - :doc:`hid` + * - MIDI 1.0/2.0 + - Yes + - Yes + - :doc:`midi` + * - Mass Storage (BOT) + - Yes + - Yes + - :doc:`msc` + * - Media Transfer (MTP) + - Yes + - No + - :doc:`mtp` + * - Network (ECM/RNDIS/NCM) + - Yes + - No + - :doc:`network` + * - Printer + - Yes + - No + - :doc:`printer` + * - Test and Measurement (USBTMC) + - Yes + - No + - :doc:`usbtmc` + * - Vendor-specific + - Yes + - Custom driver + - :doc:`vendor` + * - Video 1.5 + - Yes + - No + - :doc:`video` + +.. toctree:: + :maxdepth: 1 + :hidden: + + device + host + audio + bluetooth + cdc + dfu + hid + midi + msc + mtp + network + printer + usbtmc + vendor + video diff --git a/docs/reference/class/midi.rst b/docs/reference/class/midi.rst new file mode 100644 index 000000000..3fddbd044 --- /dev/null +++ b/docs/reference/class/midi.rst @@ -0,0 +1,214 @@ +**** +MIDI +**** + +Roles: device and host. TinyUSB has separate drivers for USB-MIDI 1.0 event +packets and USB-MIDI 2.0 Universal MIDI Packets (UMP). Enable the driver that +matches the data model used by the application. + +MIDI 1.0 device +=============== + +Enable ``CFG_TUD_MIDI``, tune ``CFG_TUD_MIDI_RX_BUFSIZE`` and +``CFG_TUD_MIDI_TX_BUFSIZE`` if needed, and add ``TUD_MIDI_DESCRIPTOR``. + +.. list-table:: + :header-rows: 1 + :widths: 38 18 44 + + * - Option + - Default + - What it controls + * - ``CFG_TUD_MIDI_RX_BUFSIZE`` / ``CFG_TUD_MIDI_TX_BUFSIZE`` + - Required when enabled + - Software FIFO bytes per interface. Define both, normally at least as + large as the matching endpoint buffer. + * - ``CFG_TUD_MIDI_RX_EPSIZE`` / ``CFG_TUD_MIDI_TX_EPSIZE`` + - Device bulk maximum + - Endpoint transfer buffer and descriptor packet size. + +Use ``tud_midi_stream_read()``/``tud_midi_stream_write()`` for MIDI byte +streams on the first interface and cable. Use ``tud_midi_n_*`` to select an +interface or cable, and the ``*_packet_*`` APIs when the application already +works with 4-byte USB-MIDI event packets. Drain received data in +``tud_midi_rx_cb()``. + +.. list-table:: + :header-rows: 1 + :widths: 42 58 + + * - API or callback + - What it does + * - ``tud_midi_n_available()`` / + ``tud_midi_n_stream_read()`` + - Reports and reads MIDI bytes for one interface and virtual cable. + * - ``tud_midi_n_demux_stream_read()`` + - Reads bytes from one cable at a time and returns that cable number. Do + not mix it with the legacy stream reader on the same interface. + * - ``tud_midi_n_stream_write()`` + - Packetizes a MIDI byte stream and returns the number of source bytes + accepted. + * - ``tud_midi_n_packet_read_n()`` / + ``tud_midi_n_packet_write_n()`` + - Reads or writes complete 4-byte USB-MIDI event packets and returns a + packet count. + * - ``tud_midi_rx_cb()`` + - Announces received data. Drain the FIFO so later OUT transfers have + room. + +See :doc:`../../examples/device/midi_test`. + +MIDI 1.0 host +============= + +Set ``CFG_TUH_MIDI`` to the number of simultaneous MIDI streaming interfaces. +The following options size each instance: + +.. list-table:: + :header-rows: 1 + :widths: 38 18 44 + + * - Option + - Default + - What it controls + * - ``CFG_TUH_MIDI_RX_BUFSIZE`` / ``CFG_TUH_MIDI_TX_BUFSIZE`` + - Host bulk maximum + - Software FIFO capacity for received and queued event packets. + * - ``CFG_TUH_MIDI_EP_BUFSIZE`` + - Host bulk maximum + - Endpoint transfer buffer size. + * - ``CFG_TUH_MIDI_STREAM_API`` + - ``1`` + - Enables byte-stream packetization/depacketization. Disable it to save + code size when the application uses only raw 4-byte event packets. + +``tuh_midi_descriptor_cb()`` reports descriptor information before the +interface is ready; begin I/O in ``tuh_midi_mount_cb()``. Receive data in +``tuh_midi_rx_cb()`` with ``tuh_midi_stream_read()`` or +``tuh_midi_packet_read_n()``. Writes remain buffered until an endpoint packet +is ready or ``tuh_midi_write_flush()`` is called. + +The RX and TX cable counts can differ. Query them with +``tuh_midi_get_rx_cable_count()`` and ``tuh_midi_get_tx_cable_count()`` before +selecting a cable. See :doc:`../../examples/host/midi_rx`. + +``tuh_midi_read_available()`` reports raw FIFO bytes, while +``tuh_midi_stream_read()`` returns decoded MIDI stream bytes and a cable +number. ``tuh_midi_packet_read_n()`` keeps the USB event-packet format. +``tuh_midi_write_flush()`` starts a short buffered transfer and returns the +number of bytes submitted. Mount/unmount callbacks define the lifetime of the +``idx``; RX/TX callbacks announce new input and newly available TX space. + +MIDI 2.0 device +=============== + +Enable ``CFG_TUD_MIDI2`` and add ``TUD_MIDI2_DESCRIPTOR``. The descriptor +contains alternate setting 0 for USB-MIDI 1.0 fallback and alternate setting 1 +for UMP, as required by the MIDI 2.0 class specification. + +.. code-block:: c + + #define CFG_TUD_MIDI2 1 + #define CFG_TUD_MIDI2_RX_BUFSIZE 256 + #define CFG_TUD_MIDI2_TX_BUFSIZE 256 + +.. list-table:: + :header-rows: 1 + :widths: 38 18 44 + + * - Option + - Default + - What it controls + * - ``CFG_TUD_MIDI2_RX_EPSIZE`` / ``CFG_TUD_MIDI2_TX_EPSIZE`` + - Device bulk maximum + - Endpoint transfer buffers and descriptor packet sizes. + * - ``CFG_TUD_MIDI2_RX_BUFSIZE`` / ``CFG_TUD_MIDI2_TX_BUFSIZE`` + - Matching endpoint size + - UMP FIFO bytes per interface. + * - ``CFG_TUD_MIDI2_NUM_GROUPS`` + - ``1`` + - Number of UMP groups exposed by the default Group Terminal Block. + * - ``CFG_TUD_MIDI2_EP_NAME`` / ``CFG_TUD_MIDI2_PRODUCT_ID`` + - TinyUSB strings + - Default endpoint name and product identifier returned by UMP discovery. + * - ``CFG_TUD_MIDI2_BLOCK_STRIDX`` + - ``0`` + - Optional string-descriptor index for the Function Block; zero means no + string. + +On alternate setting 1, read and write arrays of 32-bit words with +``tud_midi2_ump_read()`` and ``tud_midi2_ump_write()``. On alternate setting +0, use ``tud_midi2_packet_read()`` and ``tud_midi2_packet_write()`` for 4-byte +USB-MIDI 1.0 event packets. Query ``tud_midi2_alt_setting()`` and +``tud_midi2_protocol()`` when choosing the format to send. + +Drain the RX FIFO completely in the callback: + +.. code-block:: c + + void tud_midi2_rx_cb(uint8_t itf) { + uint32_t words[16]; + uint32_t count; + while ((count = tud_midi2_n_ump_read(itf, words, 16)) != 0) { + process_ump(words, count); // Track message size from each MT field. + } + } + +``tud_midi2_ump_read()`` returns available words, which can end at the caller's +``max_words`` limit. Parse UMP message boundaries from the Message Type field +and preserve an incomplete message between reads when using a small buffer. + +The driver handles standard UMP Stream discovery and protocol negotiation. +Override ``tud_midi2_gtb_desc_cb()`` to describe a custom Group Terminal Block +topology and ``tud_midi2_fb_name_cb()`` for Function Block names. Use +``tud_midi2_stream_msg_cb()`` only when the application must override a built-in +Stream response. + +``tud_midi2_n_available()`` returns queued bytes, whereas +``tud_midi2_n_ump_read()`` and ``tud_midi2_n_ump_write()`` return 32-bit word +counts. The packet APIs return counts of 4-byte MIDI 1.0 event packets. +``tud_midi2_set_itf_cb()`` announces the active alternate setting so the +application can switch its parser and producer. + +See :doc:`../../examples/device/midi2_device` for alternate-setting and +protocol fallback. + +MIDI 2.0 host +============= + +Set ``CFG_TUH_MIDI2`` to the required interface count. The host driver detects +both alternate settings, selects the highest available protocol, and completes +``SET_INTERFACE`` before reporting the mount. + +``CFG_TUH_MIDI2_RX_BUFSIZE`` and ``CFG_TUH_MIDI2_TX_BUFSIZE`` default to the +host bulk maximum and allocate FIFO storage per instance. Increase them when +the application can be delayed for several USB transfers; keep UMP data +32-bit aligned in application buffers. + +Callback order is important: + +.. code-block:: text + + descriptor callback -> protocol/alternate selection -> mount callback + -> RX/TX callbacks -> unmount callback + +``tuh_midi2_descriptor_cb()`` is informational; the interface is not yet ready. +Start I/O only after ``tuh_midi2_mount_cb()``. In ``tuh_midi2_rx_cb()``, call +``tuh_midi2_ump_read()`` in a loop until it returns zero. Queue output with +``tuh_midi2_ump_write()`` and use ``tuh_midi2_write_flush()`` when latency +matters. + +Use ``tuh_midi2_get_protocol_version()`` and +``tuh_midi2_get_alt_setting_active()`` to inspect the selected transport. The +:doc:`../../examples/host/midi2_host` example parses the UMP Message Type field +to determine whether each message occupies 1, 2, 3, or 4 words. + +``tuh_midi2_ump_write()`` returns the number of words accepted and +``tuh_midi2_write_flush()`` returns the number of bytes submitted. Preserve +unaccepted words and retry after ``tuh_midi2_tx_cb()``. Treat the data supplied +to ``tuh_midi2_descriptor_cb()`` as informational only; the interface becomes +usable at ``tuh_midi2_mount_cb()`` and invalid at ``tuh_midi2_umount_cb()``. + +Specification used: *USB Device Class Definition for MIDI Devices*, Release +2.0. It defines the MIDI 1.0-compatible alternate setting, the native UMP +alternate setting, Group Terminal Blocks, and discovery behavior. diff --git a/docs/reference/class/msc.rst b/docs/reference/class/msc.rst new file mode 100644 index 000000000..5049669e7 --- /dev/null +++ b/docs/reference/class/msc.rst @@ -0,0 +1,125 @@ +************ +Mass Storage +************ + +Roles: device and host. TinyUSB implements the USB Mass Storage Bulk-Only +Transport (BOT) and common SCSI commands. It exposes logical blocks; a +filesystem such as FatFs is a separate application layer. + +Device +====== + +Enable ``CFG_TUD_MSC`` and set ``CFG_TUD_MSC_EP_BUFSIZE``. Add one +``TUD_MSC_DESCRIPTOR`` for each Mass Storage function. Multiple logical units +(LUNs) normally share one function and are selected through the ``lun`` +callback argument. + +``CFG_TUD_MSC_EP_BUFSIZE`` has no default and is required when MSC is enabled. +It is the class transfer-buffer size per instance, not the media capacity. +Using at least one logical block is efficient; larger values improve large +transfers at the cost of static RAM. Keep it below 65536 bytes and consistent +with controller/DMA constraints. + +The minimum storage callbacks are: + +.. list-table:: + :header-rows: 1 + :widths: 38 62 + + * - Callback + - Purpose + * - ``tud_msc_inquiry_cb()`` + - Return fixed-width vendor, product, and revision fields. + * - ``tud_msc_test_unit_ready_cb()`` + - Report whether media is present and usable. + * - ``tud_msc_capacity_cb()`` + - Return the logical block count and block size. + * - ``tud_msc_read10_cb()`` + - Read ``bufsize`` bytes from ``lba`` plus ``offset``. + * - ``tud_msc_write10_cb()`` + - Write ``bufsize`` bytes to ``lba`` plus ``offset``. + * - ``tud_msc_scsi_cb()`` + - Handle commands not implemented by the class driver. + * - ``tud_msc_get_maxlun_cb()`` + - Returns the highest valid zero-based LUN number; implement it for + multiple LUNs. + * - ``tud_msc_is_writable_cb()`` + - Reports write protection before WRITE10. + * - ``tud_msc_start_stop_cb()`` + - Handles load/eject and start/stop requests, including safe-eject policy. + +Read and write callbacks may cover only part of a logical block. Honor both +``lba`` and ``offset`` instead of assuming one callback per block. On failure, +set useful sense data with ``tud_msc_set_sense()`` and return +``TUD_MSC_RET_ERROR``. + +For temporarily busy media, return ``TUD_MSC_RET_BUSY``; TinyUSB will invoke +the callback again with the same parameters. For true background I/O, return +``TUD_MSC_RET_ASYNC`` and later call ``tud_msc_async_io_done()`` with the byte +count or error. Do not report a write complete until data has reached the +durability level promised by the product. ``tud_msc_write10_complete_cb()`` is +a useful place to flush a cache. + +See :doc:`../../examples/device/cdc_msc` for a RAM disk and +:doc:`../../examples/device/msc_dual_lun` for multiple LUNs. + +Host +==== + +Set ``CFG_TUH_MSC`` to the maximum simultaneous Mass Storage devices and +``CFG_TUH_MSC_MAXLUN`` to the LUN limit per device. After +``tuh_msc_mount_cb(dev_addr)``, query cached geometry with +``tuh_msc_get_block_count()`` and ``tuh_msc_get_block_size()``. + +``CFG_TUH_MSC_MAXLUN`` defaults to 4 and allocates cached state per possible +LUN for every enabled MSC device. Set it to the maximum needed by the product, +not necessarily the maximum value a device claims. + +``tuh_msc_read10()`` and ``tuh_msc_write10()`` are asynchronous. Keep the +buffer valid, correctly aligned, cache coherent, and accessible to the USB +controller until the ``tuh_msc_complete_cb_t`` callback runs. Check +``tuh_msc_ready()`` before starting another command and inspect the completion +callback's transfer result and command status. + +.. list-table:: + :header-rows: 1 + :widths: 40 60 + + * - Host API or callback + - What it does + * - ``tuh_msc_mounted()`` / ``tuh_msc_ready()`` + - Tests whether the MSC device is present or currently able to accept a + new SCSI command. + * - ``tuh_msc_get_maxlun()`` / + ``tuh_msc_get_block_count()`` / + ``tuh_msc_get_block_size()`` + - Returns cached LUN range and geometry populated during enumeration. + * - ``tuh_msc_read10()`` / ``tuh_msc_write10()`` + - Queues an integral number of logical blocks and completes through the + supplied callback. + * - ``tuh_msc_inquiry()`` / ``tuh_msc_request_sense()`` + - Queues standard SCSI identification or detailed-error requests into an + application-owned response buffer. + * - ``tuh_msc_scsi_command()`` + - Queues a caller-built command block wrapper for commands without a + convenience API. + * - ``tuh_msc_mount_cb()`` / ``tuh_msc_umount_cb()`` + - Announces cached capacity availability or invalidates all filesystem and + media state for the address. + +TinyUSB does not mount a filesystem automatically. Connect the sector API to +your filesystem's disk I/O layer and invalidate that state in +``tuh_msc_umount_cb()``. The :doc:`../../examples/host/msc_file_explorer` +example demonstrates this with FatFs. + +Practical notes +=============== + +* Hosts cache filesystem data. Physical removal or firmware reset without an + eject/unmount can lose data even when USB transfers succeeded. +* Use the medium-present and write-protect responses consistently; mismatched + capacity or readiness information causes repeated SCSI recovery traffic. +* Validate every LUN and block range before calculating a storage address. + +Specification used: *USB Mass Storage Class Bulk-Only Transport*, Revision +1.0. Command formats and sense data come from the applicable SCSI command set. diff --git a/docs/reference/class/mtp.rst b/docs/reference/class/mtp.rst new file mode 100644 index 000000000..ca3b746ec --- /dev/null +++ b/docs/reference/class/mtp.rst @@ -0,0 +1,112 @@ +*** +MTP +*** + +Role: device only. Media Transfer Protocol (MTP) presents objects and object +metadata rather than a host-mounted block device. It is a better fit than MSC +when device firmware and the host must access managed files concurrently. + +Configuration +============= + +Set ``CFG_TUD_MTP`` to 1 and add ``TUD_MTP_DESCRIPTOR``. Configure the endpoint +and control buffers, then advertise only operations, events, properties, and +formats that the application actually implements: + +.. code-block:: c + + #define CFG_TUD_MTP 1 + #define CFG_TUD_MTP_EP_BUFSIZE 512 + #define CFG_TUD_MTP_EP_CONTROL_BUFSIZE 16 + + #define CFG_TUD_MTP_DEVICEINFO_SUPPORTED_OPERATIONS \ + MTP_OP_GET_DEVICE_INFO, MTP_OP_OPEN_SESSION, MTP_OP_CLOSE_SESSION + +.. list-table:: + :header-rows: 1 + :widths: 45 15 40 + + * - Option + - Default + - What it controls + * - ``CFG_TUD_MTP_EP_BUFSIZE`` + - Required + - Shared bulk data buffer and maximum data chunk. Larger values improve + throughput but consume static RAM. + * - ``CFG_TUD_MTP_EP_CONTROL_BUFSIZE`` + - Required + - Staging buffer for MTP class control requests and responses. + * - ``CFG_TUD_MTP_DEVICEINFO_EXTENSIONS`` + - Required + - MTP extension string returned by GetDeviceInfo; use an empty string when + no extension is implemented. + * - ``CFG_TUD_MTP_DEVICEINFO_SUPPORTED_OPERATIONS`` + - Required + - Operation codes the host is told it may issue. + * - ``CFG_TUD_MTP_DEVICEINFO_SUPPORTED_EVENTS`` + - Required + - Event codes the device may send on the interrupt endpoint. + * - ``CFG_TUD_MTP_DEVICEINFO_SUPPORTED_DEVICE_PROPERTIES`` + - Required + - Device property codes supported by the application. + * - ``CFG_TUD_MTP_DEVICEINFO_CAPTURE_FORMATS`` / + ``CFG_TUD_MTP_DEVICEINFO_PLAYBACK_FORMATS`` + - Required + - Object formats the device can create or expose for playback. + +The other ``CFG_TUD_MTP_DEVICEINFO_*`` lists describe supported events, device +properties, capture formats, and playback formats. These lists form the +GetDeviceInfo response and are a contract with the host. + +Application flow +================ + +.. list-table:: + :header-rows: 1 + :widths: 42 58 + + * - API or callback + - What it does + * - ``tud_mtp_mounted()`` + - Tests whether all three MTP endpoints are open. + * - ``tud_mtp_command_received_cb()`` + - Delivers the operation container and starts the application transaction + state machine. A negative return stalls the bulk endpoints. + * - ``tud_mtp_data_send()`` / ``tud_mtp_data_receive()`` + - Starts or continues the operation's data phase. ``false`` means the + transfer could not be queued in the current phase. + * - ``tud_mtp_response_send()`` + - Queues the final response container with the current transaction ID. + * - ``tud_mtp_event_send()`` + - Copies and queues one asynchronous event. Retry later when it returns + ``false`` because the event endpoint is busy. + * - ``tud_mtp_data_xfer_cb()`` + - Supplies or consumes the next chunk of a multi-packet data phase. + * - ``tud_mtp_data_complete_cb()`` / + ``tud_mtp_response_complete_cb()`` + - Advances application state after the entire data or response phase. + * - ``tud_mtp_request_*_cb()`` + - Handles cancel, reset, status, extended-event, and vendor control + requests. Return ``false`` or a negative length where documented to + stall an unsupported request. + +``tud_mtp_command_received_cb()`` receives an operation container. The +application performs any data phase with ``tud_mtp_data_send()`` or +``tud_mtp_data_receive()``, then completes the transaction with +``tud_mtp_response_send()``. Use ``tud_mtp_event_send()`` for asynchronous +events such as ObjectAdded. + +The ``tud_mtp_data_xfer_cb()``, ``tud_mtp_data_complete_cb()``, and +``tud_mtp_response_complete_cb()`` callbacks advance multi-stage transfers. +Control callbacks handle cancel, reset, status, and vendor requests. Validate +container lengths, object handles, property codes, and storage bounds before +using them. + +The :doc:`../../examples/device/mtp` example is the recommended template. It +implements a small in-memory object store, core session/object operations, an +upload, and an event. Replace its storage functions while preserving the +command/data/response state machine. + +TinyUSB supplies the USB transport and MTP containers; it does not provide a +filesystem, object database, stable handle allocation, or access arbitration. +Those remain application responsibilities. diff --git a/docs/reference/class/network.rst b/docs/reference/class/network.rst new file mode 100644 index 000000000..b0f8c8b46 --- /dev/null +++ b/docs/reference/class/network.rst @@ -0,0 +1,121 @@ +*********** +USB Network +*********** + +Role: device only. TinyUSB can present an Ethernet-style interface using +CDC-ECM, RNDIS, or CDC-NCM. The application connects Ethernet frames to a +network stack such as lwIP. + +Choose one driver +================= + +``CFG_TUD_ECM_RNDIS`` and ``CFG_TUD_NCM`` are mutually exclusive. + +* The ECM/RNDIS driver can expose separate configurations so Windows selects + RNDIS and macOS selects ECM; Linux can use either. +* NCM aggregates Ethernet datagrams into Network Transfer Blocks and is the + preferred starting point for current, higher-throughput designs. Windows + binding may require the Microsoft OS 2.0 descriptors shown by the example. + +Use the matching descriptor macro: ``TUD_CDC_ECM_DESCRIPTOR``, +``TUD_RNDIS_DESCRIPTOR``, or ``TUD_CDC_NCM_DESCRIPTOR``. Provide a unique +48-bit ``tud_network_mac_address`` and return the same address as a 12-digit +hexadecimal USB string descriptor where the class descriptor references it. + +Configuration options +===================== + +.. list-table:: + :header-rows: 1 + :widths: 42 16 42 + + * - Option + - Default + - What it controls + * - ``CFG_TUD_ECM_RNDIS`` / ``CFG_TUD_NCM`` + - ``0`` + - Selects one network class implementation. Enabling both is a build + error. + * - ``CFG_TUD_NET_MTU`` + - ``1514`` bytes + - Maximum Ethernet frame including its 14-byte Ethernet header. + * - ``CFG_TUD_NCM_OUT_NTB_MAX_SIZE`` + - ``3200`` bytes + - Largest host-to-device NTB received. Linux expects at least 2048 bytes. + * - ``CFG_TUD_NCM_IN_NTB_MAX_SIZE`` + - ``3200`` bytes + - Largest device-to-host NTB assembled for transmission. + * - ``CFG_TUD_NCM_OUT_NTB_N`` / ``CFG_TUD_NCM_IN_NTB_N`` + - ``1`` each + - Number of receive/transmit NTB buffers. Increasing these can reduce + stalls at a proportional RAM cost; benchmark before changing them. + * - ``CFG_TUD_NCM_IN_MAX_DATAGRAMS_PER_NTB`` + - ``8`` + - Maximum Ethernet frames TinyUSB aggregates into a transmit NTB. + * - ``CFG_TUD_NCM_OUT_MAX_DATAGRAMS_PER_NTB`` + - ``6`` + - Maximum frames the device tells the host to place in one receive NTB. + +Frame flow +========== + +For host-to-device frames, TinyUSB calls +``tud_network_recv_cb(src, size)``. Copy or pass the frame to the network stack +and call ``tud_network_recv_renew()`` when the supplied packet storage is no +longer needed. Return ``false`` if the frame cannot be accepted. + +For device-to-host frames: + +1. Call ``tud_network_can_xmit(size)``. +2. If it returns true, call ``tud_network_xmit(ref, arg)`` once. +3. TinyUSB calls ``tud_network_xmit_cb(dst, ref, arg)``; copy the complete + Ethernet frame into ``dst`` and return its length. + +Use ``tud_network_link_state()`` to notify the host when the logical or physical +link changes. A mounted USB device is not necessarily a link-up network +interface. + +.. list-table:: + :header-rows: 1 + :widths: 40 60 + + * - API or callback + - What it does + * - ``tud_network_recv_cb()`` + - Offers one received Ethernet frame. Return ``true`` only if the + application accepted the buffer or copied the frame. + * - ``tud_network_recv_renew()`` + - Releases the offered receive storage and permits the next host packet. + * - ``tud_network_can_xmit()`` / ``tud_network_xmit()`` + - Reserves room and requests one device-to-host frame. Call ``xmit`` only + once after a successful capacity check. + * - ``tud_network_xmit_cb()`` + - Copies the complete frame into TinyUSB's destination and returns its + actual byte length. + * - ``tud_network_init_cb()`` + - Resets the application network state when the ECM/RNDIS driver is + initialized or reset. + * - ``tud_network_set_packet_filter_cb()`` + - Reports NCM host filter bits so the application can adjust multicast or + promiscuous delivery. + * - ``tud_network_default_link_state_cb()`` / + ``tud_network_link_state()`` + - Supplies the initial NCM link state and later sends link up/down changes + to the host. + +NCM sizing +========== + +NCM buffer sizes have a direct RAM/throughput tradeoff. The class requires an +OUT NTB size of at least 2048 bytes. Begin with one IN and one OUT NTB, then +measure before increasing ``CFG_TUD_NCM_IN_NTB_MAX_SIZE``, +``CFG_TUD_NCM_OUT_NTB_MAX_SIZE``, or their ``*_NTB_N`` counts. Keep descriptor +capabilities and runtime responses consistent with the enabled NCM features. + +The :doc:`../../examples/device/net_lwip_webserver` example includes NCM and +ECM/RNDIS descriptor sets, lwIP integration, DHCP, DNS, link-state changes, and +host setup notes. + +Specifications used: *CDC Ethernet Control Model*, Revision 1.2, and *CDC +Network Control Model*, Revision 1.0 (Errata 1). RNDIS is a vendor protocol, +not a USB-IF CDC subclass. diff --git a/docs/reference/class/printer.rst b/docs/reference/class/printer.rst new file mode 100644 index 000000000..d3f20dbe3 --- /dev/null +++ b/docs/reference/class/printer.rst @@ -0,0 +1,91 @@ +******* +Printer +******* + +Role: device only. The Printer class provides bulk OUT data from a host print +spooler, optional bulk IN data for a bidirectional printer, and standard device +ID, port-status, and soft-reset requests. + +Configuration +============= + +Enable ``CFG_TUD_PRINTER`` and define the RX/TX FIFO and endpoint sizes. Add a +``TUD_PRINTER_DESCRIPTOR``; protocol 2 is the bidirectional interface used by +the TinyUSB example. + +.. code-block:: c + + #define CFG_TUD_PRINTER 1 + #define CFG_TUD_PRINTER_RX_BUFSIZE 64 + #define CFG_TUD_PRINTER_TX_BUFSIZE 64 + #define CFG_TUD_PRINTER_RX_EPSIZE 64 + #define CFG_TUD_PRINTER_TX_EPSIZE 64 + +.. list-table:: + :header-rows: 1 + :widths: 42 17 41 + + * - Option + - Default + - What it controls + * - ``CFG_TUD_PRINTER_RX_BUFSIZE`` / + ``CFG_TUD_PRINTER_TX_BUFSIZE`` + - Required when enabled + - Software FIFO capacity per printer interface. TX is still allocated + even if the application normally only receives print data. + * - ``CFG_TUD_PRINTER_RX_EPSIZE`` / + ``CFG_TUD_PRINTER_TX_EPSIZE`` + - Device bulk maximum + - Endpoint transfer buffer and descriptor packet size in each direction. + +Data received from the host is available through +``tud_printer_read_available()`` and ``tud_printer_read()``. Send status or +bidirectional data with ``tud_printer_write()`` and flush when the response +should leave promptly. Use the ``tud_printer_n_*`` forms for multiple +interfaces. + +.. list-table:: + :header-rows: 1 + :widths: 42 58 + + * - Data API or callback + - What it does + * - ``tud_printer_n_read_available()`` / + ``tud_printer_n_read()`` + - Reports and removes bytes sent by the print spooler. + * - ``tud_printer_n_write_available()`` / + ``tud_printer_n_write()`` + - Reports TX room and copies as much bidirectional response data as fits. + * - ``tud_printer_n_write_flush()`` + - Starts a short TX transfer and returns the number of bytes submitted. + * - ``tud_printer_n_read_flush()`` / + ``tud_printer_n_write_clear()`` + - Discards pending receive or transmit FIFO data, for example on soft + reset. + * - ``tud_printer_rx_cb()`` / + ``tud_printer_tx_complete_cb()`` + - Announces new input or newly available TX capacity. + +Control callbacks +================= + +``tud_printer_get_device_id_cb()`` must return an IEEE 1284 device ID. Its +first two bytes are the big-endian total length, including those two bytes, and +the buffer must remain valid through transfer completion. A typical text body +is ``MFG:Vendor;MDL:Model;CMD:PCL;CLS:PRINTER;``. + +Return current online, error, and paper state from +``tud_printer_get_port_status_cb()`` using +``tusb_printer_port_status_t``. In ``tud_printer_soft_reset_cb()``, cancel the +current print job and reset the class-facing parser without resetting unrelated +parts of a composite device. + +``tud_printer_request_complete_cb()`` marks the end of the control transfer and +is the safe point to reuse request-specific application state, including a +dynamically selected device-ID buffer. + +See :doc:`../../examples/device/printer_to_cdc` for bidirectional data and all +three class requests. + +Specification used: *USB Device Class Definition for Printing Devices*, +Version 1.1. diff --git a/docs/reference/class/usbtmc.rst b/docs/reference/class/usbtmc.rst new file mode 100644 index 000000000..dfa7ef649 --- /dev/null +++ b/docs/reference/class/usbtmc.rst @@ -0,0 +1,110 @@ +****** +USBTMC +****** + +Role: device only. USB Test and Measurement Class (USBTMC) carries instrument +commands and responses. The optional USB488 subclass adds IEEE-488-style +status, trigger, and service-request behavior; SCPI command parsing remains an +application concern. + +Configuration and descriptors +============================= + +Enable ``CFG_TUD_USBTMC``. Set ``CFG_TUD_USBTMC_ENABLE_488`` when USB488 is +implemented and ``CFG_TUD_USBTMC_ENABLE_INT_EP`` when an interrupt IN endpoint +is present. Construct the configuration from +``TUD_USBTMC_IF_DESCRIPTOR``, ``TUD_USBTMC_BULK_DESCRIPTORS``, and, when +enabled, ``TUD_USBTMC_INT_DESCRIPTOR``. + +.. list-table:: + :header-rows: 1 + :widths: 42 16 42 + + * - Option + - Default + - What it controls + * - ``CFG_TUD_USBTMC`` + - ``0`` + - Enables the device class. The current driver exposes one instrument + interface. + * - ``CFG_TUD_USBTMC_ENABLE_488`` + - ``1`` + - Builds USB488 capability, status-byte, and trigger support. Set it to + ``0`` for base USBTMC only. + * - ``CFG_TUD_USBTMC_ENABLE_INT_EP`` + - Example-defined + - Selects whether the example descriptor includes the notification + endpoint; keep this consistent with the capabilities response. + * - ``CFG_TUD_USBTMC_INT_EP_SIZE`` + - ``2`` bytes + - Internal interrupt notification buffer. It must fit the notification + format and descriptor packet size. + +Return a static capabilities structure from +``tud_usbtmc_get_capabilities_cb()``. Its flags must agree with the descriptor +and callbacks actually implemented. + +Message flow +============ + +.. list-table:: + :header-rows: 1 + :widths: 45 55 + + * - API or callback + - What it does + * - ``tud_usbtmc_open_cb()`` + - Announces an opened interface; initialize instrument transaction state + and arrange the first bus read. + * - ``tud_usbtmc_msgBulkOut_start_cb()`` / + ``tud_usbtmc_msg_data_cb()`` + - Accepts a device-dependent OUT header and subsequent payload chunks. + Return ``false`` when the message cannot be accepted. + * - ``tud_usbtmc_msgBulkIn_request_cb()`` + - Receives a host request for instrument data and should queue the response + when ready. + * - ``tud_usbtmc_transmit_dev_msg_data()`` + - Queues response data with EOM/termination flags. The source remains + application-owned and must stay unchanged until completion. + * - ``tud_usbtmc_msgBulkIn_complete_cb()`` + - Releases the response buffer and lets the application queue more data or + restart command reception. + * - ``tud_usbtmc_transmit_notification_data()`` + - Copies one interrupt notification when that endpoint is present; + ``false`` means the previous notification is still pending. + * - ``tud_usbtmc_start_bus_read()`` + - Arms the next bulk OUT transfer. Call it after every path that becomes + ready to receive another command. + * - ``tud_usbtmc_initiate_*_cb()`` / ``tud_usbtmc_check_*_cb()`` + - Starts and reports progress for abort/clear control requests. + * - ``tud_usbtmc_get_stb_cb()`` / + ``tud_usbtmc_msg_trigger_cb()`` + - Supplies the USB488 status byte and handles a USB488 trigger message. + +For host-to-instrument messages, TinyUSB calls +``tud_usbtmc_msgBulkOut_start_cb()`` followed by one or more +``tud_usbtmc_msg_data_cb()`` calls. ``transfer_complete`` marks a USB transfer, +not necessarily the end of the USBTMC message; use the message header and EOM +information to frame commands. + +When the host requests instrument data, prepare a response in +``tud_usbtmc_msgBulkIn_request_cb()`` and queue it with +``tud_usbtmc_transmit_dev_msg_data()``. The driver retains the buffer pointer, +so keep the data valid and unchanged until +``tud_usbtmc_msgBulkIn_complete_cb()``. + +Call ``tud_usbtmc_start_bus_read()`` during or soon after open and after each +message/completion path that is ready to accept another command. Failing to +restart the read is a common reason an instrument answers once and then stops. + +Implement abort and clear callbacks as a coherent state machine: stop the +pending operation, report progress through the corresponding check callback, +and restart the bus read when recovery completes. With USB488 enabled, +``tud_usbtmc_get_stb_cb()`` supplies the status byte and +``tud_usbtmc_msg_trigger_cb()`` handles trigger messages. + +The :doc:`../../examples/device/usbtmc` example implements ``*IDN?``, USB488 +status/trigger handling, abort/clear, and a PyVISA test script. + +Specifications used: *USB Test and Measurement Class Specification*, Revision +1.0, and *USBTMC USB488 Subclass Specification*, Revision 1.0. diff --git a/docs/reference/class/vendor.rst b/docs/reference/class/vendor.rst new file mode 100644 index 000000000..cd59cd276 --- /dev/null +++ b/docs/reference/class/vendor.rst @@ -0,0 +1,118 @@ +*************** +Vendor-specific +*************** + +The device driver provides bulk, and optionally interrupt or isochronous, +transfers for a vendor-defined interface. There is no generic vendor protocol: +the device descriptors, request semantics, framing, and host software are part +of the product's protocol. + +Device +====== + +Enable ``CFG_TUD_VENDOR`` and add ``TUD_VENDOR_DESCRIPTOR`` for the usual pair +of bulk endpoints. Buffered mode is the practical default. + +.. list-table:: + :header-rows: 1 + :widths: 43 17 40 + + * - Option + - Default + - What it controls + * - ``CFG_TUD_VENDOR_RX_BUFSIZE`` / + ``CFG_TUD_VENDOR_TX_BUFSIZE`` + - Device bulk maximum + - Software FIFO bytes. Setting either to zero selects direct mode for + both directions. + * - ``CFG_TUD_VENDOR_RX_EPSIZE`` / + ``CFG_TUD_VENDOR_TX_EPSIZE`` + - Device bulk maximum + - Bulk endpoint transfer buffers and descriptor packet sizes. + * - ``CFG_TUD_VENDOR_RX_MANUAL_XFER`` + - ``0`` + - Requires the application to call ``tud_vendor_n_read_xfer()`` to arm + each buffered bulk OUT transfer. + * - ``CFG_TUD_VENDOR_RX_NEED_ZLP`` + - ``0`` + - Allows multi-packet receive termination by a zero-length packet; enable + only when the custom host protocol sends that terminator. + * - ``CFG_TUD_VENDOR_EP_INT_OUT`` / + ``CFG_TUD_VENDOR_EP_INT_IN`` + - ``0`` + - Enables optional direct interrupt endpoints. Their buffer-size options + default to 64 bytes. + * - ``CFG_TUD_VENDOR_EP_ISO_OUT`` / + ``CFG_TUD_VENDOR_EP_ISO_IN`` + - ``0`` + - Enables optional direct isochronous endpoints. They require alternate + settings; their buffers default to 64 bytes. + * - ``CFG_TUD_VENDOR_ALT_SETTINGS`` + - ``0`` + - Enables alternate-setting tracking. It requires direct mode and is + required by the optional isochronous endpoints. + +Use ``tud_vendor_available()``/``tud_vendor_read()`` for OUT data and +``tud_vendor_write()``/``tud_vendor_write_flush()`` for IN data. In buffered +mode, ``tud_vendor_rx_cb()`` is only a notification; read the FIFO rather than +using its null buffer argument. + +For direct transfers, configure zero RX/TX FIFO sizes and follow the ownership +rules in ``vendor_device.h``. Optional interrupt, isochronous, and alternate +setting support is controlled by ``CFG_TUD_VENDOR_EP_*`` and +``CFG_TUD_VENDOR_ALT_SETTINGS``. Interrupt and isochronous OUT endpoints must +be explicitly re-armed after their receive callbacks. + +.. list-table:: + :header-rows: 1 + :widths: 43 57 + + * - API or callback + - What it does + * - ``tud_vendor_n_mounted()`` + - Tests whether an instance has any configured bulk, interrupt, or + isochronous endpoint open. + * - ``tud_vendor_n_available()`` / ``tud_vendor_n_read()`` + - Reports and removes bulk OUT FIFO bytes in buffered mode. + * - ``tud_vendor_n_write_available()`` / + ``tud_vendor_n_write()`` + - Reports room and copies as many bulk IN bytes as fit. In direct mode the + copy is limited to one endpoint buffer. + * - ``tud_vendor_n_write_flush()`` + - Starts a short buffered IN transfer and returns the number of bytes + submitted. + * - ``tud_vendor_rx_cb()`` / ``tud_vendor_tx_cb()`` + - Announces received data or completed output. In direct mode, consume or + copy the receive pointer before returning from the callback. + * - ``tud_vendor_n_int_read_xfer()`` / + ``tud_vendor_n_iso_read_xfer()`` + - Arms one optional OUT transfer; re-arm after each receive callback. + * - ``tud_vendor_n_int_write()`` / + ``tud_vendor_n_iso_write()`` + - Copies and queues at most one optional endpoint buffer and returns the + accepted byte count. + * - ``tud_vendor_n_alt()`` + - Returns the host-selected alternate setting when support is enabled. + +Handle vendor control requests in ``tud_vendor_control_xfer_cb()`` and perform +the data/status stage with ``tud_control_xfer()`` or +``tud_control_status()``. Validate ``bmRequestType``, ``bRequest``, +``wIndex``, ``wValue``, and ``wLength`` before accepting a request. + +The :doc:`../../examples/device/webusb_serial` example combines a vendor bulk +interface with WebUSB and Microsoft OS 2.0 descriptors. + +Host +==== + +A host cannot interpret an arbitrary vendor interface from its class code. +TinyUSB does not currently offer a supported, protocol-neutral +``tuh_vendor_*`` application API. For a simple fixed device, enable +``CFG_TUH_API_EDPT_XFER`` and use the descriptor/endpoint APIs demonstrated by +:doc:`../../examples/host/bare_api`. For a reusable protocol, implement a +custom host class driver that matches devices by descriptors and VID/PID and +owns their enumeration and transfer state. + +Define framing, version negotiation, maximum message lengths, timeouts, and +error recovery before deploying a vendor protocol. Never cast unvalidated +wire data directly to an application structure. diff --git a/docs/reference/class/video.rst b/docs/reference/class/video.rst new file mode 100644 index 000000000..07ff4412b --- /dev/null +++ b/docs/reference/class/video.rst @@ -0,0 +1,104 @@ +***** +Video +***** + +Role: device only. The USB Video Class (UVC) driver streams application-owned +video frames and handles the standard probe/commit negotiation used by host +camera software. + +Start from an example +===================== + +UVC descriptors contain a linked control topology plus one or more formats, +frames, intervals, and streaming alternate settings. Start from +:doc:`../../examples/device/video_capture` and change the format or dimensions +incrementally. Use :doc:`../../examples/device/video_capture_2ch` for multiple +control/streaming functions. + +Configuration +============= + +``CFG_TUD_VIDEO`` counts VideoControl interfaces and +``CFG_TUD_VIDEO_STREAMING`` counts VideoStreaming interfaces. Set +``CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE`` to at least the payload size used by the +stream. The examples use ``CFG_TUD_VIDEO_STREAMING_BULK`` to choose bulk or +isochronous descriptors; the endpoint type in those descriptors is what the +driver follows. + +.. list-table:: + :header-rows: 1 + :widths: 43 16 41 + + * - Option + - Default + - What it controls + * - ``CFG_TUD_VIDEO`` + - ``0`` + - Number of VideoControl functions retained by the driver. + * - ``CFG_TUD_VIDEO_STREAMING`` + - ``0`` + - Total VideoStreaming interfaces across all control functions. + * - ``CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE`` + - Required + - Per-stream USB payload buffer, including the UVC payload header. If it + is smaller than the negotiated payload, TinyUSB caps each transfer to + this size. + * - ``CFG_TUD_VIDEO_STREAMING_BULK`` + - Example-defined + - Chooses between the example's bulk and isochronous descriptor layouts; + it is not interpreted by the class driver itself. + +The helpers in ``src/class/video/video.h`` build individual UVC descriptor +blocks; unlike simpler classes, there is no single descriptor macro for every +camera topology. Verify entity IDs, terminal links, class-specific total +lengths, format/frame counts, endpoint addresses, and alternate settings as a +unit. + +Frame flow +========== + +.. list-table:: + :header-rows: 1 + :widths: 43 57 + + * - API or callback + - What it does + * - ``tud_video_n_connected()`` + - Tests whether a VideoControl function is mounted. + * - ``tud_video_n_streaming()`` + - Tests whether the host selected an active streaming alternate setting + for a control/stream pair. + * - ``tud_video_n_frame_xfer()`` + - Queues one non-empty frame. ``false`` means no active endpoint, probe is + in progress, or another frame is still owned by the driver. + * - ``tud_video_frame_xfer_complete_cb()`` + - Releases the queued frame after all of its UVC payloads complete. + * - ``tud_video_commit_cb()`` + - Validates and applies the host's committed format, frame index, and + interval; return a ``video_error_code_t`` value. + * - ``tud_video_power_mode_cb()`` + - Applies a host power-mode control request or returns an appropriate UVC + error. + * - ``tud_video_prepare_payload_cb()`` + - Fills payload bytes on demand when the frame was queued with a null data + pointer; honor the requested offset and maximum length. + +Wait for ``tud_video_n_streaming(ctl_idx, stm_idx)`` before submitting a frame. +Queue it with ``tud_video_n_frame_xfer()`` and do not modify or reuse the buffer +until ``tud_video_frame_xfer_complete_cb()``. + +Implement ``tud_video_commit_cb()`` to inspect and adopt the format, frame, and +interval committed by the host. Generate frames at the negotiated interval; +continuing at a hard-coded rate can overflow or starve the stream. + +For data generated directly into USB payloads, submit a null frame buffer with +the intended frame size and fill each request in +``tud_video_prepare_payload_cb()``. Respect the supplied length and offset and +avoid lengthy work in the callback. + +Isochronous endpoints reserve periodic bandwidth and tolerate a missed packet; +bulk endpoints retry errors but provide no bandwidth guarantee. Check that the +advertised maximum packet size is feasible for the controller and bus speed. + +Specification used: *USB Device Class Definition for Video Devices*, Revision +1.5. |
