summaryrefslogtreecommitdiff
path: root/docs/reference/class
diff options
context:
space:
mode:
authorHiFiPhile <[email protected]>2026-08-01 19:22:52 +0200
committerHiFiPhile <[email protected]>2026-08-01 19:22:52 +0200
commitcd9bbed39f5851d5e4dc64271f18b8db777acb53 (patch)
tree83866c4127a6d808ba9eb6d543fe5d3787cd3af2 /docs/reference/class
parentf3021b337fcea154b898489c417d428c92f88e92 (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.rst131
-rw-r--r--docs/reference/class/bluetooth.rst75
-rw-r--r--docs/reference/class/cdc.rst169
-rw-r--r--docs/reference/class/device.rst159
-rw-r--r--docs/reference/class/dfu.rst92
-rw-r--r--docs/reference/class/hid.rst168
-rw-r--r--docs/reference/class/host.rst142
-rw-r--r--docs/reference/class/index.rst96
-rw-r--r--docs/reference/class/midi.rst214
-rw-r--r--docs/reference/class/msc.rst125
-rw-r--r--docs/reference/class/mtp.rst112
-rw-r--r--docs/reference/class/network.rst121
-rw-r--r--docs/reference/class/printer.rst91
-rw-r--r--docs/reference/class/usbtmc.rst110
-rw-r--r--docs/reference/class/vendor.rst118
-rw-r--r--docs/reference/class/video.rst104
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.