# Changelog
Format based on Keep a Changelog. This project follows Semantic Versioning.
## [Unreleased]
## [0.10.0]
### Changed
- `midi2_msg_stream_fb_info()` and the `on_fb_info` dispatch callback drop
their `protocol` parameter. Word 1 of a Function Block Info Notification
carries four byte-wide fields (M2-104-UM 7.1.8) and no protocol field.
Callers pass one argument less.
- Software Revision Level is carried as four manufacturer defined bytes,
replacing the 28-bit packing used since 0.8.0. Both M2-104-UM 7.1.3 and
M2-101-UM 5.5 describe the field as four bytes whose format is device
specific, and the M2-105 DeviceInfo schema types it as a four item byte
array. The change covers the UMP Stream Device Identity Notification and
MIDI-CI Discovery, so a device declaring `0x00010000` now puts
`00 01 00 00` on the wire in both.
### Fixed
- Function Block Info encodes and decodes the layout the spec defines: Max
Number of SysEx8 Streams occupies the low byte and covers its documented
0-255 range, MIDI-CI Message Version is a byte, and Number of Groups
Spanned fits the maximum of 16.
- The `atmega32u4-device-baremetal` example packs its manufacturer id the
way the CI builder expects, and the `teensy-device-midi2` example declares
the same identity across Property Exchange, UMP Stream and MIDI-CI.
## [0.9.0]
### Added
- `midi2_conv_next()`: drains the additional message a single MIDI 1.0 byte
can produce. Per M2-104-UM 7.7.1, System Real-Time may interleave inside a
SysEx and any other status terminates it, so one byte can yield two UMP
messages; the canonical consumption loop is now
`if (midi2_conv_feed(...)) do { ... } while (midi2_conv_next(...));`.
For ordinary bytes the loop body runs once. Debug builds assert if a queued
message is left undrained; release builds drop it.
### Fixed
- `midi2_conv`: a completed System Common message (F1-F3) no longer leaves
its status as Running Status. Data bytes arriving after Song Position,
Song Select or MTC Quarter Frame are orphans per MIDI 1.0 -- previously
every further data-byte pair fabricated another copy of the message.
### Changed
- `midi2_conv` now applies the M2-104-UM 7.7.1 interspersing rules:
- A Real-Time byte inside a SysEx is emitted after the partial packet
holding the bytes that preceded it on the wire, preserving its timing
position (previously it was emitted first, reordering it ahead of data
it followed).
- A status byte inside a SysEx closes the message with a COMPLETE or END
packet carrying the bytes received (previously the buffered bytes were
dropped and an already-emitted START was left unterminated).
- A SysEx Start while another SysEx is open closes the previous message
the same way before starting the new one.
Verified against the byte vectors from AM_MIDI2.0Lib issues #16, #23 and
#24; the first packets for the #24 vector now match that issue's expected
words exactly.
## [0.8.0]
### Added
- Example `atmega32u4-device-arduino`: USB MIDI 2.0 device on the Arduino
Leonardo over the midi2duino transport, with UMP Stream and MIDI-CI
responders. MIDI-CI replies are queued atomically and inbound Data128 is
echoed directly, so a full TX ring cannot corrupt USB output.
- Example `atmega32u4-device-baremetal`: USB MIDI 2.0 device on the Arduino
Pro Micro, bare metal C99 over the midi2lufa transport, with the 58-entry
M2-104 catalog, UMP Stream and MIDI-CI responders, and a MIDI 1.0
fallback riff. Validated on hardware (Linux ALSA UMP, echo, per-boot MUID).
### Changed
- Device identity field byte order in the Stream and MIDI-CI builders now
follows M2-104 Figure 14 and the MIDI-CI Discovery tables: the packed
`manufacturer_id` is `id1<<16 | id2<<8 | id3` (the educational prefix
0x7D packs as 0x7D0000), family and model are 14-bit values sent as
7-bit LSB/MSB pairs, and the version is 28 bits sent as four 7-bit
bytes LSB first. Callers that passed the manufacturer id in the
previous packed form must update; the wire layout is cross-checked
against the MIDI 2.0 Workbench, the Linux kernel UMP driver and
Windows MIDI Services.
### Fixed
- MIDI-CI responder re-announces via Discovery after receiving an Invalidate
MUID or detecting a MUID collision (Workbench ci1.2).
- Multi-packet senders (`midi2_proc_send_sysex7`, `midi2_proc_send_sysex8`,
`midi2_proc_send_fb_name`, endpoint name and product id) stop at the first
short write instead of continuing past it, so a full transport sink can no
longer leave a gap in the middle of a message. The receiver resynchronizes
on the next Start packet.
## [0.7.0]
Validated end to end against the official MIDI 2.0 Workbench on hardware
(Teensy 4.1, RP2350, Raspberry Pi Pico): Discovery, Profile Configuration, and
Property Exchange with zero errors and zero warnings.
### Added
- MIDI-CI responder handles Set Profile On/Off: a listed always-on profile
answers with a Profile Enabled Report, an unlisted profile is NAKed.
- MIDI-CI responder handles Process Inquiry MIDI Message Report: Reply and End
messages for Function Block and in-use channel requests, NAK for channels
not in use.
### Fixed
- Property Exchange Get replies for list resources (ResourceList, ChannelList,
ProgramList) now carry `totalCount` in the header, as M2-105 requires for
paginable resources. Object resources such as DeviceInfo are unchanged.
### Changed
- Example set reduced to three real USB MIDI 2.0 devices sharing the C99 core:
`teensy-device-midi2` (Arduino loop), `rp2350-device-freertos`
(FreeRTOS + TinyUSB), and `rpi-pico-device-zephyr` (native `usbd_midi2`). The
two synthetic sketches (`basic-usage`, `ci-discovery`) were removed. The
Teensy sketch announces the UMP Stream identity in-band so hosts running
active Endpoint Discovery register it.
## [0.6.1]
- MIDI-CI responder declares Message Version 0x02 across all replies.
- Property Exchange Get/Set replies carry a status header, match the requested
resource, and return 404 when it does not exist.
- Added `midi2_ci_set_capabilities` and a built-in `ResourceList` resource.
## [0.6.0]
- `midi2_dispatch_feed` and `midi2_proc_feed` drop a typed message shorter than
its type requires instead of over-reading.
- `midi2_ci` returns `MIDI2_CI_ERR_NULL` for a NULL state or name in the
property and subscribe entry points.
- Added an overridable `MIDI2_ASSERT` and a debug-only reentrancy guard (both
compiled out under `NDEBUG`). Reproducible amalgam (no build-date stamp).
## [0.5.0]
- Zephyr module support and a Raspberry Pi Pico example.
- NULL arguments at public entry points are no-ops or zero returns;
`midi2_msg_word_count` covers all 16 message types.
## [0.4.0]
Breaking signature changes so the builders emit spec fields they previously
dropped. Default-safe values reproduce the prior wire behaviour; migration
snippets are in git history.
- UMP Stream: Config Request and Notify gain JR enable bits; FB Info gains
`ui_hint` and `max_sysex8_streams`.
- Utility: `midi2_msg_jr_clock` and `_jr_timestamp` drop the now-reserved Group
parameter; added `midi2_msg_noop`.
- MIDI 2.0 Channel Voice: Note On/Off split the attribute into `attr_type` plus
a 16-bit `attr_data`; Program Change Bank Valid bit moved to the spec lane.
- Flex Data: `midi2_msg_time_sig` gains `num_32nd_notes`.
## [0.3.4]
- ESP-IDF gate consumes the modular `src/*.c` set the Component Manager
delivers (it filters `dist/` out of the dependency tarball).
## [0.3.3]
- ESP-IDF Component Manager support via a root `idf_component.yml` and an
`ESP_PLATFORM` gate ahead of `project()`, so native CMake consumers are
unaffected.
## [0.3.2]
- CMake build alongside the Makefile: `midi2::midi2` target, install and export
ruleset for `find_package(midi2 CONFIG)`, FetchContent support, and a
downstream consumer test.
## [0.3.1]
- Arduino Library Manager compliance: `library.properties`, the `src/midi2.h`
umbrella, and reference sketches. Registered on the Arduino Library Manager.
## [0.3.0]
- Property Exchange Subscribe/Notify state machine (M2-101-UM 8.11 to 8.13) via
`midi2_ci_init_ex`; legacy `midi2_ci_init` stays source-compatible.
- UMP Stream and SysEx8 fragmenters in `midi2_proc`; MT 0x4 to MT 0x2 downgrade;
USB MIDI 1.0 cable-event helper; System message wrappers.
- Breaking: `midi2_ci_property` gains a trailing `subscribable` bool
(designated-initialiser call sites compile unchanged).
## [0.2.4]
- MIDI-CI responder completeness (M2-101-UM Appendix E): MUID regeneration and
collision detection, NAK-on-unknown, and an automatic PE Capability reply.
Additive, no breaking change.
## [0.2.3]
- `dist/midi2.c` companion to the single header; `tools/amalgamate.sh` emits
both files under `dist/`. Spec references added across the module headers.
## [0.2.2]
- Single-header amalgam (`midi2.h`, stb-style).
- `midi2_msg_mt2_to_mt4` protocol translation with value scaling and a dispatch
`upscale_mt2` flag; streaming SysEx7 in `midi2_conv`.
## [0.2.0]
- `midi2_dispatch` (42 typed UMP callbacks), `midi2_ci_msg` and
`midi2_ci_dispatch` (full MIDI-CI surface), complete UMP construction.
- Fixed the Utility status nibble shift and the SysEx dispatch status values.
## [0.1.0]
Initial release: `midi2_msg`, `midi2_proc`, `midi2_ci`, `midi2_conv`. Caller
provided storage, zero allocation, C99.