summaryrefslogtreecommitdiff
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
parentf3021b337fcea154b898489c417d428c92f88e92 (diff)
doc: add class docscodex/class-reference-docs
Signed-off-by: HiFiPhile <[email protected]>
-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
-rw-r--r--docs/reference/class_drivers.rst316
-rw-r--r--docs/reference/index.rst2
18 files changed, 2028 insertions, 317 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.
diff --git a/docs/reference/class_drivers.rst b/docs/reference/class_drivers.rst
deleted file mode 100644
index 4a101fabc..000000000
--- a/docs/reference/class_drivers.rst
+++ /dev/null
@@ -1,316 +0,0 @@
-***************
-Class Drivers
-***************
-
-USB Class Drivers implement specific USB device classes (CDC, HID, MSC, MIDI, Audio, etc.) and are the main interface between the USB core and application code.
-
-MIDI 2.0 Device Driver
-=======================
-
-Overview
---------
-
-The MIDI 2.0 Device driver enables TinyUSB to act as a USB MIDI 2.0 device. It implements both Alt Setting 0 (MIDI 1.0 fallback) and Alt Setting 1 (native UMP) as required by the USB-MIDI 2.0 specification.
-
-**Key Features:**
-
-- **Dual Alt Settings**: Alt 0 (MIDI 1.0) and Alt 1 (UMP native) per USB-MIDI 2.0 spec
-- **Protocol Negotiation**: Endpoint Discovery, Config Request/Notify, Function Block Discovery
-- **Group Terminal Block**: Served via GET_DESCRIPTOR automatically
-- **Atomic UMP Framing**: Read/write with correct message boundaries
-- **Memory Safe**: No dynamic allocation, static instances
-
-Configuration
--------------
-
-Enable MIDI 2.0 Device support in ``tusb_config.h``:
-
-.. code-block:: c
-
- #define CFG_TUD_ENABLED 1
- #define CFG_TUD_MIDI2 1
-
-Optional configuration:
-
-.. code-block:: c
-
- #define CFG_TUD_MIDI2_TX_BUFSIZE 256
- #define CFG_TUD_MIDI2_RX_BUFSIZE 256
- #define CFG_TUD_MIDI2_TX_EPSIZE 64
- #define CFG_TUD_MIDI2_RX_EPSIZE 64
- #define CFG_TUD_MIDI2_NUM_GROUPS 1 // 1..16
- #define CFG_TUD_MIDI2_NUM_FUNCTION_BLOCKS 1 // 1..32
- #define CFG_TUD_MIDI2_EP_NAME "TinyUSB MIDI 2.0"
- #define CFG_TUD_MIDI2_PRODUCT_ID "TinyUSB-MIDI2"
-
-Public API
-----------
-
-Query Functions
-^^^^^^^^^^^^^^^
-
-.. code-block:: c
-
- bool tud_midi2_mounted(void);
- uint32_t tud_midi2_available(void);
- uint8_t tud_midi2_alt_setting(void);
- bool tud_midi2_negotiated(void);
- uint8_t tud_midi2_protocol(void);
-
-I/O Functions
-^^^^^^^^^^^^^
-
-.. code-block:: c
-
- uint32_t tud_midi2_ump_read(uint32_t* words, uint32_t max_words);
- uint32_t tud_midi2_ump_write(const uint32_t* words, uint32_t count);
- uint32_t tud_midi2_packet_read(uint8_t packets[], uint32_t max_packets);
- uint32_t tud_midi2_packet_write(const uint8_t packets[], uint32_t count);
-
-Callbacks
-^^^^^^^^^
-
-.. code-block:: c
-
- void tud_midi2_rx_cb(uint8_t itf);
- void tud_midi2_set_itf_cb(uint8_t itf, uint8_t alt);
- bool tud_midi2_get_req_itf_cb(uint8_t rhport, const tusb_control_request_t* request);
-
-MIDI 2.0 Host Driver
-=====================
-
-Overview
---------
-
-The MIDI 2.0 Host driver enables TinyUSB to enumerate and communicate with USB MIDI 2.0 devices. It implements the USB MIDI 2.0 specification, supporting both MIDI 1.0 legacy devices and modern MIDI 2.0 devices with UMP (Universal MIDI Packet) protocol.
-
-**Key Features:**
-
-- **Reactive Architecture**: Auto-detects Alt Setting 1 (MIDI 2.0) capability during enumeration
-- **Auto-Selection**: Automatically selects the highest available protocol and issues SET_INTERFACE to activate Alt Setting 1 when MIDI 2.0 is detected
-- **Transparent Stream Messages**: All data (UMP packets + Stream Messages) flow through callbacks
-- **Memory Safe**: No dynamic allocation, fixed-size instances per device
-
-Configuration
--------------
-
-Enable MIDI 2.0 Host support in ``tusb_config.h``:
-
-.. code-block:: c
-
- #define CFG_TUH_ENABLED 1
- #define CFG_TUH_MIDI2 4 // Number of MIDI 2.0 devices to support
-
-Optional buffer configuration:
-
-.. code-block:: c
-
- #define CFG_TUH_MIDI2_RX_BUFSIZE (4 * TUH_EPSIZE_BULK_MAX)
- #define CFG_TUH_MIDI2_TX_BUFSIZE (4 * TUH_EPSIZE_BULK_MAX)
-
-Enumeration Lifecycle
----------------------
-
-When a MIDI 2.0 device is connected, the host stack invokes callbacks in this order:
-
-.. code-block:: none
-
- Device Connected
- |
- [Host detects Alt 0 and Alt 1 descriptors]
- |
- tuh_midi2_descriptor_cb() <- Device detected, NOT yet ready
- |
- [Auto-select highest protocol]
- |
- tuh_midi2_mount_cb() <- Device ready to use
- |
- [Application can read/write data]
- |
- tuh_midi2_rx_cb() <- Data arrived
- tuh_midi2_tx_cb() <- TX buffer space available
- |
- [Device disconnects]
- |
- tuh_midi2_umount_cb() <- Device removed
-
-Public API
-----------
-
-Query Functions
-^^^^^^^^^^^^^^^
-
-.. code-block:: c
-
- bool tuh_midi2_mounted(uint8_t idx);
- uint8_t tuh_midi2_get_protocol_version(uint8_t idx); // 0=MIDI 1.0, 1=MIDI 2.0
- uint8_t tuh_midi2_get_alt_setting_active(uint8_t idx); // 0 or 1
- uint8_t tuh_midi2_get_cable_count(uint8_t idx);
-
-I/O Functions
-^^^^^^^^^^^^^
-
-Read and write UMP (Universal MIDI Packet) data:
-
-.. code-block:: c
-
- uint32_t tuh_midi2_ump_read(uint8_t idx, uint32_t* words, uint32_t max_words);
- uint32_t tuh_midi2_ump_write(uint8_t idx, const uint32_t* words, uint32_t count);
- uint32_t tuh_midi2_write_flush(uint8_t idx);
-
-Callbacks
----------
-
-Application can define weak callback implementations to respond to device events.
-
-Descriptor Callback
-^^^^^^^^^^^^^^^^^^^
-
-Invoked when device is detected but not yet ready for I/O:
-
-.. code-block:: c
-
- void tuh_midi2_descriptor_cb(uint8_t idx, const tuh_midi2_descriptor_cb_t *desc_cb_data) {
- printf("MIDI %s device detected\r\n",
- desc_cb_data->protocol_version == 0 ? "1.0" : "2.0");
- }
-
-Mount Callback
-^^^^^^^^^^^^^^
-
-Invoked when device is ready for I/O:
-
-.. code-block:: c
-
- void tuh_midi2_mount_cb(uint8_t idx, const tuh_midi2_mount_cb_t *mount_cb_data) {
- printf("Device mounted at idx=%u, protocol=%u, alt_setting=%u\r\n",
- idx, mount_cb_data->protocol_version, mount_cb_data->alt_setting_active);
- }
-
-RX Callback
-^^^^^^^^^^^
-
-Invoked when data arrives from device (both UMP packets and Stream Messages):
-
-.. code-block:: c
-
- void tuh_midi2_rx_cb(uint8_t idx, uint32_t xferred_bytes) {
- uint32_t words[4];
- uint32_t n = tuh_midi2_ump_read(idx, words, 4);
-
- for (uint32_t i = 0; i < n; i++) {
- uint8_t mt = (words[i] >> 28) & 0x0F;
- if (mt == 0x0F) {
- // Stream Message - app handles discovery, negotiation, etc.
- } else {
- // Regular MIDI UMP packet
- }
- }
- }
-
-TX Callback
-^^^^^^^^^^^
-
-Invoked when TX buffer space becomes available:
-
-.. code-block:: c
-
- void tuh_midi2_tx_cb(uint8_t idx, uint32_t xferred_bytes) {
- // Buffer space available for writing
- }
-
-Unmount Callback
-^^^^^^^^^^^^^^^^
-
-Invoked when device is disconnected:
-
-.. code-block:: c
-
- void tuh_midi2_umount_cb(uint8_t idx) {
- printf("Device at idx=%u disconnected\r\n", idx);
- }
-
-Complete Example
-----------------
-
-.. code-block:: c
-
- #include "tusb.h"
-
- void tuh_midi2_mount_cb(uint8_t idx, const tuh_midi2_mount_cb_t *mount_cb_data) {
- printf("MIDI 2.0 device mounted\r\n");
- }
-
- void tuh_midi2_rx_cb(uint8_t idx, uint32_t xferred_bytes) {
- uint32_t words[4];
- uint32_t n = tuh_midi2_ump_read(idx, words, 4);
-
- for (uint32_t i = 0; i < n; i++) {
- printf("RX: 0x%08lx\r\n", words[i]);
- }
- }
-
- void tuh_midi2_umount_cb(uint8_t idx) {
- printf("MIDI 2.0 device disconnected\r\n");
- }
-
- int main(void) {
- board_init();
-
- tusb_rhport_init_t host_init = {.role = TUSB_ROLE_HOST, .speed = TUSB_SPEED_AUTO};
- tusb_init(BOARD_TUH_RHPORT, &host_init);
-
- while (1) {
- tuh_task();
- }
- }
-
-Architecture
-------------
-
-The MIDI 2.0 Host driver uses a **reactive, callback-driven architecture** that mirrors the proven patterns in TinyUSB's existing device drivers (CDC, HID, etc.):
-
-- **Auto-Detection**: Host automatically detects Alt Setting 1 capability
-- **Auto-Selection**: Selects highest protocol available and issues SET_INTERFACE
-- **Transparent I/O**: Stream Messages and UMP packets flow through callbacks
-- **Callback-Driven**: App receives events via callbacks (descriptor, mount, rx, tx, unmount)
-
-Differences from MIDI 1.0 Host
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-.. list-table::
- :header-rows: 1
-
- * - Aspect
- - MIDI 1.0 Host
- - MIDI 2.0 Host
- * - Alt Settings
- - Parses only Alt 0
- - Parses Alt 0 + Alt 1
- * - Data Format
- - 4-byte MIDI packets
- - UMP (32/64/128-bit)
- * - Version Detection
- - None
- - bcdMSC from descriptor
- * - GTB
- - N/A
- - Presence detection
- * - Stream Messages
- - N/A
- - Transparent passthrough
- * - Callbacks
- - descriptor_cb, mount_cb, rx_cb, umount_cb
- - descriptor_cb, mount_cb, rx_cb, tx_cb, umount_cb
- * - Public API
- - tuh_midi_*
- - tuh_midi2_*
-
-Implementation Notes
---------------------
-
-- All internal state is statically allocated (no dynamic allocation)
-- Endpoint streams use TinyUSB's tu_edpt_stream_t for buffered I/O
-- Protocol version detection via bcdMSC field
-- Alt Setting is automatically selected during mount
-- Compatible with all TinyUSB-supported MCU families
diff --git a/docs/reference/index.rst b/docs/reference/index.rst
index c66ce618f..0c46f6531 100644
--- a/docs/reference/index.rst
+++ b/docs/reference/index.rst
@@ -9,7 +9,7 @@ Complete reference documentation for TinyUSB APIs, configuration, and supported
architecture
usb_concepts
- class_drivers
+ class/index
boards
dependencies
concurrency