summaryrefslogtreecommitdiff
path: root/docs/reference/class/midi.rst
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/midi.rst
parentf3021b337fcea154b898489c417d428c92f88e92 (diff)
doc: add class docscodex/class-reference-docs
Signed-off-by: HiFiPhile <[email protected]>
Diffstat (limited to 'docs/reference/class/midi.rst')
-rw-r--r--docs/reference/class/midi.rst214
1 files changed, 214 insertions, 0 deletions
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.