diff options
Diffstat (limited to 'src/class/midi/midi2_device.h')
| -rw-r--r-- | src/class/midi/midi2_device.h | 119 |
1 files changed, 91 insertions, 28 deletions
diff --git a/src/class/midi/midi2_device.h b/src/class/midi/midi2_device.h index e53535693..e3eb084d9 100644 --- a/src/class/midi/midi2_device.h +++ b/src/class/midi/midi2_device.h @@ -1,25 +1,7 @@ /* - * The MIT License (MIT) - * - * Copyright (c) 2026 Saulo Verissimo - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. + * SPDX-FileCopyrightText: Copyright (c) 2026 Saulo Verissimo + * SPDX-FileCopyrightText: Copyright (c) 2026 Ha Thach (tinyusb.org) + * SPDX-License-Identifier: MIT * * This file is part of the TinyUSB stack. */ @@ -37,7 +19,7 @@ // Config defaults are in tusb_option.h: // CFG_TUD_MIDI2_RX_EPSIZE, CFG_TUD_MIDI2_TX_EPSIZE, // CFG_TUD_MIDI2_RX_BUFSIZE, CFG_TUD_MIDI2_TX_BUFSIZE, -// CFG_TUD_MIDI2_NUM_GROUPS, CFG_TUD_MIDI2_NUM_FUNCTION_BLOCKS, +// CFG_TUD_MIDI2_NUM_GROUPS, // CFG_TUD_MIDI2_EP_NAME, CFG_TUD_MIDI2_PRODUCT_ID #ifdef __cplusplus @@ -68,10 +50,6 @@ extern "C" { #define CFG_TUD_MIDI2_NUM_GROUPS 1 #endif -#ifndef CFG_TUD_MIDI2_NUM_FUNCTION_BLOCKS - #define CFG_TUD_MIDI2_NUM_FUNCTION_BLOCKS 1 -#endif - #ifndef CFG_TUD_MIDI2_EP_NAME #define CFG_TUD_MIDI2_EP_NAME "TinyUSB MIDI 2.0" #endif @@ -80,6 +58,17 @@ extern "C" { #define CFG_TUD_MIDI2_PRODUCT_ID "TinyUSB-MIDI2" #endif +// Function Block capabilities reported in Function Block Info Notification. +// The GTB descriptor carries direction and group span, but not these: they +// depend on what the application implements, so they default to "none". +#ifndef CFG_TUD_MIDI2_FB_CI_VERSION + #define CFG_TUD_MIDI2_FB_CI_VERSION 0 // 0: none or unknown, 1 or higher: MIDI-CI version +#endif + +#ifndef CFG_TUD_MIDI2_FB_SYSEX8_STREAMS + #define CFG_TUD_MIDI2_FB_SYSEX8_STREAMS 0 // 0: unsupported, 1: single, 2-255: simultaneous streams +#endif + // String descriptor index for the Group Terminal Block (iBlockItem, Table 5-6). // 0 = no string descriptor (default, spec-allowed). #ifndef CFG_TUD_MIDI2_BLOCK_STRIDX @@ -87,6 +76,39 @@ extern "C" { #endif //--------------------------------------------------------------------+ +// Group Terminal Block descriptor builders (USB-MIDI 2.0 Table 5-5/5-6) +//--------------------------------------------------------------------+ +// Group Terminal Block descriptor type and subtypes. +enum { + MIDI2_CS_GRP_TRM_BLOCK = 0x26, // bDescriptorType + MIDI2_GRP_TRM_BLOCK_HEADER = 0x01, // bDescriptorSubtype: list header + MIDI2_GRP_TRM_BLOCK_ENTRY = 0x02, // bDescriptorSubtype: block entry +}; + +// Block direction (bGrpTrmBlkType). +enum { + MIDI2_GTB_BIDIRECTIONAL = 0x00, + MIDI2_GTB_INPUT_ONLY = 0x01, + MIDI2_GTB_OUTPUT_ONLY = 0x02, +}; + +// GTB descriptor sizes (bytes). +enum { + MIDI2_GTB_HEADER_LEN = 5, // list header + MIDI2_GTB_ENTRY_LEN = 13, // one block entry +}; + +// Build a multi-block GTB descriptor for tud_midi2_gtb_desc_cb. Function Block +// Info is derived from these blocks (direction + group span). +#define TUD_MIDI2_GTB_DESC_LEN(_nblocks) (MIDI2_GTB_HEADER_LEN + MIDI2_GTB_ENTRY_LEN * (_nblocks)) +#define TUD_MIDI2_GTB_HEADER(_nblocks) \ + MIDI2_GTB_HEADER_LEN, MIDI2_CS_GRP_TRM_BLOCK, MIDI2_GRP_TRM_BLOCK_HEADER, \ + U16_TO_U8S_LE(TUD_MIDI2_GTB_DESC_LEN(_nblocks)) +#define TUD_MIDI2_GTB_BLOCK(_id, _type, _first_group, _num_groups, _stridx) \ + MIDI2_GTB_ENTRY_LEN, MIDI2_CS_GRP_TRM_BLOCK, MIDI2_GRP_TRM_BLOCK_ENTRY, \ + (_id), (_type), (_first_group), (_num_groups), (_stridx), 0x00, 0, 0, 0, 0 + +//--------------------------------------------------------------------+ // MIDI Protocol Values (returned by tud_midi2_n_protocol) //--------------------------------------------------------------------+ @@ -96,6 +118,28 @@ enum { MIDI_PROTOCOL_MIDI2 = 0x02, }; +// Result of the optional UMP Stream message callback (tud_midi2_stream_msg_cb). +// PASS lets the built-in responder handle the message; the others mean the +// application answered it. NEGOTIATED_* also record the protocol so +// tud_midi2_n_protocol / tud_midi2_n_negotiated stay accurate. +typedef enum { + MIDI2_STREAM_PASS = 0, + MIDI2_STREAM_HANDLED, + MIDI2_STREAM_NEGOTIATED_MIDI1, + MIDI2_STREAM_NEGOTIATED_MIDI2, +} tud_midi2_stream_result_t; + +// Device identity fields, as defined for the MIDI 1.0 Device Inquiry reply and +// reused by the Device Identity Notification. Every byte carries 7 bits. +// A 1-byte System Exclusive ID goes in the first of the three manufacturer +// bytes, so 0x7D is passed as 0x7D0000. +typedef struct { + uint32_t manufacturer; // 3 bytes, first byte is most significant + uint16_t family; // 2 bytes + uint16_t model; // 2 bytes + uint32_t sw_revision; // 4 bytes +} tud_midi2_device_identity_t; + //--------------------------------------------------------------------+ // Application Callback API (weak, optional) //--------------------------------------------------------------------+ @@ -104,11 +148,30 @@ 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); // Per-interface UMP Stream config (override for per-itf values). -uint8_t tud_midi2_num_groups_cb(uint8_t itf); -uint8_t tud_midi2_num_function_blocks_cb(uint8_t itf); const char* tud_midi2_ep_name_cb(uint8_t itf); const char* tud_midi2_product_id_cb(uint8_t itf); +// Group Terminal Block descriptor source: the single source of truth for block +// topology. Override to expose multiple blocks with independent directions and +// group spans. Function Block Info is derived from this descriptor. +const uint8_t* tud_midi2_gtb_desc_cb(uint8_t itf, uint16_t* len); + +// Optional per-block name, sent as a Function Block Name Notification during +// discovery. Return NULL or "" for no name. +const char* tud_midi2_fb_name_cb(uint8_t itf, uint8_t fb_idx); + +// Optional device identity, sent as a Device Identity Notification when the +// host sets the 'd' bit in the Endpoint Discovery filter. Same four fields as +// the MIDI 1.0 Device Inquiry reply. Return false to skip the notification, +// which is the default. All values are 7-bit per byte. +bool tud_midi2_device_identity_cb(uint8_t itf, tud_midi2_device_identity_t* identity); + +// Optional: intercept an incoming UMP Stream message (MT 0xF). Return PASS to +// let the built-in responder handle it, or HANDLED / NEGOTIATED_* if the app +// answered it (e.g. via tud_midi2_n_ump_write). Lets an app override a single +// response without reimplementing the whole negotiation. +tud_midi2_stream_result_t tud_midi2_stream_msg_cb(uint8_t itf, const uint32_t* ump_words); + //--------------------------------------------------------------------+ // Application API (Multiple Interfaces) //--------------------------------------------------------------------+ |
