Skip to content

feat(midi2): opt-in app responder for UMP Stream#3739

Closed
sauloverissimo wants to merge 1 commit into
hathach:masterfrom
sauloverissimo:feat/midi2-user-responder
Closed

feat(midi2): opt-in app responder for UMP Stream#3739
sauloverissimo wants to merge 1 commit into
hathach:masterfrom
sauloverissimo:feat/midi2-user-responder

Conversation

@sauloverissimo

Copy link
Copy Markdown
Contributor

Summary

Small, opt-in change, quick to review. Touches only the MIDI 2.0 device class
(legacy MIDI 1.0 driver untouched) and is byte-identical to current behavior
when the flag is off.

Adds CFG_TUD_MIDI2_USER_RESPONDER (default off). When set, the driver leaves
UMP Stream messages in the RX FIFO so the application can answer Endpoint /
Function Block discovery and Stream Configuration itself, for endpoints whose
topology is dynamic (e.g. a bridge whose function blocks track the devices
plugged into it). Built-in responder is unchanged when off.

Test plan

  • Builds with the flag off (default) and on (RP2350 midi2_device example).
  • Used on hardware by an ESP32-P4 USB MIDI bridge to expose dynamic FB names/groups.

Ref #3571

Copilot AI review requested due to automatic review settings June 27, 2026 03:56

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an opt-in build-time switch to the MIDI 2.0 device class that lets applications take over UMP Stream (MT=0xF) discovery/configuration handling, while preserving current driver behavior when the option is disabled.

Changes:

  • Introduces CFG_TUD_MIDI2_USER_RESPONDER (default 0) configuration define.
  • When enabled, disables the built-in UMP Stream responder and leaves UMP Stream messages in the RX FIFO for the application to read/handle.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
src/class/midi/midi2_device.h Adds the new opt-in configuration macro default.
src/class/midi/midi2_device.c Gates the built-in UMP Stream negotiation responder and skips consuming stream messages when user-responder mode is enabled.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +89 to +91
#ifndef CFG_TUD_MIDI2_USER_RESPONDER
#define CFG_TUD_MIDI2_USER_RESPONDER 0
#endif
Comment on lines +390 to +395
#if CFG_TUD_MIDI2_USER_RESPONDER
// User responder owns UMP Stream discovery: MT 0xF messages stay in the
// RX FIFO and surface through tud_midi2_n_ump_read so the application can
// answer Endpoint / Function Block discovery itself.
(void)p_midi;
#else

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5f8a734576

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +390 to +394
#if CFG_TUD_MIDI2_USER_RESPONDER
// User responder owns UMP Stream discovery: MT 0xF messages stay in the
// RX FIFO and surface through tud_midi2_n_ump_read so the application can
// answer Endpoint / Function Block discovery itself.
(void)p_midi;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve negotiation state in user responder mode

With CFG_TUD_MIDI2_USER_RESPONDER=1, this branch returns before the only code path that handles STREAM_CONFIG_REQUEST; since there is also no public setter for p_midi->protocol or p_midi->negotiated, an application that accepts a host's MIDI 1.0 Config Request and sends its own Config Notify will still see tud_midi2_n_protocol() report the reset default MIDI2 and tud_midi2_n_negotiated() stay false. Please either keep parsing config requests for state or provide a way for the user responder to update these getters.

Useful? React with 👍 / 👎.

CFG_TUD_MIDI2_USER_RESPONDER lets the application answer UMP Stream
discovery (Endpoint, Function Block, Stream Config) instead of the
built-in responder, for endpoints with dynamic topology. Ref hathach#3571
@sauloverissimo sauloverissimo force-pushed the feat/midi2-user-responder branch from 5f8a734 to 08d6bf8 Compare June 27, 2026 04:17
@sauloverissimo

Copy link
Copy Markdown
Contributor Author

Updated to address the automated review: added tud_midi2_n_set_protocol() so the application can keep tud_midi2_n_protocol / tud_midi2_n_negotiated accurate when it owns UMP Stream negotiation, plus header/.c notes on draining the RX FIFO. Builds with the flag off (default) and on.

@github-actions

github-actions Bot commented Jun 27, 2026

Copy link
Copy Markdown

Hardware-in-the-loop (HIL) Test Report

hfp.json

✅ 52 passed · ❌ 0 failed · ⚪ 0 skipped · blank not run

Board cdc_dual_ports cdc_msc dfu cdc_msc_throughput audio_test_freertos dfu_runtime cdc_msc_freertos hid_boot_interface msc_dual_lun hid_generic_inout printer_to_cdc midi_test mtp
stm32l412nucleo ✅ CDC 628k/403k MSC 825k/767k
stm32f746disco ✅ CDC 13.7M/10M MSC 15.4M/28.8M
stm32f746disco-DMA ✅ CDC 13.4M/9.2M MSC 18M/29.8M
lpcxpresso43s67 ✅ CDC 12.6M/11.8M MSC 29.6M/32.5M

tinyusb.json

✅ 200 passed · ❌ 138 failed · ⚪ 11 skipped · blank not run

Board cdc_dual_ports cdc_msc dfu cdc_msc_throughput audio_test_freertos dfu_runtime cdc_msc_freertos hid_boot_interface msc_dual_lun hid_generic_inout printer_to_cdc midi_test mtp host_info_to_device_cdc cdc_msc_hid msc_file_explorer msc_file_explorer_freertos device_info hid_composite_freertos
ek_tm4c123gxl ✅ CDC 849k/1M MSC 825k/941k
espressif_p4_function_ev rd 409KB/s
espressif_p4_function_ev-DMA rd 409KB/s
espressif_s3_devkitm rd 409KB/s
espressif_s3_devkitm-DMA rd 409KB/s
feather_nrf52840_express
max32666fthr
metro_m4_express
mimxrt1015_evk
mimxrt1064_evk
lpcxpresso11u37
ra4m1_ek
raspberry_pi_pico
raspberry_pi_pico_w
raspberry_pi_pico2
adafruit_fruit_jam
stm32f072disco ✅ CDC 466k/333k MSC 617k/499k
stm32f407disco ✅ CDC 921k/496k MSC 830k/916k
stm32f723disco ✅ CDC 738k/776k MSC 704k/921k rd 18078KB/s rd 4096KB/s
stm32f723disco-DMA ✅ CDC 922k/786k MSC 921k/986k rd 19418KB/s rd 4096KB/s
stm32h743nucleo ✅ CDC 838k/864k MSC 941k/1M
stm32h743nucleo-DMA ✅ CDC 137k/640k MSC 908k/669k
stm32g0b1nucleo ✅ CDC 488k/485k MSC 564k/538k
stm32l476disco ✅ CDC 509k/506k MSC 551k/907k
stm32u083nucleo ✅ CDC 370k/479k MSC 636k/542k
nanoch32v203-fsdev ✅ CDC 754k/181k MSC 775k/824k
nanoch32v203-usbfs ✅ CDC 663k/684k MSC 537k/970k
ch32v103r_r1_1v0
ch582m_evt ✅ CDC 231k/219k MSC 434k/463k

@github-actions

Copy link
Copy Markdown

MemBrowse Memory Report

No memory changes detected across 2404 targets. View Project Dashboard →

@@ -402,6 +411,7 @@ static void _nego_process_rx(midi2d_interface_t* p_midi) {
tu_edpt_stream_read(ep_rx, buf, pkt_bytes);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm thinking about adding a weak callback here, with the return value we can differentiate between Handled, Negotiated to V1 , Negotiated to V2 , etc.

Maybe the user only want to override a one specific response instead of implement full negotiation in app.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @HiFiPhile! Are you thinking of a per-message hook at the stream dispatch, where the return value decides fallthrough vs handled? So the app could intercept just FB Discovery, say, and let the built-in responder take the rest.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes exactely.

@sauloverissimo

Copy link
Copy Markdown
Contributor Author

Closing this in favor of #3738. While I was working through the function block changes there, I ended up adding a per-message callback (tud_midi2_stream_msg_cb, returning PASS / HANDLED / NEGOTIATED_*) that does what the CFG_TUD_MIDI2_USER_RESPONDER flag here does, but per message and without a compile-time switch. That made this one redundant.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants