From c8914517ba87a86c62d0040645e16071765760e0 Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Tue, 17 Dec 2024 21:56:05 +0100 Subject: [PATCH 01/67] Store raw data inside UsbMidiEventPacket --- examples/example-esp32s3/CHANGELOG.md | 37 ++++++ examples/example-esp32s3/src/main.rs | 7 +- src/data/byte/u7.rs | 2 +- src/data/midi/message/control_function.rs | 2 +- src/data/midi/message/mod.rs | 2 +- src/data/usb_midi/cable_number.rs | 1 + src/data/usb_midi/usb_midi_event_packet.rs | 127 ++++++++++++--------- 7 files changed, 122 insertions(+), 56 deletions(-) create mode 100644 examples/example-esp32s3/CHANGELOG.md diff --git a/examples/example-esp32s3/CHANGELOG.md b/examples/example-esp32s3/CHANGELOG.md new file mode 100644 index 0000000..a64b5d3 --- /dev/null +++ b/examples/example-esp32s3/CHANGELOG.md @@ -0,0 +1,37 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +### Added + +- `UsbMidiEventPacket::cable_number` function. +- `UsbMidiEventPacket::message` function. +- `UsbMidiEventPacket::as_message_bytes` function. +- `UsbMidiEventPacket::as_raw_bytes` function. +- `UsbMidiEventPacket::to_raw_bytes` function. + +### Changed + +- `UsbMidiEventPacket::message` field is now private, use function instead. +- Renamed `UsbMidiEventPacket::from_midi` function to `UsbMidiEventPacket::from_message`. + +### Removed + +- `UsbMidiEventPacket::cable_number` field, use function instead. + +## [0.3.0] - 2024-05-27 + +### Changed + +- Updated `usb-device` dependency to 0.3. +- Updated `num_enum` dependency to 0.7.2. +- Extended endpoint descriptors to 9 bytes as stated in specification. + +### Removed + +- Removed unused `embedded-hal` and `nb` dependencies. diff --git a/examples/example-esp32s3/src/main.rs b/examples/example-esp32s3/src/main.rs index 1ef6dad..4bb7d9e 100644 --- a/examples/example-esp32s3/src/main.rs +++ b/examples/example-esp32s3/src/main.rs @@ -44,7 +44,12 @@ fn main() -> ! { let buffer_reader = MidiPacketBufferReader::new(&buffer, size); for packet in buffer_reader.into_iter() { if let Ok(packet) = packet { - println!("{:?}", packet); + println!( + "Cable: {:?}, Message: {:?}, Bytes: {:?}", + packet.cable_number(), + packet.message(), + packet.as_message_bytes(), + ); } } } diff --git a/src/data/byte/u7.rs b/src/data/byte/u7.rs index 184cc5c..213f9e9 100644 --- a/src/data/byte/u7.rs +++ b/src/data/byte/u7.rs @@ -4,7 +4,7 @@ use crate::data::byte::from_traits::{FromClamped, FromOverFlow}; use core::convert::TryFrom; /// A primitive value that can be from 0-0x7F -#[derive(Debug, Eq, PartialEq)] +#[derive(Debug, Clone, Eq, PartialEq)] pub struct U7(pub(crate) u8); /// Error representing that this value is not a valid u7 diff --git a/src/data/midi/message/control_function.rs b/src/data/midi/message/control_function.rs index c4cb433..58028f4 100644 --- a/src/data/midi/message/control_function.rs +++ b/src/data/midi/message/control_function.rs @@ -3,7 +3,7 @@ use crate::data::byte::u7::U7; /// Custom type for a control function. -#[derive(Debug, Eq, PartialEq)] +#[derive(Debug, Clone, Eq, PartialEq)] pub struct ControlFunction(pub U7); /// Control Functions as defined in the MIDI 1.0 Specification. diff --git a/src/data/midi/message/mod.rs b/src/data/midi/message/mod.rs index 18da7bf..c2ae5d5 100644 --- a/src/data/midi/message/mod.rs +++ b/src/data/midi/message/mod.rs @@ -19,7 +19,7 @@ type Velocity = U7; /// Note: not current exhaustive and SysEx messages end up /// being a confusing case. So are currently note implemented /// they are sort-of unbounded -#[derive(Debug, Eq, PartialEq)] +#[derive(Debug, Eq, PartialEq, Clone)] pub enum Message { /// Note On message. NoteOff(Channel, Note, Velocity), diff --git a/src/data/usb_midi/cable_number.rs b/src/data/usb_midi/cable_number.rs index aaa17e0..e76c262 100644 --- a/src/data/usb_midi/cable_number.rs +++ b/src/data/usb_midi/cable_number.rs @@ -29,6 +29,7 @@ pub enum CableNumber { } /// Error indicating an invalid cable number. +#[derive(Debug)] pub struct InvalidCableNumber(u8); impl TryFrom for CableNumber { diff --git a/src/data/usb_midi/usb_midi_event_packet.rs b/src/data/usb_midi/usb_midi_event_packet.rs index 10ed096..b930bb9 100644 --- a/src/data/usb_midi/usb_midi_event_packet.rs +++ b/src/data/usb_midi/usb_midi_event_packet.rs @@ -5,7 +5,7 @@ use crate::data::midi::message::raw::{Payload, Raw}; use crate::data::midi::message::Message; use crate::data::usb_midi::cable_number::CableNumber; use crate::data::usb_midi::code_index_number::CodeIndexNumber; -use core::convert::TryFrom; +use core::convert::{TryFrom, TryInto}; /// A packet that communicates with the host. /// @@ -13,16 +13,16 @@ use core::convert::TryFrom; /// message over the supplied cable number #[derive(Debug, Eq, PartialEq)] pub struct UsbMidiEventPacket { - /// Cable number of the packet. - pub cable_number: CableNumber, + /// Raw packet data. + raw: [u8; 4], /// Message payload. - pub message: Message, + message: Message, } impl From for [u8; 4] { fn from(value: UsbMidiEventPacket) -> [u8; 4] { + let cable_number = U4::from(value.cable_number()); let message = value.message; - let cable_number = U4::from(value.cable_number); let index_number = { let code_index = CodeIndexNumber::find_from_message(&message); U4::from(code_index) @@ -43,6 +43,8 @@ impl From for [u8; 4] { /// Error variants for parsing the packet. #[derive(Debug)] pub enum MidiPacketParsingError { + /// Invalid packet. + InvalidPacket, /// Invalid note. InvalidNote(u8), /// Invalid cable number. @@ -57,14 +59,8 @@ impl TryFrom<&[u8]> for UsbMidiEventPacket { type Error = MidiPacketParsingError; fn try_from(value: &[u8]) -> Result { - let raw_cable_number = match value.first() { - Some(byte) => *byte >> 4, - None => return Err(MidiPacketParsingError::MissingDataPacket), - }; - - let cable_number = match CableNumber::try_from(raw_cable_number) { - Ok(val) => val, - _ => return Err(MidiPacketParsingError::InvalidCableNumber(raw_cable_number)), + let Ok(data) = value.try_into() else { + return Err(MidiPacketParsingError::InvalidPacket); }; let message_body = match value.get(1..) { @@ -74,20 +70,68 @@ impl TryFrom<&[u8]> for UsbMidiEventPacket { let message = Message::try_from(message_body)?; - Ok(UsbMidiEventPacket { - cable_number, - message, - }) + Ok(UsbMidiEventPacket { raw: data, message }) } } impl UsbMidiEventPacket { - /// Creates a packet from a MIDI message and returns it. - pub const fn from_midi(cable: CableNumber, midi: Message) -> UsbMidiEventPacket { - UsbMidiEventPacket { - cable_number: cable, - message: midi, - } + /// Returns the cable number. + pub fn cable_number(&self) -> CableNumber { + let raw_cable_number = self.raw.first().unwrap() >> 4; + + CableNumber::try_from(raw_cable_number).unwrap() + } + + /// Returns the message. + pub fn message(&self) -> Message { + self.message.clone() + } + + /// Returns a slice to the message bytes. The length is dependent on the message type. + pub fn as_message_bytes(&self) -> &[u8] { + let r = Raw::from(self.message.clone()); + let length = match r.payload { + Payload::Empty => 1, + Payload::SingleByte(_) => 2, + Payload::DoubleByte(_, _) => 3, + }; + + &self.raw[1..1 + length] + } + + /// Returns a reference to the raw bytes. + pub fn as_raw_bytes(&self) -> &[u8] { + &self.raw + } + + /// Returns the raw bytes as owned array. + pub fn to_raw_bytes(&self) -> [u8; 4] { + self.raw.clone() + } + + /// Creates a packet from a message and returns it. + pub fn from_message(cable: CableNumber, message: Message) -> Self { + let mut raw = [0; 4]; + let cin = u8::from(U4::from(CodeIndexNumber::find_from_message(&message))); + raw[0] = (cable as u8) << 4 | cin; + let r = Raw::from(message.clone()); + raw[1] = r.status; + match r.payload { + Payload::Empty => { + raw[2] = 0; + raw[3] = 0; + } + Payload::SingleByte(byte) => { + raw[2] = byte.0; + raw[3] = 0; + } + Payload::DoubleByte(byte1, byte2) => { + raw[2] = byte1.0; + raw[3] = byte2.0; + } + }; + + UsbMidiEventPacket { raw, message } } } @@ -107,7 +151,7 @@ mod tests { $( #[test] fn $id() { - let (usb_midi_data_packet,expected) = $value; + let (usb_midi_data_packet, expected) = $value; let message = UsbMidiEventPacket::try_from(&usb_midi_data_packet[..]).unwrap(); assert_eq!(expected, message); } @@ -116,33 +160,12 @@ mod tests { } decode_message_test! { - note_on: ([9, 144, 36, 127], UsbMidiEventPacket { - cable_number: Cable0, - message: Message::NoteOn(Channel1, Note::C2, U7(127)) - }), - note_off: ([8, 128, 36, 0], UsbMidiEventPacket { - cable_number: Cable0, - message: Message::NoteOff(Channel1, Note::C2, U7(0)) - }), - polyphonic_aftertouch: ([10, 160, 36, 64], UsbMidiEventPacket { - cable_number: Cable0, - message: Message::PolyphonicAftertouch(Channel1, Note::C2, U7(64)) - }), - program_change: ([28, 192, 127, 0], UsbMidiEventPacket { - cable_number: Cable1, - message: Message::ProgramChange(Channel1, U7(127)) - }), - channel_aftertouch: ([13, 208, 127, 0], UsbMidiEventPacket { - cable_number: Cable0, - message: Message::ChannelAftertouch(Channel1, U7(127)) - }), - pitch_wheel: ([14, 224, 64, 32], UsbMidiEventPacket { - cable_number: Cable0, - message: Message::PitchWheelChange(Channel1, U7(64), U7(32)) - }), - control_change: ([11, 177, 1, 32], UsbMidiEventPacket { - cable_number: Cable0, - message: Message::ControlChange(Channel2, ControlFunction::MOD_WHEEL_1, U7(32)) - }), + note_on: ([9, 144, 36, 127], UsbMidiEventPacket::from_message(Cable0, Message::NoteOn(Channel1, Note::C2, U7(127)))), + note_off: ([8, 128, 36, 0], UsbMidiEventPacket::from_message(Cable0, Message::NoteOff(Channel1, Note::C2, U7(0)))), + polyphonic_aftertouch: ([10, 160, 36, 64], UsbMidiEventPacket::from_message(Cable0, Message::PolyphonicAftertouch(Channel1, Note::C2, U7(64)))), + program_change: ([28, 192, 127, 0], UsbMidiEventPacket::from_message(Cable1, Message::ProgramChange(Channel1, U7(127)))), + channel_aftertouch: ([13, 208, 127, 0], UsbMidiEventPacket::from_message(Cable0, Message::ChannelAftertouch(Channel1, U7(127)))), + pitch_wheel: ([14, 224, 64, 32], UsbMidiEventPacket::from_message(Cable0, Message::PitchWheelChange(Channel1, U7(64), U7(32)))), + control_change: ([11, 177, 1, 32], UsbMidiEventPacket::from_message(Cable0, Message::ControlChange(Channel2, ControlFunction::MOD_WHEEL_1, U7(32)))), } } From a10fac10de3d0d23534eac20359ae915c67ce97b Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Tue, 17 Dec 2024 22:07:15 +0100 Subject: [PATCH 02/67] ESP32-S3 example: convert packet to midi-types message. --- examples/example-esp32s3/Cargo.toml | 1 + examples/example-esp32s3/src/main.rs | 10 ++++------ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/examples/example-esp32s3/Cargo.toml b/examples/example-esp32s3/Cargo.toml index 0531c4c..0c9563b 100644 --- a/examples/example-esp32s3/Cargo.toml +++ b/examples/example-esp32s3/Cargo.toml @@ -13,3 +13,4 @@ esp-backtrace = { version = "0.14.2", features = [ esp-println = { version = "0.12.0", features = ["esp32s3", "log"] } usb-device = { version = "0.3.2", features = ["control-buffer-256"] } usbd-midi = { path = "../../" } +midi-convert = "0.2.0" diff --git a/examples/example-esp32s3/src/main.rs b/examples/example-esp32s3/src/main.rs index 4bb7d9e..6f904cf 100644 --- a/examples/example-esp32s3/src/main.rs +++ b/examples/example-esp32s3/src/main.rs @@ -7,6 +7,8 @@ use core::ptr::addr_of_mut; use esp_backtrace as _; use esp_println::println; +use midi_convert::midi_types::MidiMessage; +use midi_convert::parse::MidiTryParseSlice; use usb_device::prelude::*; use usbd_midi::{ data::usb_midi::midi_packet_reader::MidiPacketBufferReader, midi_device::MidiClass, @@ -44,12 +46,8 @@ fn main() -> ! { let buffer_reader = MidiPacketBufferReader::new(&buffer, size); for packet in buffer_reader.into_iter() { if let Ok(packet) = packet { - println!( - "Cable: {:?}, Message: {:?}, Bytes: {:?}", - packet.cable_number(), - packet.message(), - packet.as_message_bytes(), - ); + let message = MidiMessage::try_parse_slice(packet.as_message_bytes()); + println!("Cable: {:?}, Message: {:?}", packet.cable_number(), message); } } } From 9cf84e02494a21d47e3e0a307f70e8ee11e38423 Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Wed, 18 Dec 2024 09:38:03 +0100 Subject: [PATCH 03/67] Generate message on the fly inside UsbMidiEventPacket --- examples/example-esp32s3/CHANGELOG.md | 2 +- src/data/usb_midi/usb_midi_event_packet.rs | 26 ++++++++-------------- 2 files changed, 10 insertions(+), 18 deletions(-) diff --git a/examples/example-esp32s3/CHANGELOG.md b/examples/example-esp32s3/CHANGELOG.md index a64b5d3..0804deb 100644 --- a/examples/example-esp32s3/CHANGELOG.md +++ b/examples/example-esp32s3/CHANGELOG.md @@ -17,12 +17,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Changed -- `UsbMidiEventPacket::message` field is now private, use function instead. - Renamed `UsbMidiEventPacket::from_midi` function to `UsbMidiEventPacket::from_message`. ### Removed - `UsbMidiEventPacket::cable_number` field, use function instead. +- `UsbMidiEventPacket::message` field, use function instead. ## [0.3.0] - 2024-05-27 diff --git a/src/data/usb_midi/usb_midi_event_packet.rs b/src/data/usb_midi/usb_midi_event_packet.rs index b930bb9..eddb7c1 100644 --- a/src/data/usb_midi/usb_midi_event_packet.rs +++ b/src/data/usb_midi/usb_midi_event_packet.rs @@ -1,28 +1,27 @@ //! Representation of a USB MIDI event packet. +use core::convert::{TryFrom, TryInto}; + use crate::data::byte::u4::U4; use crate::data::midi::message::raw::{Payload, Raw}; use crate::data::midi::message::Message; use crate::data::usb_midi::cable_number::CableNumber; use crate::data::usb_midi::code_index_number::CodeIndexNumber; -use core::convert::{TryFrom, TryInto}; /// A packet that communicates with the host. /// /// Currently supported is sending the specified normal midi /// message over the supplied cable number -#[derive(Debug, Eq, PartialEq)] +#[derive(Debug, Clone, Eq, PartialEq)] pub struct UsbMidiEventPacket { /// Raw packet data. raw: [u8; 4], - /// Message payload. - message: Message, } impl From for [u8; 4] { fn from(value: UsbMidiEventPacket) -> [u8; 4] { let cable_number = U4::from(value.cable_number()); - let message = value.message; + let message = value.message(); let index_number = { let code_index = CodeIndexNumber::find_from_message(&message); U4::from(code_index) @@ -59,18 +58,11 @@ impl TryFrom<&[u8]> for UsbMidiEventPacket { type Error = MidiPacketParsingError; fn try_from(value: &[u8]) -> Result { - let Ok(data) = value.try_into() else { + let Ok(raw) = value.try_into() else { return Err(MidiPacketParsingError::InvalidPacket); }; - let message_body = match value.get(1..) { - Some(bytes) => bytes, - None => return Err(MidiPacketParsingError::MissingDataPacket), - }; - - let message = Message::try_from(message_body)?; - - Ok(UsbMidiEventPacket { raw: data, message }) + Ok(UsbMidiEventPacket { raw }) } } @@ -84,12 +76,12 @@ impl UsbMidiEventPacket { /// Returns the message. pub fn message(&self) -> Message { - self.message.clone() + Message::try_from(&self.raw[1..]).unwrap() } /// Returns a slice to the message bytes. The length is dependent on the message type. pub fn as_message_bytes(&self) -> &[u8] { - let r = Raw::from(self.message.clone()); + let r = Raw::from(self.message()); let length = match r.payload { Payload::Empty => 1, Payload::SingleByte(_) => 2, @@ -131,7 +123,7 @@ impl UsbMidiEventPacket { } }; - UsbMidiEventPacket { raw, message } + UsbMidiEventPacket { raw } } } From 562e809349b6012c4af02368cefd73c27664a27b Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Wed, 18 Dec 2024 10:01:33 +0100 Subject: [PATCH 04/67] Added UsbMidiEventPacket::from_message_bytes function --- examples/example-esp32s3/CHANGELOG.md | 1 + src/data/usb_midi/usb_midi_event_packet.rs | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/examples/example-esp32s3/CHANGELOG.md b/examples/example-esp32s3/CHANGELOG.md index 0804deb..97a052a 100644 --- a/examples/example-esp32s3/CHANGELOG.md +++ b/examples/example-esp32s3/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - `UsbMidiEventPacket::as_message_bytes` function. - `UsbMidiEventPacket::as_raw_bytes` function. - `UsbMidiEventPacket::to_raw_bytes` function. +- `UsbMidiEventPacket::from_message_bytes` function. ### Changed diff --git a/src/data/usb_midi/usb_midi_event_packet.rs b/src/data/usb_midi/usb_midi_event_packet.rs index eddb7c1..e9e9340 100644 --- a/src/data/usb_midi/usb_midi_event_packet.rs +++ b/src/data/usb_midi/usb_midi_event_packet.rs @@ -103,11 +103,13 @@ impl UsbMidiEventPacket { /// Creates a packet from a message and returns it. pub fn from_message(cable: CableNumber, message: Message) -> Self { - let mut raw = [0; 4]; let cin = u8::from(U4::from(CodeIndexNumber::find_from_message(&message))); + + let mut raw = [0; 4]; raw[0] = (cable as u8) << 4 | cin; let r = Raw::from(message.clone()); raw[1] = r.status; + match r.payload { Payload::Empty => { raw[2] = 0; @@ -123,7 +125,17 @@ impl UsbMidiEventPacket { } }; - UsbMidiEventPacket { raw } + Self { raw } + } + + /// Creates a packet from a slice of message bytes. + pub fn from_message_bytes( + cable: CableNumber, + bytes: &[u8], + ) -> Result { + let message = Message::try_from(bytes)?; + + Ok(Self::from_message(cable, message)) } } From 5ec935e9b45c0da0920c9321bde2cfe0f96194ac Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Wed, 18 Dec 2024 10:49:00 +0100 Subject: [PATCH 05/67] Renamed MidiClass::send_message to MidiClass::send_packet --- src/midi_device.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/midi_device.rs b/src/midi_device.rs index ea65c1b..e422287 100644 --- a/src/midi_device.rs +++ b/src/midi_device.rs @@ -64,7 +64,7 @@ impl MidiClass<'_, B> { } /// Sends a `UsbMidiEventPacket` and returns either the transferred size or an error. - pub fn send_message(&mut self, usb_midi: UsbMidiEventPacket) -> Result { + pub fn send_packet(&mut self, usb_midi: UsbMidiEventPacket) -> Result { let bytes: [u8; MIDI_PACKET_SIZE] = usb_midi.into(); self.standard_bulkin.write(&bytes) } From b93a89b3c2516db5c956f3d0adfa8a5ca88c2113 Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Wed, 18 Dec 2024 10:50:12 +0100 Subject: [PATCH 06/67] Changelog update, fixed wrong file location --- CHANGELOG.md | 21 +++++++++++++++ examples/example-esp32s3/CHANGELOG.md | 38 --------------------------- 2 files changed, 21 insertions(+), 38 deletions(-) delete mode 100644 examples/example-esp32s3/CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md index b52a777..97f02bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,27 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [Unreleased] + +### Added + +- `UsbMidiEventPacket::cable_number` function. +- `UsbMidiEventPacket::message` function. +- `UsbMidiEventPacket::as_message_bytes` function. +- `UsbMidiEventPacket::as_raw_bytes` function. +- `UsbMidiEventPacket::to_raw_bytes` function. +- `UsbMidiEventPacket::from_message_bytes` function. + +### Changed + +- Renamed `UsbMidiEventPacket::from_midi` function to `UsbMidiEventPacket::from_message`. +- Renamed `MidiClass::send_message` function to `MidiClass::send_packet`. + +### Removed + +- `UsbMidiEventPacket::cable_number` field, use function instead. +- `UsbMidiEventPacket::message` field, use function instead. + ## [0.3.0] - 2024-05-27 ### Changed diff --git a/examples/example-esp32s3/CHANGELOG.md b/examples/example-esp32s3/CHANGELOG.md deleted file mode 100644 index 97a052a..0000000 --- a/examples/example-esp32s3/CHANGELOG.md +++ /dev/null @@ -1,38 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) -and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). - -## [Unreleased] - -### Added - -- `UsbMidiEventPacket::cable_number` function. -- `UsbMidiEventPacket::message` function. -- `UsbMidiEventPacket::as_message_bytes` function. -- `UsbMidiEventPacket::as_raw_bytes` function. -- `UsbMidiEventPacket::to_raw_bytes` function. -- `UsbMidiEventPacket::from_message_bytes` function. - -### Changed - -- Renamed `UsbMidiEventPacket::from_midi` function to `UsbMidiEventPacket::from_message`. - -### Removed - -- `UsbMidiEventPacket::cable_number` field, use function instead. -- `UsbMidiEventPacket::message` field, use function instead. - -## [0.3.0] - 2024-05-27 - -### Changed - -- Updated `usb-device` dependency to 0.3. -- Updated `num_enum` dependency to 0.7.2. -- Extended endpoint descriptors to 9 bytes as stated in specification. - -### Removed - -- Removed unused `embedded-hal` and `nb` dependencies. From 6e6fcfc7ffc489ba8a3696d60bec5a6624d71533 Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Wed, 18 Dec 2024 10:51:12 +0100 Subject: [PATCH 07/67] ESP32-S3 example: send midi-types message on button press --- examples/example-esp32s3/src/main.rs | 49 +++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/examples/example-esp32s3/src/main.rs b/examples/example-esp32s3/src/main.rs index 6f904cf..69cec03 100644 --- a/examples/example-esp32s3/src/main.rs +++ b/examples/example-esp32s3/src/main.rs @@ -6,24 +6,29 @@ use core::ptr::addr_of_mut; use esp_backtrace as _; +use esp_hal::{clock, gpio, otg_fs, xtensa_lx_rt, Config}; use esp_println::println; -use midi_convert::midi_types::MidiMessage; -use midi_convert::parse::MidiTryParseSlice; +use midi_convert::midi_types::{Channel, MidiMessage, Note, Value7}; +use midi_convert::{parse::MidiTryParseSlice, render_slice::MidiRenderSlice}; use usb_device::prelude::*; use usbd_midi::{ - data::usb_midi::midi_packet_reader::MidiPacketBufferReader, midi_device::MidiClass, + data::usb_midi::{ + cable_number::CableNumber, midi_packet_reader::MidiPacketBufferReader, + usb_midi_event_packet::UsbMidiEventPacket, + }, + midi_device::MidiClass, }; static mut EP_MEMORY: [u32; 1024] = [0; 1024]; -#[esp_hal::xtensa_lx_rt::entry] +#[xtensa_lx_rt::entry] fn main() -> ! { - let mut config = esp_hal::Config::default(); - config.cpu_clock = esp_hal::clock::CpuClock::Clock240MHz; + let mut config = Config::default(); + config.cpu_clock = clock::CpuClock::Clock240MHz; let peripherals = esp_hal::init(config); - let usb_bus_allocator = esp_hal::otg_fs::UsbBus::new( - esp_hal::otg_fs::Usb::new(peripherals.USB0, peripherals.GPIO20, peripherals.GPIO19), + let usb_bus_allocator = otg_fs::UsbBus::new( + otg_fs::Usb::new(peripherals.USB0, peripherals.GPIO20, peripherals.GPIO19), unsafe { &mut *addr_of_mut!(EP_MEMORY) }, ); @@ -39,9 +44,14 @@ fn main() -> ! { .unwrap() .build(); + let button = gpio::Input::new(peripherals.GPIO0, gpio::Pull::Up); + let mut last_button_level = button.level(); + loop { if usb_dev.poll(&mut [&mut midi_class]) { + // Receive messages. let mut buffer = [0; 64]; + if let Ok(size) = midi_class.read(&mut buffer) { let buffer_reader = MidiPacketBufferReader::new(&buffer, size); for packet in buffer_reader.into_iter() { @@ -52,5 +62,28 @@ fn main() -> ! { } } } + + // Send messages on button press. + let button_level = button.level(); + + if button_level != last_button_level { + last_button_level = button_level; + + let mut bytes = [0; 3]; + + let message = if button_level == gpio::Level::Low { + MidiMessage::NoteOn(Channel::C1, Note::C3, Value7::from(100)) + } else { + MidiMessage::NoteOff(Channel::C1, Note::C3, Value7::from(0)) + }; + + message.render_slice(&mut bytes); + + let packet = + UsbMidiEventPacket::from_message_bytes(CableNumber::Cable0, &bytes).unwrap(); + let result = midi_class.send_packet(packet); + + println!("Send result {:?}", result); + } } } From 30d7b48fe950093c8667647a459e762abe005a26 Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Wed, 18 Dec 2024 12:38:47 +0100 Subject: [PATCH 08/67] Added re-exports for some common items in crate root --- CHANGELOG.md | 1 + examples/example-esp32s3/src/main.rs | 8 +------- src/lib.rs | 5 +++++ 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 97f02bd..f1c056f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - `UsbMidiEventPacket::as_raw_bytes` function. - `UsbMidiEventPacket::to_raw_bytes` function. - `UsbMidiEventPacket::from_message_bytes` function. +- Re-exports of common items in crate root. ### Changed diff --git a/examples/example-esp32s3/src/main.rs b/examples/example-esp32s3/src/main.rs index 69cec03..020ae3c 100644 --- a/examples/example-esp32s3/src/main.rs +++ b/examples/example-esp32s3/src/main.rs @@ -11,13 +11,7 @@ use esp_println::println; use midi_convert::midi_types::{Channel, MidiMessage, Note, Value7}; use midi_convert::{parse::MidiTryParseSlice, render_slice::MidiRenderSlice}; use usb_device::prelude::*; -use usbd_midi::{ - data::usb_midi::{ - cable_number::CableNumber, midi_packet_reader::MidiPacketBufferReader, - usb_midi_event_packet::UsbMidiEventPacket, - }, - midi_device::MidiClass, -}; +use usbd_midi::{CableNumber, MidiClass, MidiPacketBufferReader, UsbMidiEventPacket}; static mut EP_MEMORY: [u32; 1024] = [0; 1024]; diff --git a/src/lib.rs b/src/lib.rs index 1017e0c..bf4c6b8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,3 +4,8 @@ pub mod data; pub mod midi_device; + +pub use crate::data::usb_midi::cable_number::CableNumber; +pub use crate::data::usb_midi::midi_packet_reader::MidiPacketBufferReader; +pub use crate::data::usb_midi::usb_midi_event_packet::UsbMidiEventPacket; +pub use crate::midi_device::MidiClass; From 270f24429c2f74e431b55930e3ab05ca78403f26 Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Thu, 19 Dec 2024 10:25:16 +0100 Subject: [PATCH 09/67] Moved descriptor constants into class module --- CHANGELOG.md | 1 + src/data/mod.rs | 1 - src/data/usb/constants.rs | 19 ------------------- src/data/usb/mod.rs | 3 --- src/midi_device.rs | 15 ++++++++++++++- 5 files changed, 15 insertions(+), 24 deletions(-) delete mode 100644 src/data/usb/constants.rs delete mode 100644 src/data/usb/mod.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index f1c056f..56c81bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Renamed `UsbMidiEventPacket::from_midi` function to `UsbMidiEventPacket::from_message`. - Renamed `MidiClass::send_message` function to `MidiClass::send_packet`. +- Moved usb descriptor constants into class module and made them private. ### Removed diff --git a/src/data/mod.rs b/src/data/mod.rs index 15d2f71..910bcc1 100644 --- a/src/data/mod.rs +++ b/src/data/mod.rs @@ -2,5 +2,4 @@ pub mod byte; pub mod midi; -pub mod usb; pub mod usb_midi; diff --git a/src/data/usb/constants.rs b/src/data/usb/constants.rs deleted file mode 100644 index a4901c0..0000000 --- a/src/data/usb/constants.rs +++ /dev/null @@ -1,19 +0,0 @@ -//! Constants for use in USB descriptors. - -#![allow(missing_docs)] - -// TODO: this should be better organized in future. - -pub const USB_CLASS_NONE: u8 = 0x00; -pub const USB_AUDIO_CLASS: u8 = 0x01; -pub const USB_AUDIOCONTROL_SUBCLASS: u8 = 0x01; -pub const USB_MIDISTREAMING_SUBCLASS: u8 = 0x03; -pub const MIDI_IN_JACK_SUBTYPE: u8 = 0x02; -pub const MIDI_OUT_JACK_SUBTYPE: u8 = 0x03; -pub const EMBEDDED: u8 = 0x01; -pub const EXTERNAL: u8 = 0x02; -pub const CS_INTERFACE: u8 = 0x24; -pub const CS_ENDPOINT: u8 = 0x25; -pub const HEADER_SUBTYPE: u8 = 0x01; -pub const MS_HEADER_SUBTYPE: u8 = 0x01; -pub const MS_GENERAL: u8 = 0x01; diff --git a/src/data/usb/mod.rs b/src/data/usb/mod.rs deleted file mode 100644 index 28ecd9f..0000000 --- a/src/data/usb/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -//! General items used for USB communication. - -pub mod constants; diff --git a/src/midi_device.rs b/src/midi_device.rs index e422287..a1c47da 100644 --- a/src/midi_device.rs +++ b/src/midi_device.rs @@ -1,10 +1,23 @@ //! Contains the class implementation. -use crate::data::usb::constants::*; use crate::data::usb_midi::usb_midi_event_packet::{MidiPacketParsingError, UsbMidiEventPacket}; use usb_device::class_prelude::*; use usb_device::Result; +// Constants for use in descriptors. +const USB_AUDIO_CLASS: u8 = 0x01; +const USB_AUDIOCONTROL_SUBCLASS: u8 = 0x01; +const USB_MIDISTREAMING_SUBCLASS: u8 = 0x03; +const MIDI_IN_JACK_SUBTYPE: u8 = 0x02; +const MIDI_OUT_JACK_SUBTYPE: u8 = 0x03; +const EMBEDDED: u8 = 0x01; +const EXTERNAL: u8 = 0x02; +const CS_INTERFACE: u8 = 0x24; +const CS_ENDPOINT: u8 = 0x25; +const HEADER_SUBTYPE: u8 = 0x01; +const MS_HEADER_SUBTYPE: u8 = 0x01; +const MS_GENERAL: u8 = 0x01; + const MIDI_IN_SIZE: u8 = 0x06; const MIDI_OUT_SIZE: u8 = 0x09; From bd780633f0564869565c785f3ffdcbe4cf72ce70 Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Thu, 19 Dec 2024 10:28:44 +0100 Subject: [PATCH 10/67] Renamed midi_device module to class --- CHANGELOG.md | 1 + src/{midi_device.rs => class.rs} | 0 src/data/usb_midi/midi_packet_reader.rs | 2 +- src/lib.rs | 4 ++-- 4 files changed, 4 insertions(+), 3 deletions(-) rename src/{midi_device.rs => class.rs} (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 56c81bb..bf482e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Renamed `UsbMidiEventPacket::from_midi` function to `UsbMidiEventPacket::from_message`. - Renamed `MidiClass::send_message` function to `MidiClass::send_packet`. +- Renamed `midi_device` module to `class`. - Moved usb descriptor constants into class module and made them private. ### Removed diff --git a/src/midi_device.rs b/src/class.rs similarity index 100% rename from src/midi_device.rs rename to src/class.rs diff --git a/src/data/usb_midi/midi_packet_reader.rs b/src/data/usb_midi/midi_packet_reader.rs index 012afe5..5f4c40e 100644 --- a/src/data/usb_midi/midi_packet_reader.rs +++ b/src/data/usb_midi/midi_packet_reader.rs @@ -1,7 +1,7 @@ //! Reader for received packets. +use crate::class::{MAX_PACKET_SIZE, MIDI_PACKET_SIZE}; use crate::data::usb_midi::usb_midi_event_packet::{MidiPacketParsingError, UsbMidiEventPacket}; -use crate::midi_device::{MAX_PACKET_SIZE, MIDI_PACKET_SIZE}; use core::convert::TryFrom; /// Packet reader with internal buffer for received message. diff --git a/src/lib.rs b/src/lib.rs index bf4c6b8..500d169 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,10 +2,10 @@ #![no_std] +pub mod class; pub mod data; -pub mod midi_device; +pub use crate::class::MidiClass; pub use crate::data::usb_midi::cable_number::CableNumber; pub use crate::data::usb_midi::midi_packet_reader::MidiPacketBufferReader; pub use crate::data::usb_midi::usb_midi_event_packet::UsbMidiEventPacket; -pub use crate::midi_device::MidiClass; From 0e12422868a1a459b330c51b4a60d2a585918e7f Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Thu, 19 Dec 2024 10:38:44 +0100 Subject: [PATCH 11/67] Renamed usb_midi module to packet --- CHANGELOG.md | 1 + src/class.rs | 2 +- src/data/midi/message/mod.rs | 2 +- src/data/mod.rs | 2 +- src/data/{usb_midi => packet}/cable_number.rs | 0 src/data/{usb_midi => packet}/code_index_number.rs | 0 src/data/{usb_midi => packet}/midi_packet_reader.rs | 2 +- src/data/{usb_midi => packet}/mod.rs | 0 src/data/{usb_midi => packet}/usb_midi_event_packet.rs | 8 ++++---- src/lib.rs | 6 +++--- 10 files changed, 12 insertions(+), 11 deletions(-) rename src/data/{usb_midi => packet}/cable_number.rs (100%) rename src/data/{usb_midi => packet}/code_index_number.rs (100%) rename src/data/{usb_midi => packet}/midi_packet_reader.rs (92%) rename src/data/{usb_midi => packet}/mod.rs (100%) rename src/data/{usb_midi => packet}/usb_midi_event_packet.rs (95%) diff --git a/CHANGELOG.md b/CHANGELOG.md index bf482e2..e143608 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Renamed `UsbMidiEventPacket::from_midi` function to `UsbMidiEventPacket::from_message`. - Renamed `MidiClass::send_message` function to `MidiClass::send_packet`. - Renamed `midi_device` module to `class`. +- Renamed `usb_midi` module to `packet`. - Moved usb descriptor constants into class module and made them private. ### Removed diff --git a/src/class.rs b/src/class.rs index a1c47da..a7b6c1d 100644 --- a/src/class.rs +++ b/src/class.rs @@ -1,6 +1,6 @@ //! Contains the class implementation. -use crate::data::usb_midi::usb_midi_event_packet::{MidiPacketParsingError, UsbMidiEventPacket}; +use crate::data::packet::usb_midi_event_packet::{MidiPacketParsingError, UsbMidiEventPacket}; use usb_device::class_prelude::*; use usb_device::Result; diff --git a/src/data/midi/message/mod.rs b/src/data/midi/message/mod.rs index c2ae5d5..60839c3 100644 --- a/src/data/midi/message/mod.rs +++ b/src/data/midi/message/mod.rs @@ -9,7 +9,7 @@ use crate::data::midi::channel::Channel; use crate::data::midi::message::control_function::ControlFunction; use crate::data::midi::message::raw::{Payload, Raw}; use crate::data::midi::notes::Note; -use crate::data::usb_midi::usb_midi_event_packet::MidiPacketParsingError; +use crate::data::packet::usb_midi_event_packet::MidiPacketParsingError; use core::convert::TryFrom; type Velocity = U7; diff --git a/src/data/mod.rs b/src/data/mod.rs index 910bcc1..736816d 100644 --- a/src/data/mod.rs +++ b/src/data/mod.rs @@ -2,4 +2,4 @@ pub mod byte; pub mod midi; -pub mod usb_midi; +pub mod packet; diff --git a/src/data/usb_midi/cable_number.rs b/src/data/packet/cable_number.rs similarity index 100% rename from src/data/usb_midi/cable_number.rs rename to src/data/packet/cable_number.rs diff --git a/src/data/usb_midi/code_index_number.rs b/src/data/packet/code_index_number.rs similarity index 100% rename from src/data/usb_midi/code_index_number.rs rename to src/data/packet/code_index_number.rs diff --git a/src/data/usb_midi/midi_packet_reader.rs b/src/data/packet/midi_packet_reader.rs similarity index 92% rename from src/data/usb_midi/midi_packet_reader.rs rename to src/data/packet/midi_packet_reader.rs index 5f4c40e..733644d 100644 --- a/src/data/usb_midi/midi_packet_reader.rs +++ b/src/data/packet/midi_packet_reader.rs @@ -1,7 +1,7 @@ //! Reader for received packets. use crate::class::{MAX_PACKET_SIZE, MIDI_PACKET_SIZE}; -use crate::data::usb_midi::usb_midi_event_packet::{MidiPacketParsingError, UsbMidiEventPacket}; +use crate::data::packet::usb_midi_event_packet::{MidiPacketParsingError, UsbMidiEventPacket}; use core::convert::TryFrom; /// Packet reader with internal buffer for received message. diff --git a/src/data/usb_midi/mod.rs b/src/data/packet/mod.rs similarity index 100% rename from src/data/usb_midi/mod.rs rename to src/data/packet/mod.rs diff --git a/src/data/usb_midi/usb_midi_event_packet.rs b/src/data/packet/usb_midi_event_packet.rs similarity index 95% rename from src/data/usb_midi/usb_midi_event_packet.rs rename to src/data/packet/usb_midi_event_packet.rs index e9e9340..1cb8823 100644 --- a/src/data/usb_midi/usb_midi_event_packet.rs +++ b/src/data/packet/usb_midi_event_packet.rs @@ -5,8 +5,8 @@ use core::convert::{TryFrom, TryInto}; use crate::data::byte::u4::U4; use crate::data::midi::message::raw::{Payload, Raw}; use crate::data::midi::message::Message; -use crate::data::usb_midi::cable_number::CableNumber; -use crate::data::usb_midi::code_index_number::CodeIndexNumber; +use crate::data::packet::cable_number::CableNumber; +use crate::data::packet::code_index_number::CodeIndexNumber; /// A packet that communicates with the host. /// @@ -146,8 +146,8 @@ mod tests { use crate::data::midi::message::control_function::ControlFunction; use crate::data::midi::message::Message; use crate::data::midi::notes::Note; - use crate::data::usb_midi::cable_number::CableNumber::{Cable0, Cable1}; - use crate::data::usb_midi::usb_midi_event_packet::UsbMidiEventPacket; + use crate::data::packet::cable_number::CableNumber::{Cable0, Cable1}; + use crate::data::packet::usb_midi_event_packet::UsbMidiEventPacket; use core::convert::TryFrom; macro_rules! decode_message_test { diff --git a/src/lib.rs b/src/lib.rs index 500d169..c331605 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,6 +6,6 @@ pub mod class; pub mod data; pub use crate::class::MidiClass; -pub use crate::data::usb_midi::cable_number::CableNumber; -pub use crate::data::usb_midi::midi_packet_reader::MidiPacketBufferReader; -pub use crate::data::usb_midi::usb_midi_event_packet::UsbMidiEventPacket; +pub use crate::data::packet::cable_number::CableNumber; +pub use crate::data::packet::midi_packet_reader::MidiPacketBufferReader; +pub use crate::data::packet::usb_midi_event_packet::UsbMidiEventPacket; From 2016ef0d5f988f936646abc0559a1596e759ddad Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Thu, 19 Dec 2024 10:45:28 +0100 Subject: [PATCH 12/67] Moved packet module into crate root --- CHANGELOG.md | 2 +- src/class.rs | 2 +- src/data/midi/message/mod.rs | 2 +- src/data/mod.rs | 1 - src/lib.rs | 7 ++++--- src/{data => }/packet/cable_number.rs | 0 src/{data => }/packet/code_index_number.rs | 0 src/{data => }/packet/midi_packet_reader.rs | 2 +- src/{data => }/packet/mod.rs | 0 src/{data => }/packet/usb_midi_event_packet.rs | 8 ++++---- 10 files changed, 12 insertions(+), 12 deletions(-) rename src/{data => }/packet/cable_number.rs (100%) rename src/{data => }/packet/code_index_number.rs (100%) rename src/{data => }/packet/midi_packet_reader.rs (92%) rename src/{data => }/packet/mod.rs (100%) rename src/{data => }/packet/usb_midi_event_packet.rs (95%) diff --git a/CHANGELOG.md b/CHANGELOG.md index e143608..c67b13c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,7 +22,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Renamed `UsbMidiEventPacket::from_midi` function to `UsbMidiEventPacket::from_message`. - Renamed `MidiClass::send_message` function to `MidiClass::send_packet`. - Renamed `midi_device` module to `class`. -- Renamed `usb_midi` module to `packet`. +- Renamed `usb_midi` module to `packet` and moved it into crate root. - Moved usb descriptor constants into class module and made them private. ### Removed diff --git a/src/class.rs b/src/class.rs index a7b6c1d..c82c177 100644 --- a/src/class.rs +++ b/src/class.rs @@ -1,6 +1,6 @@ //! Contains the class implementation. -use crate::data::packet::usb_midi_event_packet::{MidiPacketParsingError, UsbMidiEventPacket}; +use crate::packet::usb_midi_event_packet::{MidiPacketParsingError, UsbMidiEventPacket}; use usb_device::class_prelude::*; use usb_device::Result; diff --git a/src/data/midi/message/mod.rs b/src/data/midi/message/mod.rs index 60839c3..a5e833c 100644 --- a/src/data/midi/message/mod.rs +++ b/src/data/midi/message/mod.rs @@ -9,7 +9,7 @@ use crate::data::midi::channel::Channel; use crate::data::midi::message::control_function::ControlFunction; use crate::data::midi::message::raw::{Payload, Raw}; use crate::data::midi::notes::Note; -use crate::data::packet::usb_midi_event_packet::MidiPacketParsingError; +use crate::packet::usb_midi_event_packet::MidiPacketParsingError; use core::convert::TryFrom; type Velocity = U7; diff --git a/src/data/mod.rs b/src/data/mod.rs index 736816d..34515c9 100644 --- a/src/data/mod.rs +++ b/src/data/mod.rs @@ -2,4 +2,3 @@ pub mod byte; pub mod midi; -pub mod packet; diff --git a/src/lib.rs b/src/lib.rs index c331605..baccde3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,8 +4,9 @@ pub mod class; pub mod data; +pub mod packet; pub use crate::class::MidiClass; -pub use crate::data::packet::cable_number::CableNumber; -pub use crate::data::packet::midi_packet_reader::MidiPacketBufferReader; -pub use crate::data::packet::usb_midi_event_packet::UsbMidiEventPacket; +pub use crate::packet::cable_number::CableNumber; +pub use crate::packet::midi_packet_reader::MidiPacketBufferReader; +pub use crate::packet::usb_midi_event_packet::UsbMidiEventPacket; diff --git a/src/data/packet/cable_number.rs b/src/packet/cable_number.rs similarity index 100% rename from src/data/packet/cable_number.rs rename to src/packet/cable_number.rs diff --git a/src/data/packet/code_index_number.rs b/src/packet/code_index_number.rs similarity index 100% rename from src/data/packet/code_index_number.rs rename to src/packet/code_index_number.rs diff --git a/src/data/packet/midi_packet_reader.rs b/src/packet/midi_packet_reader.rs similarity index 92% rename from src/data/packet/midi_packet_reader.rs rename to src/packet/midi_packet_reader.rs index 733644d..89265ed 100644 --- a/src/data/packet/midi_packet_reader.rs +++ b/src/packet/midi_packet_reader.rs @@ -1,7 +1,7 @@ //! Reader for received packets. use crate::class::{MAX_PACKET_SIZE, MIDI_PACKET_SIZE}; -use crate::data::packet::usb_midi_event_packet::{MidiPacketParsingError, UsbMidiEventPacket}; +use crate::packet::usb_midi_event_packet::{MidiPacketParsingError, UsbMidiEventPacket}; use core::convert::TryFrom; /// Packet reader with internal buffer for received message. diff --git a/src/data/packet/mod.rs b/src/packet/mod.rs similarity index 100% rename from src/data/packet/mod.rs rename to src/packet/mod.rs diff --git a/src/data/packet/usb_midi_event_packet.rs b/src/packet/usb_midi_event_packet.rs similarity index 95% rename from src/data/packet/usb_midi_event_packet.rs rename to src/packet/usb_midi_event_packet.rs index 1cb8823..5fc6297 100644 --- a/src/data/packet/usb_midi_event_packet.rs +++ b/src/packet/usb_midi_event_packet.rs @@ -5,8 +5,8 @@ use core::convert::{TryFrom, TryInto}; use crate::data::byte::u4::U4; use crate::data::midi::message::raw::{Payload, Raw}; use crate::data::midi::message::Message; -use crate::data::packet::cable_number::CableNumber; -use crate::data::packet::code_index_number::CodeIndexNumber; +use crate::packet::cable_number::CableNumber; +use crate::packet::code_index_number::CodeIndexNumber; /// A packet that communicates with the host. /// @@ -146,8 +146,8 @@ mod tests { use crate::data::midi::message::control_function::ControlFunction; use crate::data::midi::message::Message; use crate::data::midi::notes::Note; - use crate::data::packet::cable_number::CableNumber::{Cable0, Cable1}; - use crate::data::packet::usb_midi_event_packet::UsbMidiEventPacket; + use crate::packet::cable_number::CableNumber::{Cable0, Cable1}; + use crate::packet::usb_midi_event_packet::UsbMidiEventPacket; use core::convert::TryFrom; macro_rules! decode_message_test { From f24c118b7239e3b0f8c16d723223c9957f30f629 Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Thu, 19 Dec 2024 10:49:10 +0100 Subject: [PATCH 13/67] Renamed midi_packet_reader module to reader --- CHANGELOG.md | 1 + src/lib.rs | 2 +- src/packet/mod.rs | 2 +- src/packet/{midi_packet_reader.rs => reader.rs} | 0 4 files changed, 3 insertions(+), 2 deletions(-) rename src/packet/{midi_packet_reader.rs => reader.rs} (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index c67b13c..8c7ef5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Renamed `MidiClass::send_message` function to `MidiClass::send_packet`. - Renamed `midi_device` module to `class`. - Renamed `usb_midi` module to `packet` and moved it into crate root. +- Renamed `midi_packet_reader` module to `reader`. - Moved usb descriptor constants into class module and made them private. ### Removed diff --git a/src/lib.rs b/src/lib.rs index baccde3..9a64a62 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,5 +8,5 @@ pub mod packet; pub use crate::class::MidiClass; pub use crate::packet::cable_number::CableNumber; -pub use crate::packet::midi_packet_reader::MidiPacketBufferReader; +pub use crate::packet::reader::MidiPacketBufferReader; pub use crate::packet::usb_midi_event_packet::UsbMidiEventPacket; diff --git a/src/packet/mod.rs b/src/packet/mod.rs index 4f41a5a..1bb9273 100644 --- a/src/packet/mod.rs +++ b/src/packet/mod.rs @@ -2,5 +2,5 @@ pub mod cable_number; pub mod code_index_number; -pub mod midi_packet_reader; +pub mod reader; pub mod usb_midi_event_packet; diff --git a/src/packet/midi_packet_reader.rs b/src/packet/reader.rs similarity index 100% rename from src/packet/midi_packet_reader.rs rename to src/packet/reader.rs From 82e9370095b7d43f23f5b2223f70f97a6b43d5b4 Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Thu, 19 Dec 2024 10:51:57 +0100 Subject: [PATCH 14/67] Renamed usb_midi_event_packet module to event_packet --- CHANGELOG.md | 1 + src/class.rs | 2 +- src/data/midi/message/mod.rs | 2 +- src/lib.rs | 2 +- src/packet/{usb_midi_event_packet.rs => event_packet.rs} | 2 +- src/packet/mod.rs | 2 +- src/packet/reader.rs | 2 +- 7 files changed, 7 insertions(+), 6 deletions(-) rename src/packet/{usb_midi_event_packet.rs => event_packet.rs} (98%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c7ef5f..6262301 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Renamed `midi_device` module to `class`. - Renamed `usb_midi` module to `packet` and moved it into crate root. - Renamed `midi_packet_reader` module to `reader`. +- Renamed `usb_midi_event_packet` module to `event_packet`. - Moved usb descriptor constants into class module and made them private. ### Removed diff --git a/src/class.rs b/src/class.rs index c82c177..9630422 100644 --- a/src/class.rs +++ b/src/class.rs @@ -1,6 +1,6 @@ //! Contains the class implementation. -use crate::packet::usb_midi_event_packet::{MidiPacketParsingError, UsbMidiEventPacket}; +use crate::packet::event_packet::{MidiPacketParsingError, UsbMidiEventPacket}; use usb_device::class_prelude::*; use usb_device::Result; diff --git a/src/data/midi/message/mod.rs b/src/data/midi/message/mod.rs index a5e833c..3637b9d 100644 --- a/src/data/midi/message/mod.rs +++ b/src/data/midi/message/mod.rs @@ -9,7 +9,7 @@ use crate::data::midi::channel::Channel; use crate::data::midi::message::control_function::ControlFunction; use crate::data::midi::message::raw::{Payload, Raw}; use crate::data::midi::notes::Note; -use crate::packet::usb_midi_event_packet::MidiPacketParsingError; +use crate::packet::event_packet::MidiPacketParsingError; use core::convert::TryFrom; type Velocity = U7; diff --git a/src/lib.rs b/src/lib.rs index 9a64a62..7485425 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,5 +8,5 @@ pub mod packet; pub use crate::class::MidiClass; pub use crate::packet::cable_number::CableNumber; +pub use crate::packet::event_packet::UsbMidiEventPacket; pub use crate::packet::reader::MidiPacketBufferReader; -pub use crate::packet::usb_midi_event_packet::UsbMidiEventPacket; diff --git a/src/packet/usb_midi_event_packet.rs b/src/packet/event_packet.rs similarity index 98% rename from src/packet/usb_midi_event_packet.rs rename to src/packet/event_packet.rs index 5fc6297..0cc7624 100644 --- a/src/packet/usb_midi_event_packet.rs +++ b/src/packet/event_packet.rs @@ -147,7 +147,7 @@ mod tests { use crate::data::midi::message::Message; use crate::data::midi::notes::Note; use crate::packet::cable_number::CableNumber::{Cable0, Cable1}; - use crate::packet::usb_midi_event_packet::UsbMidiEventPacket; + use crate::packet::event_packet::UsbMidiEventPacket; use core::convert::TryFrom; macro_rules! decode_message_test { diff --git a/src/packet/mod.rs b/src/packet/mod.rs index 1bb9273..007d310 100644 --- a/src/packet/mod.rs +++ b/src/packet/mod.rs @@ -2,5 +2,5 @@ pub mod cable_number; pub mod code_index_number; +pub mod event_packet; pub mod reader; -pub mod usb_midi_event_packet; diff --git a/src/packet/reader.rs b/src/packet/reader.rs index 89265ed..6c6df3c 100644 --- a/src/packet/reader.rs +++ b/src/packet/reader.rs @@ -1,7 +1,7 @@ //! Reader for received packets. use crate::class::{MAX_PACKET_SIZE, MIDI_PACKET_SIZE}; -use crate::packet::usb_midi_event_packet::{MidiPacketParsingError, UsbMidiEventPacket}; +use crate::packet::event_packet::{MidiPacketParsingError, UsbMidiEventPacket}; use core::convert::TryFrom; /// Packet reader with internal buffer for received message. From 46fa072ccd75c19ddbeb285f7b3d5f2489c80033 Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Thu, 19 Dec 2024 11:01:15 +0100 Subject: [PATCH 15/67] Moved channel and notes module into message module --- CHANGELOG.md | 1 + src/data/midi/{ => message}/channel.rs | 0 src/data/midi/message/mod.rs | 6 ++++-- src/data/midi/{ => message}/notes.rs | 0 src/data/midi/mod.rs | 2 -- src/packet/event_packet.rs | 4 ++-- 6 files changed, 7 insertions(+), 6 deletions(-) rename src/data/midi/{ => message}/channel.rs (100%) rename src/data/midi/{ => message}/notes.rs (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6262301..3ed47a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Renamed `usb_midi` module to `packet` and moved it into crate root. - Renamed `midi_packet_reader` module to `reader`. - Renamed `usb_midi_event_packet` module to `event_packet`. +- Moved `channel` and `notes` modules into `message` module. - Moved usb descriptor constants into class module and made them private. ### Removed diff --git a/src/data/midi/channel.rs b/src/data/midi/message/channel.rs similarity index 100% rename from src/data/midi/channel.rs rename to src/data/midi/message/channel.rs diff --git a/src/data/midi/message/mod.rs b/src/data/midi/message/mod.rs index 3637b9d..d52919b 100644 --- a/src/data/midi/message/mod.rs +++ b/src/data/midi/message/mod.rs @@ -1,14 +1,16 @@ //! Enum representing the MIDI message. +pub mod channel; pub mod control_function; +pub mod notes; pub mod raw; use crate::data::byte::from_traits::FromClamped; use crate::data::byte::u7::U7; -use crate::data::midi::channel::Channel; +use crate::data::midi::message::channel::Channel; use crate::data::midi::message::control_function::ControlFunction; +use crate::data::midi::message::notes::Note; use crate::data::midi::message::raw::{Payload, Raw}; -use crate::data::midi::notes::Note; use crate::packet::event_packet::MidiPacketParsingError; use core::convert::TryFrom; diff --git a/src/data/midi/notes.rs b/src/data/midi/message/notes.rs similarity index 100% rename from src/data/midi/notes.rs rename to src/data/midi/message/notes.rs diff --git a/src/data/midi/mod.rs b/src/data/midi/mod.rs index 341d6f6..65baac5 100644 --- a/src/data/midi/mod.rs +++ b/src/data/midi/mod.rs @@ -1,5 +1,3 @@ //! MIDI message and related types. -pub mod channel; pub mod message; -pub mod notes; diff --git a/src/packet/event_packet.rs b/src/packet/event_packet.rs index 0cc7624..98812ff 100644 --- a/src/packet/event_packet.rs +++ b/src/packet/event_packet.rs @@ -142,10 +142,10 @@ impl UsbMidiEventPacket { #[cfg(test)] mod tests { use crate::data::byte::u7::U7; - use crate::data::midi::channel::Channel::{Channel1, Channel2}; + use crate::data::midi::message::channel::Channel::{Channel1, Channel2}; use crate::data::midi::message::control_function::ControlFunction; + use crate::data::midi::message::notes::Note; use crate::data::midi::message::Message; - use crate::data::midi::notes::Note; use crate::packet::cable_number::CableNumber::{Cable0, Cable1}; use crate::packet::event_packet::UsbMidiEventPacket; use core::convert::TryFrom; From 7a59ae3c43a4f01875b03511e4588a14dc421559 Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Thu, 19 Dec 2024 11:09:53 +0100 Subject: [PATCH 16/67] Moved message module to crate root --- CHANGELOG.md | 1 + src/data/midi/mod.rs | 3 --- src/data/mod.rs | 1 - src/lib.rs | 2 ++ src/{data/midi => }/message/channel.rs | 0 src/{data/midi => }/message/control_function.rs | 0 src/{data/midi => }/message/mod.rs | 8 ++++---- src/{data/midi => }/message/notes.rs | 0 src/{data/midi => }/message/raw.rs | 0 src/packet/code_index_number.rs | 2 +- src/packet/event_packet.rs | 12 ++++++------ 11 files changed, 14 insertions(+), 15 deletions(-) delete mode 100644 src/data/midi/mod.rs rename src/{data/midi => }/message/channel.rs (100%) rename src/{data/midi => }/message/control_function.rs (100%) rename src/{data/midi => }/message/mod.rs (96%) rename src/{data/midi => }/message/notes.rs (100%) rename src/{data/midi => }/message/raw.rs (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ed47a2..18c0ea7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Renamed `midi_packet_reader` module to `reader`. - Renamed `usb_midi_event_packet` module to `event_packet`. - Moved `channel` and `notes` modules into `message` module. +- Moved `message` module to crate root. - Moved usb descriptor constants into class module and made them private. ### Removed diff --git a/src/data/midi/mod.rs b/src/data/midi/mod.rs deleted file mode 100644 index 65baac5..0000000 --- a/src/data/midi/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -//! MIDI message and related types. - -pub mod message; diff --git a/src/data/mod.rs b/src/data/mod.rs index 34515c9..944c28f 100644 --- a/src/data/mod.rs +++ b/src/data/mod.rs @@ -1,4 +1,3 @@ //! Primitives and structures used in USB MIDI data. pub mod byte; -pub mod midi; diff --git a/src/lib.rs b/src/lib.rs index 7485425..0c13777 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,9 +4,11 @@ pub mod class; pub mod data; +pub mod message; pub mod packet; pub use crate::class::MidiClass; +pub use crate::message::Message; pub use crate::packet::cable_number::CableNumber; pub use crate::packet::event_packet::UsbMidiEventPacket; pub use crate::packet::reader::MidiPacketBufferReader; diff --git a/src/data/midi/message/channel.rs b/src/message/channel.rs similarity index 100% rename from src/data/midi/message/channel.rs rename to src/message/channel.rs diff --git a/src/data/midi/message/control_function.rs b/src/message/control_function.rs similarity index 100% rename from src/data/midi/message/control_function.rs rename to src/message/control_function.rs diff --git a/src/data/midi/message/mod.rs b/src/message/mod.rs similarity index 96% rename from src/data/midi/message/mod.rs rename to src/message/mod.rs index d52919b..d74cada 100644 --- a/src/data/midi/message/mod.rs +++ b/src/message/mod.rs @@ -7,10 +7,10 @@ pub mod raw; use crate::data::byte::from_traits::FromClamped; use crate::data::byte::u7::U7; -use crate::data::midi::message::channel::Channel; -use crate::data::midi::message::control_function::ControlFunction; -use crate::data::midi::message::notes::Note; -use crate::data::midi::message::raw::{Payload, Raw}; +use crate::message::channel::Channel; +use crate::message::control_function::ControlFunction; +use crate::message::notes::Note; +use crate::message::raw::{Payload, Raw}; use crate::packet::event_packet::MidiPacketParsingError; use core::convert::TryFrom; diff --git a/src/data/midi/message/notes.rs b/src/message/notes.rs similarity index 100% rename from src/data/midi/message/notes.rs rename to src/message/notes.rs diff --git a/src/data/midi/message/raw.rs b/src/message/raw.rs similarity index 100% rename from src/data/midi/message/raw.rs rename to src/message/raw.rs diff --git a/src/packet/code_index_number.rs b/src/packet/code_index_number.rs index 63c884b..609d253 100644 --- a/src/packet/code_index_number.rs +++ b/src/packet/code_index_number.rs @@ -1,7 +1,7 @@ //! Enum representing the code index number of a packet. use crate::data::byte::u4::U4; -use crate::data::midi::message::Message; +use crate::message::Message; use core::convert::TryFrom; /// The Code Index Number(CIN) indicates the classification diff --git a/src/packet/event_packet.rs b/src/packet/event_packet.rs index 98812ff..dd56d43 100644 --- a/src/packet/event_packet.rs +++ b/src/packet/event_packet.rs @@ -3,8 +3,8 @@ use core::convert::{TryFrom, TryInto}; use crate::data::byte::u4::U4; -use crate::data::midi::message::raw::{Payload, Raw}; -use crate::data::midi::message::Message; +use crate::message::raw::{Payload, Raw}; +use crate::message::Message; use crate::packet::cable_number::CableNumber; use crate::packet::code_index_number::CodeIndexNumber; @@ -142,10 +142,10 @@ impl UsbMidiEventPacket { #[cfg(test)] mod tests { use crate::data::byte::u7::U7; - use crate::data::midi::message::channel::Channel::{Channel1, Channel2}; - use crate::data::midi::message::control_function::ControlFunction; - use crate::data::midi::message::notes::Note; - use crate::data::midi::message::Message; + use crate::message::channel::Channel::{Channel1, Channel2}; + use crate::message::control_function::ControlFunction; + use crate::message::notes::Note; + use crate::message::Message; use crate::packet::cable_number::CableNumber::{Cable0, Cable1}; use crate::packet::event_packet::UsbMidiEventPacket; use core::convert::TryFrom; From 061a4b3ba8094471006e8471c06790272abcd6e9 Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Thu, 19 Dec 2024 11:18:13 +0100 Subject: [PATCH 17/67] Moved byte submodules into data module --- CHANGELOG.md | 1 + src/data/byte/mod.rs | 5 ----- src/data/{byte => }/from_traits.rs | 0 src/data/mod.rs | 4 +++- src/data/{byte => }/u4.rs | 0 src/data/{byte => }/u7.rs | 2 +- src/message/control_function.rs | 2 +- src/message/mod.rs | 4 ++-- src/message/notes.rs | 4 ++-- src/message/raw.rs | 2 +- src/packet/cable_number.rs | 2 +- src/packet/code_index_number.rs | 2 +- src/packet/event_packet.rs | 4 ++-- 13 files changed, 15 insertions(+), 17 deletions(-) delete mode 100644 src/data/byte/mod.rs rename src/data/{byte => }/from_traits.rs (100%) rename src/data/{byte => }/u4.rs (100%) rename src/data/{byte => }/u7.rs (94%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 18c0ea7..0e7b5dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Renamed `usb_midi_event_packet` module to `event_packet`. - Moved `channel` and `notes` modules into `message` module. - Moved `message` module to crate root. +- Moved `byte` submodules into `data` module. - Moved usb descriptor constants into class module and made them private. ### Removed diff --git a/src/data/byte/mod.rs b/src/data/byte/mod.rs deleted file mode 100644 index bdcb243..0000000 --- a/src/data/byte/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -//! Primitive types with bit lengths used in USB MIDI data. - -pub mod from_traits; -pub mod u4; -pub mod u7; diff --git a/src/data/byte/from_traits.rs b/src/data/from_traits.rs similarity index 100% rename from src/data/byte/from_traits.rs rename to src/data/from_traits.rs diff --git a/src/data/mod.rs b/src/data/mod.rs index 944c28f..fcdd7d3 100644 --- a/src/data/mod.rs +++ b/src/data/mod.rs @@ -1,3 +1,5 @@ //! Primitives and structures used in USB MIDI data. -pub mod byte; +pub mod from_traits; +pub mod u4; +pub mod u7; diff --git a/src/data/byte/u4.rs b/src/data/u4.rs similarity index 100% rename from src/data/byte/u4.rs rename to src/data/u4.rs diff --git a/src/data/byte/u7.rs b/src/data/u7.rs similarity index 94% rename from src/data/byte/u7.rs rename to src/data/u7.rs index 213f9e9..3a57eaa 100644 --- a/src/data/byte/u7.rs +++ b/src/data/u7.rs @@ -1,6 +1,6 @@ //! A primitive value with 7-bit length. -use crate::data::byte::from_traits::{FromClamped, FromOverFlow}; +use crate::data::from_traits::{FromClamped, FromOverFlow}; use core::convert::TryFrom; /// A primitive value that can be from 0-0x7F diff --git a/src/message/control_function.rs b/src/message/control_function.rs index 58028f4..932e1a4 100644 --- a/src/message/control_function.rs +++ b/src/message/control_function.rs @@ -1,6 +1,6 @@ //! Control function definitions. -use crate::data::byte::u7::U7; +use crate::data::u7::U7; /// Custom type for a control function. #[derive(Debug, Clone, Eq, PartialEq)] diff --git a/src/message/mod.rs b/src/message/mod.rs index d74cada..2db61f0 100644 --- a/src/message/mod.rs +++ b/src/message/mod.rs @@ -5,8 +5,8 @@ pub mod control_function; pub mod notes; pub mod raw; -use crate::data::byte::from_traits::FromClamped; -use crate::data::byte::u7::U7; +use crate::data::from_traits::FromClamped; +use crate::data::u7::U7; use crate::message::channel::Channel; use crate::message::control_function::ControlFunction; use crate::message::notes::Note; diff --git a/src/message/notes.rs b/src/message/notes.rs index ff27f83..89a38a8 100644 --- a/src/message/notes.rs +++ b/src/message/notes.rs @@ -1,7 +1,7 @@ //! Enum representing the MIDI notes. -use crate::data::byte::from_traits::FromOverFlow; -use crate::data::byte::u7::U7; +use crate::data::from_traits::FromOverFlow; +use crate::data::u7::U7; use num_enum::TryFromPrimitive; /// A simple enum type that represents all the midi 'notes'. diff --git a/src/message/raw.rs b/src/message/raw.rs index a318702..1c8c397 100644 --- a/src/message/raw.rs +++ b/src/message/raw.rs @@ -1,6 +1,6 @@ //! Type for the raw MIDI message. -use crate::data::byte::u7::U7; +use crate::data::u7::U7; /// Represents the payloads that the midi message may contain. pub enum Payload { diff --git a/src/packet/cable_number.rs b/src/packet/cable_number.rs index e76c262..70d4f7f 100644 --- a/src/packet/cable_number.rs +++ b/src/packet/cable_number.rs @@ -1,6 +1,6 @@ //! Enum representing the cable number of a packet. -use crate::data::byte::u4::U4; +use crate::data::u4::U4; use core::convert::TryFrom; /// The Cable Number (CN) is a value ranging from 0x0 to 0xF diff --git a/src/packet/code_index_number.rs b/src/packet/code_index_number.rs index 609d253..d424c27 100644 --- a/src/packet/code_index_number.rs +++ b/src/packet/code_index_number.rs @@ -1,6 +1,6 @@ //! Enum representing the code index number of a packet. -use crate::data::byte::u4::U4; +use crate::data::u4::U4; use crate::message::Message; use core::convert::TryFrom; diff --git a/src/packet/event_packet.rs b/src/packet/event_packet.rs index dd56d43..fb9423e 100644 --- a/src/packet/event_packet.rs +++ b/src/packet/event_packet.rs @@ -2,7 +2,7 @@ use core::convert::{TryFrom, TryInto}; -use crate::data::byte::u4::U4; +use crate::data::u4::U4; use crate::message::raw::{Payload, Raw}; use crate::message::Message; use crate::packet::cable_number::CableNumber; @@ -141,7 +141,7 @@ impl UsbMidiEventPacket { #[cfg(test)] mod tests { - use crate::data::byte::u7::U7; + use crate::data::u7::U7; use crate::message::channel::Channel::{Channel1, Channel2}; use crate::message::control_function::ControlFunction; use crate::message::notes::Note; From 06b41e3b7cfe5af769fb613e7d85edd3cc9b606a Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Thu, 19 Dec 2024 11:59:07 +0100 Subject: [PATCH 18/67] Added TryFrom<&UsbMidiEventPacket> for Message --- CHANGELOG.md | 1 + src/message/mod.rs | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e7b5dd..02abc1d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - `UsbMidiEventPacket::as_raw_bytes` function. - `UsbMidiEventPacket::to_raw_bytes` function. - `UsbMidiEventPacket::from_message_bytes` function. +- `TryFrom<&UsbMidiEventPacket>` implementation for `Message` type. - Re-exports of common items in crate root. ### Changed diff --git a/src/message/mod.rs b/src/message/mod.rs index 2db61f0..e555fab 100644 --- a/src/message/mod.rs +++ b/src/message/mod.rs @@ -5,14 +5,15 @@ pub mod control_function; pub mod notes; pub mod raw; +use core::convert::TryFrom; + use crate::data::from_traits::FromClamped; use crate::data::u7::U7; use crate::message::channel::Channel; use crate::message::control_function::ControlFunction; use crate::message::notes::Note; use crate::message::raw::{Payload, Raw}; -use crate::packet::event_packet::MidiPacketParsingError; -use core::convert::TryFrom; +use crate::packet::event_packet::{MidiPacketParsingError, UsbMidiEventPacket}; type Velocity = U7; @@ -91,6 +92,7 @@ impl From for Raw { impl TryFrom<&[u8]> for Message { type Error = MidiPacketParsingError; + fn try_from(data: &[u8]) -> Result { let status_byte = match data.first() { Some(byte) => byte, @@ -135,6 +137,14 @@ impl TryFrom<&[u8]> for Message { } } +impl TryFrom<&UsbMidiEventPacket> for Message { + type Error = MidiPacketParsingError; + + fn try_from(value: &UsbMidiEventPacket) -> Result { + Self::try_from(&value.as_raw_bytes()[1..]) + } +} + fn get_note(data: &[u8]) -> Result { let note_byte = get_byte_at_position(data, 1)?; match Note::try_from(note_byte) { From 763e1f48aa07504d41cf74453644e0079d76c19b Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Thu, 19 Dec 2024 12:25:28 +0100 Subject: [PATCH 19/67] Added Message::into_packet function --- CHANGELOG.md | 1 + src/message/mod.rs | 32 ++++++++++++++++++++++++++++++++ src/packet/event_packet.rs | 24 +----------------------- 3 files changed, 34 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 02abc1d..ed1bf76 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - `UsbMidiEventPacket::to_raw_bytes` function. - `UsbMidiEventPacket::from_message_bytes` function. - `TryFrom<&UsbMidiEventPacket>` implementation for `Message` type. +- `Message::into_packet` function. - Re-exports of common items in crate root. ### Changed diff --git a/src/message/mod.rs b/src/message/mod.rs index e555fab..2371e1f 100644 --- a/src/message/mod.rs +++ b/src/message/mod.rs @@ -8,11 +8,14 @@ pub mod raw; use core::convert::TryFrom; use crate::data::from_traits::FromClamped; +use crate::data::u4::U4; use crate::data::u7::U7; use crate::message::channel::Channel; use crate::message::control_function::ControlFunction; use crate::message::notes::Note; use crate::message::raw::{Payload, Raw}; +use crate::packet::cable_number::CableNumber; +use crate::packet::code_index_number::CodeIndexNumber; use crate::packet::event_packet::{MidiPacketParsingError, UsbMidiEventPacket}; type Velocity = U7; @@ -145,6 +148,35 @@ impl TryFrom<&UsbMidiEventPacket> for Message { } } +impl Message { + /// Create a packet from the message. + pub fn into_packet(self, cable: CableNumber) -> UsbMidiEventPacket { + let cin = u8::from(U4::from(CodeIndexNumber::find_from_message(&self))); + + let mut raw = [0; 4]; + raw[0] = (cable as u8) << 4 | cin; + let r = Raw::from(self); + raw[1] = r.status; + + match r.payload { + Payload::Empty => { + raw[2] = 0; + raw[3] = 0; + } + Payload::SingleByte(byte) => { + raw[2] = byte.0; + raw[3] = 0; + } + Payload::DoubleByte(byte1, byte2) => { + raw[2] = byte1.0; + raw[3] = byte2.0; + } + }; + + UsbMidiEventPacket::try_from(raw.as_slice()).unwrap() + } +} + fn get_note(data: &[u8]) -> Result { let note_byte = get_byte_at_position(data, 1)?; match Note::try_from(note_byte) { diff --git a/src/packet/event_packet.rs b/src/packet/event_packet.rs index fb9423e..b8978d9 100644 --- a/src/packet/event_packet.rs +++ b/src/packet/event_packet.rs @@ -103,29 +103,7 @@ impl UsbMidiEventPacket { /// Creates a packet from a message and returns it. pub fn from_message(cable: CableNumber, message: Message) -> Self { - let cin = u8::from(U4::from(CodeIndexNumber::find_from_message(&message))); - - let mut raw = [0; 4]; - raw[0] = (cable as u8) << 4 | cin; - let r = Raw::from(message.clone()); - raw[1] = r.status; - - match r.payload { - Payload::Empty => { - raw[2] = 0; - raw[3] = 0; - } - Payload::SingleByte(byte) => { - raw[2] = byte.0; - raw[3] = 0; - } - Payload::DoubleByte(byte1, byte2) => { - raw[2] = byte1.0; - raw[3] = byte2.0; - } - }; - - Self { raw } + message.into_packet(cable) } /// Creates a packet from a slice of message bytes. From 9b634eb03f4de053ff45c939940c123f29b4b07e Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Thu, 19 Dec 2024 12:40:08 +0100 Subject: [PATCH 20/67] Moved tests from packet to message module --- src/message/mod.rs | 35 +++++++++++++++++++++++++++++++++++ src/packet/event_packet.rs | 35 ----------------------------------- 2 files changed, 35 insertions(+), 35 deletions(-) diff --git a/src/message/mod.rs b/src/message/mod.rs index 2371e1f..429e254 100644 --- a/src/message/mod.rs +++ b/src/message/mod.rs @@ -196,3 +196,38 @@ fn get_byte_at_position(data: &[u8], index: usize) -> Result Err(MidiPacketParsingError::MissingDataPacket), } } + +#[cfg(test)] +mod tests { + use crate::data::u7::U7; + use crate::message::channel::Channel::{Channel1, Channel2}; + use crate::message::control_function::ControlFunction; + use crate::message::notes::Note; + use crate::message::Message; + use crate::packet::cable_number::CableNumber::{Cable0, Cable1}; + use crate::packet::event_packet::UsbMidiEventPacket; + use core::convert::TryFrom; + + macro_rules! decode_message_test { + ($($id:ident:$value:expr,)*) => { + $( + #[test] + fn $id() { + let (usb_midi_data_packet, expected) = $value; + let message = UsbMidiEventPacket::try_from(&usb_midi_data_packet[..]).unwrap(); + assert_eq!(expected, message); + } + )* + } + } + + decode_message_test! { + note_on: ([9, 144, 36, 127], Message::NoteOn(Channel1, Note::C2, U7(127)).into_packet(Cable0)), + note_off: ([8, 128, 36, 0], Message::NoteOff(Channel1, Note::C2, U7(0)).into_packet(Cable0)), + polyphonic_aftertouch: ([10, 160, 36, 64], Message::PolyphonicAftertouch(Channel1, Note::C2, U7(64)).into_packet(Cable0)), + program_change: ([28, 192, 127, 0], Message::ProgramChange(Channel1, U7(127)).into_packet(Cable1)), + channel_aftertouch: ([13, 208, 127, 0], Message::ChannelAftertouch(Channel1, U7(127)).into_packet(Cable0)), + pitch_wheel: ([14, 224, 64, 32], Message::PitchWheelChange(Channel1, U7(64), U7(32)).into_packet(Cable0)), + control_change: ([11, 177, 1, 32], Message::ControlChange(Channel2, ControlFunction::MOD_WHEEL_1, U7(32)).into_packet(Cable0)), + } +} diff --git a/src/packet/event_packet.rs b/src/packet/event_packet.rs index b8978d9..792064a 100644 --- a/src/packet/event_packet.rs +++ b/src/packet/event_packet.rs @@ -116,38 +116,3 @@ impl UsbMidiEventPacket { Ok(Self::from_message(cable, message)) } } - -#[cfg(test)] -mod tests { - use crate::data::u7::U7; - use crate::message::channel::Channel::{Channel1, Channel2}; - use crate::message::control_function::ControlFunction; - use crate::message::notes::Note; - use crate::message::Message; - use crate::packet::cable_number::CableNumber::{Cable0, Cable1}; - use crate::packet::event_packet::UsbMidiEventPacket; - use core::convert::TryFrom; - - macro_rules! decode_message_test { - ($($id:ident:$value:expr,)*) => { - $( - #[test] - fn $id() { - let (usb_midi_data_packet, expected) = $value; - let message = UsbMidiEventPacket::try_from(&usb_midi_data_packet[..]).unwrap(); - assert_eq!(expected, message); - } - )* - } - } - - decode_message_test! { - note_on: ([9, 144, 36, 127], UsbMidiEventPacket::from_message(Cable0, Message::NoteOn(Channel1, Note::C2, U7(127)))), - note_off: ([8, 128, 36, 0], UsbMidiEventPacket::from_message(Cable0, Message::NoteOff(Channel1, Note::C2, U7(0)))), - polyphonic_aftertouch: ([10, 160, 36, 64], UsbMidiEventPacket::from_message(Cable0, Message::PolyphonicAftertouch(Channel1, Note::C2, U7(64)))), - program_change: ([28, 192, 127, 0], UsbMidiEventPacket::from_message(Cable1, Message::ProgramChange(Channel1, U7(127)))), - channel_aftertouch: ([13, 208, 127, 0], UsbMidiEventPacket::from_message(Cable0, Message::ChannelAftertouch(Channel1, U7(127)))), - pitch_wheel: ([14, 224, 64, 32], UsbMidiEventPacket::from_message(Cable0, Message::PitchWheelChange(Channel1, U7(64), U7(32)))), - control_change: ([11, 177, 1, 32], UsbMidiEventPacket::from_message(Cable0, Message::ControlChange(Channel2, ControlFunction::MOD_WHEEL_1, U7(32)))), - } -} From d6383c84b9e77d99e11798b92f613dd515f7ddc6 Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Thu, 19 Dec 2024 12:47:16 +0100 Subject: [PATCH 21/67] Removed UsbMidiEventPacket::from_message function --- CHANGELOG.md | 2 +- src/packet/event_packet.rs | 7 +------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ed1bf76..1b20a2c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,7 +21,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Changed -- Renamed `UsbMidiEventPacket::from_midi` function to `UsbMidiEventPacket::from_message`. - Renamed `MidiClass::send_message` function to `MidiClass::send_packet`. - Renamed `midi_device` module to `class`. - Renamed `usb_midi` module to `packet` and moved it into crate root. @@ -36,6 +35,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - `UsbMidiEventPacket::cable_number` field, use function instead. - `UsbMidiEventPacket::message` field, use function instead. +- `UsbMidiEventPacket::from_midi` function, use `Message::into_packet` instead. ## [0.3.0] - 2024-05-27 diff --git a/src/packet/event_packet.rs b/src/packet/event_packet.rs index 792064a..b76e70b 100644 --- a/src/packet/event_packet.rs +++ b/src/packet/event_packet.rs @@ -101,11 +101,6 @@ impl UsbMidiEventPacket { self.raw.clone() } - /// Creates a packet from a message and returns it. - pub fn from_message(cable: CableNumber, message: Message) -> Self { - message.into_packet(cable) - } - /// Creates a packet from a slice of message bytes. pub fn from_message_bytes( cable: CableNumber, @@ -113,6 +108,6 @@ impl UsbMidiEventPacket { ) -> Result { let message = Message::try_from(bytes)?; - Ok(Self::from_message(cable, message)) + Ok(message.into_packet(cable)) } } From 5b611020598b27de7db4d947d34a6bdc4786954a Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Thu, 19 Dec 2024 12:56:15 +0100 Subject: [PATCH 22/67] Removed UsbMidiEventPacket::message function --- CHANGELOG.md | 3 +-- src/packet/event_packet.rs | 9 ++------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b20a2c..a3215b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Added - `UsbMidiEventPacket::cable_number` function. -- `UsbMidiEventPacket::message` function. - `UsbMidiEventPacket::as_message_bytes` function. - `UsbMidiEventPacket::as_raw_bytes` function. - `UsbMidiEventPacket::to_raw_bytes` function. @@ -34,7 +33,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Removed - `UsbMidiEventPacket::cable_number` field, use function instead. -- `UsbMidiEventPacket::message` field, use function instead. +- `UsbMidiEventPacket::message` field, use `Message::try_from(&UsbMidiEventPacket)` instead. - `UsbMidiEventPacket::from_midi` function, use `Message::into_packet` instead. ## [0.3.0] - 2024-05-27 diff --git a/src/packet/event_packet.rs b/src/packet/event_packet.rs index b76e70b..165c459 100644 --- a/src/packet/event_packet.rs +++ b/src/packet/event_packet.rs @@ -21,7 +21,7 @@ pub struct UsbMidiEventPacket { impl From for [u8; 4] { fn from(value: UsbMidiEventPacket) -> [u8; 4] { let cable_number = U4::from(value.cable_number()); - let message = value.message(); + let message = Message::try_from(&value).unwrap(); let index_number = { let code_index = CodeIndexNumber::find_from_message(&message); U4::from(code_index) @@ -74,14 +74,9 @@ impl UsbMidiEventPacket { CableNumber::try_from(raw_cable_number).unwrap() } - /// Returns the message. - pub fn message(&self) -> Message { - Message::try_from(&self.raw[1..]).unwrap() - } - /// Returns a slice to the message bytes. The length is dependent on the message type. pub fn as_message_bytes(&self) -> &[u8] { - let r = Raw::from(self.message()); + let r = Raw::from(Message::try_from(self).unwrap()); let length = match r.payload { Payload::Empty => 1, Payload::SingleByte(_) => 2, From e82530ff26d1e8f5215e13dc0041c25b70d57fc0 Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Thu, 19 Dec 2024 13:22:31 +0100 Subject: [PATCH 23/67] Renamed UsbMidiEventPacket::from_message_bytes to UsbMidiEventPacket::try_from_message_bytes --- CHANGELOG.md | 2 +- examples/example-esp32s3/src/main.rs | 2 +- src/packet/event_packet.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a3215b4..87742ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - `UsbMidiEventPacket::as_message_bytes` function. - `UsbMidiEventPacket::as_raw_bytes` function. - `UsbMidiEventPacket::to_raw_bytes` function. -- `UsbMidiEventPacket::from_message_bytes` function. +- `UsbMidiEventPacket::try_from_message_bytes` function. - `TryFrom<&UsbMidiEventPacket>` implementation for `Message` type. - `Message::into_packet` function. - Re-exports of common items in crate root. diff --git a/examples/example-esp32s3/src/main.rs b/examples/example-esp32s3/src/main.rs index 020ae3c..deaf93d 100644 --- a/examples/example-esp32s3/src/main.rs +++ b/examples/example-esp32s3/src/main.rs @@ -74,7 +74,7 @@ fn main() -> ! { message.render_slice(&mut bytes); let packet = - UsbMidiEventPacket::from_message_bytes(CableNumber::Cable0, &bytes).unwrap(); + UsbMidiEventPacket::try_from_message_bytes(CableNumber::Cable0, &bytes).unwrap(); let result = midi_class.send_packet(packet); println!("Send result {:?}", result); diff --git a/src/packet/event_packet.rs b/src/packet/event_packet.rs index 165c459..e978f48 100644 --- a/src/packet/event_packet.rs +++ b/src/packet/event_packet.rs @@ -97,7 +97,7 @@ impl UsbMidiEventPacket { } /// Creates a packet from a slice of message bytes. - pub fn from_message_bytes( + pub fn try_from_message_bytes( cable: CableNumber, bytes: &[u8], ) -> Result { From 4b376c2d3b096aaab90890ee9e89fd401b2e08e8 Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Thu, 19 Dec 2024 13:34:13 +0100 Subject: [PATCH 24/67] Added Message::code_index_number function --- CHANGELOG.md | 1 + src/message/mod.rs | 15 ++++++++++++++- src/packet/event_packet.rs | 6 +----- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 87742ed..5b9cfa3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - `UsbMidiEventPacket::try_from_message_bytes` function. - `TryFrom<&UsbMidiEventPacket>` implementation for `Message` type. - `Message::into_packet` function. +- `Message::code_index_number` function. - Re-exports of common items in crate root. ### Changed diff --git a/src/message/mod.rs b/src/message/mod.rs index 429e254..fd4c640 100644 --- a/src/message/mod.rs +++ b/src/message/mod.rs @@ -151,7 +151,7 @@ impl TryFrom<&UsbMidiEventPacket> for Message { impl Message { /// Create a packet from the message. pub fn into_packet(self, cable: CableNumber) -> UsbMidiEventPacket { - let cin = u8::from(U4::from(CodeIndexNumber::find_from_message(&self))); + let cin = u8::from(U4::from(self.code_index_number())); let mut raw = [0; 4]; raw[0] = (cable as u8) << 4 | cin; @@ -175,6 +175,19 @@ impl Message { UsbMidiEventPacket::try_from(raw.as_slice()).unwrap() } + + /// Returns the code index number for a message. + pub fn code_index_number(&self) -> CodeIndexNumber { + match self { + Self::NoteOn(_, _, _) => CodeIndexNumber::NOTE_ON, + Self::NoteOff(_, _, _) => CodeIndexNumber::NOTE_OFF, + Self::ChannelAftertouch(_, _) => CodeIndexNumber::CHANNEL_PRESSURE, + Self::PitchWheelChange(_, _, _) => CodeIndexNumber::PITCHBEND_CHANGE, + Self::PolyphonicAftertouch(_, _, _) => CodeIndexNumber::POLY_KEYPRESS, + Self::ProgramChange(_, _) => CodeIndexNumber::PROGRAM_CHANGE, + Self::ControlChange(_, _, _) => CodeIndexNumber::CONTROL_CHANGE, + } + } } fn get_note(data: &[u8]) -> Result { diff --git a/src/packet/event_packet.rs b/src/packet/event_packet.rs index e978f48..b90129e 100644 --- a/src/packet/event_packet.rs +++ b/src/packet/event_packet.rs @@ -6,7 +6,6 @@ use crate::data::u4::U4; use crate::message::raw::{Payload, Raw}; use crate::message::Message; use crate::packet::cable_number::CableNumber; -use crate::packet::code_index_number::CodeIndexNumber; /// A packet that communicates with the host. /// @@ -22,10 +21,7 @@ impl From for [u8; 4] { fn from(value: UsbMidiEventPacket) -> [u8; 4] { let cable_number = U4::from(value.cable_number()); let message = Message::try_from(&value).unwrap(); - let index_number = { - let code_index = CodeIndexNumber::find_from_message(&message); - U4::from(code_index) - }; + let index_number = { U4::from(message.code_index_number()) }; let header = U4::combine(cable_number, index_number); let raw_midi = Raw::from(message); From a493a9f3691eadfd8c0ca01a1169755d28a9931b Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Thu, 19 Dec 2024 13:38:22 +0100 Subject: [PATCH 25/67] Removed CodeIndexNumber::find_from_message function --- CHANGELOG.md | 1 + src/packet/code_index_number.rs | 14 -------------- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b9cfa3..c378b08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - `UsbMidiEventPacket::cable_number` field, use function instead. - `UsbMidiEventPacket::message` field, use `Message::try_from(&UsbMidiEventPacket)` instead. - `UsbMidiEventPacket::from_midi` function, use `Message::into_packet` instead. +- `CodeIndexNumber::find_from_message` function, use `Message::code_index_number` instead. ## [0.3.0] - 2024-05-27 diff --git a/src/packet/code_index_number.rs b/src/packet/code_index_number.rs index d424c27..88c01af 100644 --- a/src/packet/code_index_number.rs +++ b/src/packet/code_index_number.rs @@ -1,7 +1,6 @@ //! Enum representing the code index number of a packet. use crate::data::u4::U4; -use crate::message::Message; use core::convert::TryFrom; /// The Code Index Number(CIN) indicates the classification @@ -65,17 +64,4 @@ impl CodeIndexNumber { pub const PITCHBEND_CHANGE: CodeIndexNumber = CodeIndexNumber(0xE); /// Single Byte pub const SINGLE_BYTE: CodeIndexNumber = CodeIndexNumber(0xF); - - /// Determines the code index number of a message and returns it. - pub fn find_from_message(value: &Message) -> CodeIndexNumber { - match value { - Message::NoteOn(_, _, _) => CodeIndexNumber::NOTE_ON, - Message::NoteOff(_, _, _) => CodeIndexNumber::NOTE_OFF, - Message::ChannelAftertouch(_, _) => CodeIndexNumber::CHANNEL_PRESSURE, - Message::PitchWheelChange(_, _, _) => CodeIndexNumber::PITCHBEND_CHANGE, - Message::PolyphonicAftertouch(_, _, _) => CodeIndexNumber::POLY_KEYPRESS, - Message::ProgramChange(_, _) => CodeIndexNumber::PROGRAM_CHANGE, - Message::ControlChange(_, _, _) => CodeIndexNumber::CONTROL_CHANGE, - } - } } From ad34baf5a640dc41bdbe1568cd04b0013a4f75e2 Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Thu, 19 Dec 2024 13:57:45 +0100 Subject: [PATCH 26/67] Consolidated InvalidCableNumber and InvalidCodeIndexNumber into MidiPacketParsingError --- CHANGELOG.md | 4 +++- src/packet/cable_number.rs | 13 ++++++------- src/packet/code_index_number.rs | 12 ++++++------ src/packet/event_packet.rs | 2 ++ 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c378b08..b88b88c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,7 +29,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Moved `channel` and `notes` modules into `message` module. - Moved `message` module to crate root. - Moved `byte` submodules into `data` module. -- Moved usb descriptor constants into class module and made them private. +- Consolidated separate `InvalidCableNumber` struct into `MidiPacketParsingError`. +- Consolidated separate `InvalidCodeIndexNumber` struct into `MidiPacketParsingError`. +- Moved descriptor constants into class module and made them private. ### Removed diff --git a/src/packet/cable_number.rs b/src/packet/cable_number.rs index 70d4f7f..44f4a92 100644 --- a/src/packet/cable_number.rs +++ b/src/packet/cable_number.rs @@ -1,8 +1,10 @@ //! Enum representing the cable number of a packet. -use crate::data::u4::U4; use core::convert::TryFrom; +use crate::data::u4::U4; +use crate::packet::event_packet::MidiPacketParsingError; + /// The Cable Number (CN) is a value ranging from 0x0 to 0xF /// indicating the number assignment of the Embedded MIDI Jack associated /// with the endpoint that is transferring the data @@ -28,12 +30,9 @@ pub enum CableNumber { Cable15 = 0xF, } -/// Error indicating an invalid cable number. -#[derive(Debug)] -pub struct InvalidCableNumber(u8); - impl TryFrom for CableNumber { - type Error = InvalidCableNumber; + type Error = MidiPacketParsingError; + fn try_from(value: u8) -> Result { match value { x if x == CableNumber::Cable0 as u8 => Ok(CableNumber::Cable0), @@ -52,7 +51,7 @@ impl TryFrom for CableNumber { x if x == CableNumber::Cable13 as u8 => Ok(CableNumber::Cable13), x if x == CableNumber::Cable14 as u8 => Ok(CableNumber::Cable14), x if x == CableNumber::Cable15 as u8 => Ok(CableNumber::Cable15), - _ => Err(InvalidCableNumber(value)), + _ => Err(MidiPacketParsingError::InvalidCableNumber(value)), } } } diff --git a/src/packet/code_index_number.rs b/src/packet/code_index_number.rs index 88c01af..34d8ffa 100644 --- a/src/packet/code_index_number.rs +++ b/src/packet/code_index_number.rs @@ -1,20 +1,20 @@ //! Enum representing the code index number of a packet. -use crate::data::u4::U4; use core::convert::TryFrom; +use crate::data::u4::U4; +use crate::packet::event_packet::MidiPacketParsingError; + /// The Code Index Number(CIN) indicates the classification /// of the bytes in the MIDI_x fields pub struct CodeIndexNumber(u8); -/// Error indicating an invalid code index number. -pub struct InvalidCodeIndexNumber(u8); - impl TryFrom for CodeIndexNumber { - type Error = InvalidCodeIndexNumber; + type Error = MidiPacketParsingError; + fn try_from(value: u8) -> Result { if value > 0xF { - Err(InvalidCodeIndexNumber(value)) + Err(MidiPacketParsingError::InvalidCodeIndexNumber(value)) } else { Ok(CodeIndexNumber(value)) } diff --git a/src/packet/event_packet.rs b/src/packet/event_packet.rs index b90129e..cb28f60 100644 --- a/src/packet/event_packet.rs +++ b/src/packet/event_packet.rs @@ -44,6 +44,8 @@ pub enum MidiPacketParsingError { InvalidNote(u8), /// Invalid cable number. InvalidCableNumber(u8), + /// Invalid code index number. + InvalidCodeIndexNumber(u8), /// Invalid event type. InvalidEventType(u8), /// Missing data packet. From 43b397945936325cf1dbcc209e51321aebdfc637 Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Thu, 19 Dec 2024 14:08:00 +0100 Subject: [PATCH 27/67] Made wrapped values of error tuple structs public --- src/data/u4.rs | 2 +- src/data/u7.rs | 2 +- src/message/channel.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/data/u4.rs b/src/data/u4.rs index 5eca255..ac32374 100644 --- a/src/data/u4.rs +++ b/src/data/u4.rs @@ -6,7 +6,7 @@ use core::convert::TryFrom; pub struct U4(u8); /// Error representing that this value is not a valid u4 -pub struct InvalidU4(u8); +pub struct InvalidU4(pub u8); impl TryFrom for U4 { type Error = InvalidU4; diff --git a/src/data/u7.rs b/src/data/u7.rs index 3a57eaa..846fb04 100644 --- a/src/data/u7.rs +++ b/src/data/u7.rs @@ -8,7 +8,7 @@ use core::convert::TryFrom; pub struct U7(pub(crate) u8); /// Error representing that this value is not a valid u7 -pub struct InvalidU7(u8); +pub struct InvalidU7(pub u8); impl TryFrom for U7 { type Error = InvalidU7; diff --git a/src/message/channel.rs b/src/message/channel.rs index a23e8ab..abb447b 100644 --- a/src/message/channel.rs +++ b/src/message/channel.rs @@ -44,7 +44,7 @@ pub enum Channel { } /// Error indicating an invalid MIDI channel. -pub struct InvalidChannel(u8); +pub struct InvalidChannel(pub u8); impl TryFrom for Channel { type Error = InvalidChannel; From 771dffb7ed0e9a108e129bebe67578468a164c36 Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Thu, 19 Dec 2024 14:14:16 +0100 Subject: [PATCH 28/67] Upgraded edition to 2021 --- CHANGELOG.md | 1 + Cargo.toml | 2 +- src/data/u4.rs | 2 -- src/data/u7.rs | 1 - src/message/channel.rs | 2 -- src/message/mod.rs | 3 --- src/packet/cable_number.rs | 2 -- src/packet/code_index_number.rs | 2 -- src/packet/event_packet.rs | 2 -- src/packet/reader.rs | 1 - 10 files changed, 2 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b88b88c..e6b85db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Changed +- Set edition to 2021. - Renamed `MidiClass::send_message` function to `MidiClass::send_packet`. - Renamed `midi_device` module to `class`. - Renamed `usb_midi` module to `packet` and moved it into crate root. diff --git a/Cargo.toml b/Cargo.toml index fea8c2c..157b46e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ authors = [ "Florian Jung ", "Oliver Rockstedt ", ] -edition = "2018" +edition = "2021" description = "A USB MIDI implementation for usb-device." homepage = "https://github.com/rust-embedded-community/usbd-midi" repository = "https://github.com/rust-embedded-community/usbd-midi" diff --git a/src/data/u4.rs b/src/data/u4.rs index ac32374..10c6819 100644 --- a/src/data/u4.rs +++ b/src/data/u4.rs @@ -1,7 +1,5 @@ //! A primitive value with 4-bit length. -use core::convert::TryFrom; - /// A primitive value that can be from 0-0x0F pub struct U4(u8); diff --git a/src/data/u7.rs b/src/data/u7.rs index 846fb04..278d15c 100644 --- a/src/data/u7.rs +++ b/src/data/u7.rs @@ -1,7 +1,6 @@ //! A primitive value with 7-bit length. use crate::data::from_traits::{FromClamped, FromOverFlow}; -use core::convert::TryFrom; /// A primitive value that can be from 0-0x7F #[derive(Debug, Clone, Eq, PartialEq)] diff --git a/src/message/channel.rs b/src/message/channel.rs index abb447b..9704044 100644 --- a/src/message/channel.rs +++ b/src/message/channel.rs @@ -1,7 +1,5 @@ //! Enum representing the MIDI channel. -use core::convert::TryFrom; - /// The Channel is a value ranging from 0x0 to 0xF. /// /// This is a standard midi concept. diff --git a/src/message/mod.rs b/src/message/mod.rs index fd4c640..8486f05 100644 --- a/src/message/mod.rs +++ b/src/message/mod.rs @@ -5,8 +5,6 @@ pub mod control_function; pub mod notes; pub mod raw; -use core::convert::TryFrom; - use crate::data::from_traits::FromClamped; use crate::data::u4::U4; use crate::data::u7::U7; @@ -219,7 +217,6 @@ mod tests { use crate::message::Message; use crate::packet::cable_number::CableNumber::{Cable0, Cable1}; use crate::packet::event_packet::UsbMidiEventPacket; - use core::convert::TryFrom; macro_rules! decode_message_test { ($($id:ident:$value:expr,)*) => { diff --git a/src/packet/cable_number.rs b/src/packet/cable_number.rs index 44f4a92..ef67a4c 100644 --- a/src/packet/cable_number.rs +++ b/src/packet/cable_number.rs @@ -1,7 +1,5 @@ //! Enum representing the cable number of a packet. -use core::convert::TryFrom; - use crate::data::u4::U4; use crate::packet::event_packet::MidiPacketParsingError; diff --git a/src/packet/code_index_number.rs b/src/packet/code_index_number.rs index 34d8ffa..deb95c9 100644 --- a/src/packet/code_index_number.rs +++ b/src/packet/code_index_number.rs @@ -1,7 +1,5 @@ //! Enum representing the code index number of a packet. -use core::convert::TryFrom; - use crate::data::u4::U4; use crate::packet::event_packet::MidiPacketParsingError; diff --git a/src/packet/event_packet.rs b/src/packet/event_packet.rs index cb28f60..36886a2 100644 --- a/src/packet/event_packet.rs +++ b/src/packet/event_packet.rs @@ -1,7 +1,5 @@ //! Representation of a USB MIDI event packet. -use core::convert::{TryFrom, TryInto}; - use crate::data::u4::U4; use crate::message::raw::{Payload, Raw}; use crate::message::Message; diff --git a/src/packet/reader.rs b/src/packet/reader.rs index 6c6df3c..3543b9b 100644 --- a/src/packet/reader.rs +++ b/src/packet/reader.rs @@ -2,7 +2,6 @@ use crate::class::{MAX_PACKET_SIZE, MIDI_PACKET_SIZE}; use crate::packet::event_packet::{MidiPacketParsingError, UsbMidiEventPacket}; -use core::convert::TryFrom; /// Packet reader with internal buffer for received message. pub struct MidiPacketBufferReader<'a> { From c7c91f17f57355b7b5b41e4ee2d56729746dd524 Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Thu, 19 Dec 2024 14:15:49 +0100 Subject: [PATCH 29/67] Fixed clippy warning --- src/packet/event_packet.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/packet/event_packet.rs b/src/packet/event_packet.rs index 36886a2..2af4b01 100644 --- a/src/packet/event_packet.rs +++ b/src/packet/event_packet.rs @@ -89,7 +89,7 @@ impl UsbMidiEventPacket { /// Returns the raw bytes as owned array. pub fn to_raw_bytes(&self) -> [u8; 4] { - self.raw.clone() + self.raw } /// Creates a packet from a slice of message bytes. From 98d0626dc8105dca6b7a5c91caf173429ba09eb1 Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Thu, 19 Dec 2024 14:48:41 +0100 Subject: [PATCH 30/67] Converted CodeIndexNumber struct to enum --- CHANGELOG.md | 1 + src/message/mod.rs | 14 ++-- src/packet/code_index_number.rs | 119 ++++++++++++++++++++------------ 3 files changed, 81 insertions(+), 53 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e6b85db..379abee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Moved `byte` submodules into `data` module. - Consolidated separate `InvalidCableNumber` struct into `MidiPacketParsingError`. - Consolidated separate `InvalidCodeIndexNumber` struct into `MidiPacketParsingError`. +- Converted `CodeIndexNumber` struct to enum. - Moved descriptor constants into class module and made them private. ### Removed diff --git a/src/message/mod.rs b/src/message/mod.rs index 8486f05..0b582ac 100644 --- a/src/message/mod.rs +++ b/src/message/mod.rs @@ -177,13 +177,13 @@ impl Message { /// Returns the code index number for a message. pub fn code_index_number(&self) -> CodeIndexNumber { match self { - Self::NoteOn(_, _, _) => CodeIndexNumber::NOTE_ON, - Self::NoteOff(_, _, _) => CodeIndexNumber::NOTE_OFF, - Self::ChannelAftertouch(_, _) => CodeIndexNumber::CHANNEL_PRESSURE, - Self::PitchWheelChange(_, _, _) => CodeIndexNumber::PITCHBEND_CHANGE, - Self::PolyphonicAftertouch(_, _, _) => CodeIndexNumber::POLY_KEYPRESS, - Self::ProgramChange(_, _) => CodeIndexNumber::PROGRAM_CHANGE, - Self::ControlChange(_, _, _) => CodeIndexNumber::CONTROL_CHANGE, + Self::NoteOn(_, _, _) => CodeIndexNumber::NoteOn, + Self::NoteOff(_, _, _) => CodeIndexNumber::NoteOff, + Self::ChannelAftertouch(_, _) => CodeIndexNumber::ChannelPressure, + Self::PitchWheelChange(_, _, _) => CodeIndexNumber::PitchBendChange, + Self::PolyphonicAftertouch(_, _, _) => CodeIndexNumber::PolyKeyPress, + Self::ProgramChange(_, _) => CodeIndexNumber::ProgramChange, + Self::ControlChange(_, _, _) => CodeIndexNumber::ControlChange, } } } diff --git a/src/packet/code_index_number.rs b/src/packet/code_index_number.rs index deb95c9..cb2c2cc 100644 --- a/src/packet/code_index_number.rs +++ b/src/packet/code_index_number.rs @@ -4,62 +4,89 @@ use crate::data::u4::U4; use crate::packet::event_packet::MidiPacketParsingError; /// The Code Index Number(CIN) indicates the classification -/// of the bytes in the MIDI_x fields -pub struct CodeIndexNumber(u8); +/// of the bytes in the MIDI_x fields. +/// Code Index Number classifications. +#[derive(Debug, Clone, Copy, Eq, PartialEq)] +#[repr(u8)] +pub enum CodeIndexNumber { + /// Miscellaneous function codes. Reserved for future extensions. + MiscFunction = 0x00, + /// Cable events. Reserved for future expansion. + CableEvents = 0x1, + /// Two-byte System Common messages like MTC, SongSelect, etc. + SystemCommon2Bytes = 0x2, + /// Three-byte System Common messages like SPP, etc. + SystemCommon3Bytes = 0x3, + /// SysEx starts or continues. + SysexStartsOrContinues = 0x4, + /// Single-byte System Common Message or SysEx ends with following single byte. + SystemCommon1Byte = 0x5, + /// SysEx ends with following two bytes. + SysexEnds2Bytes = 0x6, + /// SysEx ends with following three bytes. + SysexEnds3Bytes = 0x7, + /// Note-off. + NoteOff = 0x8, + /// Note-on. + NoteOn = 0x9, + /// Poly-KeyPress. + PolyKeyPress = 0xA, + /// Control Change. + ControlChange = 0xB, + /// Program Change. + ProgramChange = 0xC, + /// Channel Pressure. + ChannelPressure = 0xD, + /// PitchBend Change. + PitchBendChange = 0xE, + /// Single Byte. + SingleByte = 0xF, +} impl TryFrom for CodeIndexNumber { type Error = MidiPacketParsingError; fn try_from(value: u8) -> Result { - if value > 0xF { - Err(MidiPacketParsingError::InvalidCodeIndexNumber(value)) - } else { - Ok(CodeIndexNumber(value)) + match value { + x if x == CodeIndexNumber::MiscFunction as u8 => Ok(CodeIndexNumber::MiscFunction), + x if x == CodeIndexNumber::CableEvents as u8 => Ok(CodeIndexNumber::CableEvents), + x if x == CodeIndexNumber::SystemCommon2Bytes as u8 => { + Ok(CodeIndexNumber::SystemCommon2Bytes) + } + x if x == CodeIndexNumber::SystemCommon3Bytes as u8 => { + Ok(CodeIndexNumber::SystemCommon3Bytes) + } + x if x == CodeIndexNumber::SysexStartsOrContinues as u8 => { + Ok(CodeIndexNumber::SysexStartsOrContinues) + } + x if x == CodeIndexNumber::SystemCommon1Byte as u8 => { + Ok(CodeIndexNumber::SystemCommon1Byte) + } + x if x == CodeIndexNumber::SysexEnds2Bytes as u8 => { + Ok(CodeIndexNumber::SysexEnds2Bytes) + } + x if x == CodeIndexNumber::SysexEnds3Bytes as u8 => { + Ok(CodeIndexNumber::SysexEnds3Bytes) + } + x if x == CodeIndexNumber::NoteOff as u8 => Ok(CodeIndexNumber::NoteOff), + x if x == CodeIndexNumber::NoteOn as u8 => Ok(CodeIndexNumber::NoteOn), + x if x == CodeIndexNumber::PolyKeyPress as u8 => Ok(CodeIndexNumber::PolyKeyPress), + x if x == CodeIndexNumber::ControlChange as u8 => Ok(CodeIndexNumber::ControlChange), + x if x == CodeIndexNumber::ProgramChange as u8 => Ok(CodeIndexNumber::ProgramChange), + x if x == CodeIndexNumber::ChannelPressure as u8 => { + Ok(CodeIndexNumber::ChannelPressure) + } + x if x == CodeIndexNumber::PitchBendChange as u8 => { + Ok(CodeIndexNumber::PitchBendChange) + } + x if x == CodeIndexNumber::SingleByte as u8 => Ok(CodeIndexNumber::SingleByte), + _ => Err(MidiPacketParsingError::InvalidCodeIndexNumber(value)), } } } impl From for U4 { fn from(value: CodeIndexNumber) -> U4 { - U4::from_overflowing_u8(value.0) + U4::from_overflowing_u8(value as u8) } } - -impl CodeIndexNumber { - /// Miscellaneous function codes. Reserved for future extensions. - pub const MISC_FUNCTION: CodeIndexNumber = CodeIndexNumber(0x00); - /// Cable events. Reserved for future expansion. - pub const CABLE_EVENTS: CodeIndexNumber = CodeIndexNumber(0x1); - /// Two-byte System Common messages like MTC, SongSelect, etc. - pub const SYSTEM_COMMON_LEN2: CodeIndexNumber = CodeIndexNumber(0x2); - /// Three-byte System Common messages like SPP, etc. - pub const SYSTEM_COMMON_LEN3: CodeIndexNumber = CodeIndexNumber(0x3); - /// SysEx starts. - pub const SYSEX_STARTS: CodeIndexNumber = CodeIndexNumber(0x4); - /// SysEx continues. - pub const SYSEX_CONTINUES: CodeIndexNumber = CodeIndexNumber::SYSEX_STARTS; - /// Single-byte System Common Message or SysEx ends with following single byte. - pub const SYSTEM_COMMON_LEN1: CodeIndexNumber = CodeIndexNumber(0x5); - /// SysEx ends with the following byte. - pub const SYSEX_ENDS_NEXT1: CodeIndexNumber = CodeIndexNumber::SYSTEM_COMMON_LEN1; - /// SysEx ends with following two bytes. - pub const SYSEX_ENDS_NEXT2: CodeIndexNumber = CodeIndexNumber(0x6); - /// SysEx ends with following three bytes. - pub const SYSEX_ENDS_NEXT3: CodeIndexNumber = CodeIndexNumber(0x7); - /// Note - Off - pub const NOTE_OFF: CodeIndexNumber = CodeIndexNumber(0x8); - /// Note - On - pub const NOTE_ON: CodeIndexNumber = CodeIndexNumber(0x9); - /// Poly-KeyPress - pub const POLY_KEYPRESS: CodeIndexNumber = CodeIndexNumber(0xA); - /// Control Change - pub const CONTROL_CHANGE: CodeIndexNumber = CodeIndexNumber(0xB); - /// Program Change - pub const PROGRAM_CHANGE: CodeIndexNumber = CodeIndexNumber(0xC); - /// Channel Pressure - pub const CHANNEL_PRESSURE: CodeIndexNumber = CodeIndexNumber(0xD); - /// Pitch Bend Change - pub const PITCHBEND_CHANGE: CodeIndexNumber = CodeIndexNumber(0xE); - /// Single Byte - pub const SINGLE_BYTE: CodeIndexNumber = CodeIndexNumber(0xF); -} From 494762606bf2901423afc922b5790e661d024c9d Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Thu, 19 Dec 2024 15:22:25 +0100 Subject: [PATCH 31/67] Added CodeIndexNumber::event_size function --- CHANGELOG.md | 1 + src/packet/code_index_number.rs | 25 +++++++++++++++++++++++++ src/packet/event_packet.rs | 13 +++++-------- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 379abee..e26f9e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - `TryFrom<&UsbMidiEventPacket>` implementation for `Message` type. - `Message::into_packet` function. - `Message::code_index_number` function. +- `CodeIndexNumber::event_size()` function. - Re-exports of common items in crate root. ### Changed diff --git a/src/packet/code_index_number.rs b/src/packet/code_index_number.rs index cb2c2cc..d8eaaad 100644 --- a/src/packet/code_index_number.rs +++ b/src/packet/code_index_number.rs @@ -90,3 +90,28 @@ impl From for U4 { U4::from_overflowing_u8(value as u8) } } + +impl CodeIndexNumber { + /// Returns the size of the MIDI_x event in bytes. + pub fn event_size(&self) -> usize { + match self { + Self::SystemCommon1Byte | Self::SingleByte => 1, + Self::SystemCommon2Bytes + | Self::SysexEnds2Bytes + | Self::ProgramChange + | Self::ChannelPressure => 2, + Self::SystemCommon3Bytes + | Self::SysexEnds3Bytes + | Self::SysexStartsOrContinues + | Self::NoteOff + | Self::NoteOn + | Self::PolyKeyPress + | Self::ControlChange + | Self::PitchBendChange => 3, + + // These variants are reserved for future use. + // We assume the maximum length of 3 bytes so that no data can get lost. + Self::MiscFunction | Self::CableEvents => 3, + } + } +} diff --git a/src/packet/event_packet.rs b/src/packet/event_packet.rs index 2af4b01..e7aa145 100644 --- a/src/packet/event_packet.rs +++ b/src/packet/event_packet.rs @@ -4,6 +4,7 @@ use crate::data::u4::U4; use crate::message::raw::{Payload, Raw}; use crate::message::Message; use crate::packet::cable_number::CableNumber; +use crate::packet::code_index_number::CodeIndexNumber; /// A packet that communicates with the host. /// @@ -65,21 +66,17 @@ impl TryFrom<&[u8]> for UsbMidiEventPacket { impl UsbMidiEventPacket { /// Returns the cable number. pub fn cable_number(&self) -> CableNumber { - let raw_cable_number = self.raw.first().unwrap() >> 4; + let raw_cable_number = self.raw[0] >> 4; CableNumber::try_from(raw_cable_number).unwrap() } /// Returns a slice to the message bytes. The length is dependent on the message type. pub fn as_message_bytes(&self) -> &[u8] { - let r = Raw::from(Message::try_from(self).unwrap()); - let length = match r.payload { - Payload::Empty => 1, - Payload::SingleByte(_) => 2, - Payload::DoubleByte(_, _) => 3, - }; + let cin = CodeIndexNumber::try_from(self.raw[0] & 0x0F).unwrap(); + let size = cin.event_size(); - &self.raw[1..1 + length] + &self.raw[1..1 + size] } /// Returns a reference to the raw bytes. From 1be9d58df25fcd8cbd5a800e9396ad0b4d7e3cbb Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Thu, 19 Dec 2024 15:28:18 +0100 Subject: [PATCH 32/67] Simplified From for [u8; 4] implementation --- src/packet/event_packet.rs | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/src/packet/event_packet.rs b/src/packet/event_packet.rs index e7aa145..c50a121 100644 --- a/src/packet/event_packet.rs +++ b/src/packet/event_packet.rs @@ -1,7 +1,5 @@ //! Representation of a USB MIDI event packet. -use crate::data::u4::U4; -use crate::message::raw::{Payload, Raw}; use crate::message::Message; use crate::packet::cable_number::CableNumber; use crate::packet::code_index_number::CodeIndexNumber; @@ -18,19 +16,7 @@ pub struct UsbMidiEventPacket { impl From for [u8; 4] { fn from(value: UsbMidiEventPacket) -> [u8; 4] { - let cable_number = U4::from(value.cable_number()); - let message = Message::try_from(&value).unwrap(); - let index_number = { U4::from(message.code_index_number()) }; - let header = U4::combine(cable_number, index_number); - - let raw_midi = Raw::from(message); - let status = raw_midi.status; - - match raw_midi.payload { - Payload::Empty => [header, status, 0, 0], - Payload::SingleByte(byte) => [header, status, byte.into(), 0], - Payload::DoubleByte(byte1, byte2) => [header, status, byte1.into(), byte2.into()], - } + value.raw } } From 8fb0bfcc72564716d8218763be65f186dce8cd0f Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Thu, 19 Dec 2024 15:42:11 +0100 Subject: [PATCH 33/67] Added default variant for CableNumber --- CHANGELOG.md | 1 + src/packet/cable_number.rs | 3 ++- src/packet/event_packet.rs | 3 ++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e26f9e9..3cc4d03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - `Message::into_packet` function. - `Message::code_index_number` function. - `CodeIndexNumber::event_size()` function. +- `CableNumber::Cable0` as default value. - Re-exports of common items in crate root. ### Changed diff --git a/src/packet/cable_number.rs b/src/packet/cable_number.rs index ef67a4c..a4adea7 100644 --- a/src/packet/cable_number.rs +++ b/src/packet/cable_number.rs @@ -7,9 +7,10 @@ use crate::packet::event_packet::MidiPacketParsingError; /// indicating the number assignment of the Embedded MIDI Jack associated /// with the endpoint that is transferring the data #[allow(missing_docs)] -#[derive(Debug, Clone, Copy, Eq, PartialEq)] +#[derive(Debug, Default, Clone, Copy, Eq, PartialEq)] #[repr(u8)] pub enum CableNumber { + #[default] Cable0 = 0x0, Cable1 = 0x1, Cable2 = 0x2, diff --git a/src/packet/event_packet.rs b/src/packet/event_packet.rs index c50a121..3728834 100644 --- a/src/packet/event_packet.rs +++ b/src/packet/event_packet.rs @@ -54,7 +54,8 @@ impl UsbMidiEventPacket { pub fn cable_number(&self) -> CableNumber { let raw_cable_number = self.raw[0] >> 4; - CableNumber::try_from(raw_cable_number).unwrap() + // Unwrap cannot fail because of limited `raw_cable_number` value range. + CableNumber::try_from(raw_cable_number).unwrap_or_default() } /// Returns a slice to the message bytes. The length is dependent on the message type. From d2778997d2c74ffa35aad856219bb4aff29fbf54 Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Thu, 19 Dec 2024 15:52:48 +0100 Subject: [PATCH 34/67] Get rid of unwrap() in UsbMidiEventPacket implementation --- src/packet/event_packet.rs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/packet/event_packet.rs b/src/packet/event_packet.rs index 3728834..64c3e00 100644 --- a/src/packet/event_packet.rs +++ b/src/packet/event_packet.rs @@ -54,16 +54,23 @@ impl UsbMidiEventPacket { pub fn cable_number(&self) -> CableNumber { let raw_cable_number = self.raw[0] >> 4; - // Unwrap cannot fail because of limited `raw_cable_number` value range. + // Unwrap can't fail because of limited `raw_cable_number` value range. CableNumber::try_from(raw_cable_number).unwrap_or_default() } /// Returns a slice to the message bytes. The length is dependent on the message type. pub fn as_message_bytes(&self) -> &[u8] { - let cin = CodeIndexNumber::try_from(self.raw[0] & 0x0F).unwrap(); - let size = cin.event_size(); + let raw_cin = self.raw[0] & 0x0F; - &self.raw[1..1 + size] + match CodeIndexNumber::try_from(raw_cin) { + Ok(cin) => { + let size = cin.event_size(); + &self.raw[1..1 + size] + } + + // Can't happen because of limited `raw_cin` value range. + Err(_) => &[], + } } /// Returns a reference to the raw bytes. From d6542be6a9d90f2d85ba0b0490bb919590e5f996 Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Thu, 19 Dec 2024 16:27:26 +0100 Subject: [PATCH 35/67] Updated the README example --- README.md | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index bf585d7..20c859c 100644 --- a/README.md +++ b/README.md @@ -15,11 +15,10 @@ Turn on an LED as long as note C2 is pressed. The example only shows the hardwar ```rust use usb_device::prelude::*; use usbd_midi::{ - data::{ - midi::{channel::Channel, message::Message, notes::Note}, - usb_midi::midi_packet_reader::MidiPacketBufferReader, - }, - midi_device::MidiClass, + message::{channel::Channel, notes::Note}, + Message, + MidiClass, + MidiPacketBufferReader, }; // Prerequisites, must be setup according to the used board. @@ -29,15 +28,15 @@ let usb_bus = todo!(); // Must be of type `usb_device::bus::UsbBusAllocator`. // Create a MIDI class with 1 input and 1 output jack. let mut midi = MidiClass::new(&usb_bus, 1, 1).unwrap(); - let mut usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x16c0, 0x5e4)) - .device_class(0) - .device_sub_class(0) - .strings(&[StringDescriptors::default() - .manufacturer("Music Company") - .product("MIDI Device") - .serial_number("12345678")]) - .unwrap() - .build(); +let mut usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x16c0, 0x5e4)) + .device_class(0) + .device_sub_class(0) + .strings(&[StringDescriptors::default() + .manufacturer("Music Company") + .product("MIDI Device") + .serial_number("12345678")]) + .unwrap() + .build(); loop { if !usb_dev.poll(&mut [&mut midi]) { From cadcc5bb500de4b57fbbdfaa8b9b9060c2b36786 Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Thu, 19 Dec 2024 18:44:38 +0100 Subject: [PATCH 36/67] Added CodeIndexNumber::try_from_event function --- CHANGELOG.md | 3 ++- src/packet/code_index_number.rs | 28 ++++++++++++++++++++++++++++ src/packet/event_packet.rs | 16 ++++++++++++---- 3 files changed, 42 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3cc4d03..61c7faf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,7 +17,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - `TryFrom<&UsbMidiEventPacket>` implementation for `Message` type. - `Message::into_packet` function. - `Message::code_index_number` function. -- `CodeIndexNumber::event_size()` function. +- `CodeIndexNumber::try_from_event` function. +- `CodeIndexNumber::event_size` function. - `CableNumber::Cable0` as default value. - Re-exports of common items in crate root. diff --git a/src/packet/code_index_number.rs b/src/packet/code_index_number.rs index d8eaaad..98da2a5 100644 --- a/src/packet/code_index_number.rs +++ b/src/packet/code_index_number.rs @@ -92,6 +92,34 @@ impl From for U4 { } impl CodeIndexNumber { + /// Creates a new number from a MIDI event. + pub fn try_from_event(event: &[u8]) -> Result { + let Some(status) = event.first() else { + return Err(MidiPacketParsingError::EmptyEvent); + }; + + if *status < 0xF0 { + match status & 0xF0 { + 0x80 => Ok(Self::NoteOff), + 0x90 => Ok(Self::NoteOn), + 0xA0 => Ok(Self::PolyKeyPress), + 0xB0 => Ok(Self::ControlChange), + 0xC0 => Ok(Self::ProgramChange), + 0xD0 => Ok(Self::ChannelPressure), + 0xE0 => Ok(Self::PitchBendChange), + _ => Err(MidiPacketParsingError::InvalidEventStatus), + } + } else { + match status { + 0xF1 | 0xF3 => Ok(Self::SystemCommon2Bytes), + 0xF2 => Ok(Self::SystemCommon3Bytes), + 0xF6 => Ok(Self::SystemCommon1Byte), + 0xF8 | 0xFA | 0xFB | 0xFC | 0xFE | 0xFF => Ok(Self::SingleByte), + _ => Err(MidiPacketParsingError::InvalidEventStatus), + } + } + } + /// Returns the size of the MIDI_x event in bytes. pub fn event_size(&self) -> usize { match self { diff --git a/src/packet/event_packet.rs b/src/packet/event_packet.rs index 64c3e00..21d93ca 100644 --- a/src/packet/event_packet.rs +++ b/src/packet/event_packet.rs @@ -1,6 +1,5 @@ //! Representation of a USB MIDI event packet. -use crate::message::Message; use crate::packet::cable_number::CableNumber; use crate::packet::code_index_number::CodeIndexNumber; @@ -35,6 +34,10 @@ pub enum MidiPacketParsingError { InvalidEventType(u8), /// Missing data packet. MissingDataPacket, + /// Empty event. + EmptyEvent, + /// Invalid event status. + InvalidEventStatus, } impl TryFrom<&[u8]> for UsbMidiEventPacket { @@ -45,7 +48,7 @@ impl TryFrom<&[u8]> for UsbMidiEventPacket { return Err(MidiPacketParsingError::InvalidPacket); }; - Ok(UsbMidiEventPacket { raw }) + Ok(Self { raw }) } } @@ -88,8 +91,13 @@ impl UsbMidiEventPacket { cable: CableNumber, bytes: &[u8], ) -> Result { - let message = Message::try_from(bytes)?; + let cin = CodeIndexNumber::try_from_event(bytes)?; + let event_size = cin.event_size(); - Ok(message.into_packet(cable)) + let mut raw = [0; 4]; + raw[0] = (cable as u8) << 4 | cin as u8; + raw[1..1 + event_size].copy_from_slice(&bytes[..event_size]); + + Ok(Self { raw }) } } From 7ea917ef02a98876b2fe939ed8eaf466127928f3 Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Thu, 19 Dec 2024 19:44:37 +0100 Subject: [PATCH 37/67] Feature-gated the message module --- CHANGELOG.md | 2 ++ Cargo.toml | 4 ++++ src/lib.rs | 8 ++++++-- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 61c7faf..b103d25 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] +**NOTE:** The `message` module containing the `Message` struct and related types is now gated behind the `message-types` feature. This feature is enabled by default. + ### Added - `UsbMidiEventPacket::cable_number` function. diff --git a/Cargo.toml b/Cargo.toml index 157b46e..c743e8b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,10 @@ license = "MIT" categories = ["no-std", "embedded", "hardware-support"] keywords = ["usb", "midi"] +[features] +default = ["message-types"] +message-types = [] + [dependencies] usb-device = "0.3" diff --git a/src/lib.rs b/src/lib.rs index 0c13777..446561e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,11 +4,15 @@ pub mod class; pub mod data; -pub mod message; pub mod packet; +#[cfg(feature = "message-types")] +pub mod message; + pub use crate::class::MidiClass; -pub use crate::message::Message; pub use crate::packet::cable_number::CableNumber; pub use crate::packet::event_packet::UsbMidiEventPacket; pub use crate::packet::reader::MidiPacketBufferReader; + +#[cfg(feature = "message-types")] +pub use crate::message::Message; From 8e9eaf191bcf0725d9dd942500b6f820cfb9b463 Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Sat, 21 Dec 2024 10:22:21 +0100 Subject: [PATCH 38/67] Moved code from event_packet.rs into packet module root --- CHANGELOG.md | 2 +- src/class.rs | 3 +- src/lib.rs | 2 +- src/message/mod.rs | 4 +- src/packet/cable_number.rs | 2 +- src/packet/code_index_number.rs | 2 +- src/packet/event_packet.rs | 103 -------------------------------- src/packet/mod.rs | 103 +++++++++++++++++++++++++++++++- src/packet/reader.rs | 2 +- 9 files changed, 111 insertions(+), 112 deletions(-) delete mode 100644 src/packet/event_packet.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index b103d25..96e1dcf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,7 +31,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Renamed `midi_device` module to `class`. - Renamed `usb_midi` module to `packet` and moved it into crate root. - Renamed `midi_packet_reader` module to `reader`. -- Renamed `usb_midi_event_packet` module to `event_packet`. +- Moved `usb_midi_event_packet` code into new `packet` module. - Moved `channel` and `notes` modules into `message` module. - Moved `message` module to crate root. - Moved `byte` submodules into `data` module. diff --git a/src/class.rs b/src/class.rs index 9630422..9248130 100644 --- a/src/class.rs +++ b/src/class.rs @@ -1,9 +1,10 @@ //! Contains the class implementation. -use crate::packet::event_packet::{MidiPacketParsingError, UsbMidiEventPacket}; use usb_device::class_prelude::*; use usb_device::Result; +use crate::packet::{MidiPacketParsingError, UsbMidiEventPacket}; + // Constants for use in descriptors. const USB_AUDIO_CLASS: u8 = 0x01; const USB_AUDIOCONTROL_SUBCLASS: u8 = 0x01; diff --git a/src/lib.rs b/src/lib.rs index 446561e..fb3219f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,8 +11,8 @@ pub mod message; pub use crate::class::MidiClass; pub use crate::packet::cable_number::CableNumber; -pub use crate::packet::event_packet::UsbMidiEventPacket; pub use crate::packet::reader::MidiPacketBufferReader; +pub use crate::packet::UsbMidiEventPacket; #[cfg(feature = "message-types")] pub use crate::message::Message; diff --git a/src/message/mod.rs b/src/message/mod.rs index 0b582ac..346578e 100644 --- a/src/message/mod.rs +++ b/src/message/mod.rs @@ -14,7 +14,7 @@ use crate::message::notes::Note; use crate::message::raw::{Payload, Raw}; use crate::packet::cable_number::CableNumber; use crate::packet::code_index_number::CodeIndexNumber; -use crate::packet::event_packet::{MidiPacketParsingError, UsbMidiEventPacket}; +use crate::packet::{MidiPacketParsingError, UsbMidiEventPacket}; type Velocity = U7; @@ -216,7 +216,7 @@ mod tests { use crate::message::notes::Note; use crate::message::Message; use crate::packet::cable_number::CableNumber::{Cable0, Cable1}; - use crate::packet::event_packet::UsbMidiEventPacket; + use crate::packet::UsbMidiEventPacket; macro_rules! decode_message_test { ($($id:ident:$value:expr,)*) => { diff --git a/src/packet/cable_number.rs b/src/packet/cable_number.rs index a4adea7..78cb33c 100644 --- a/src/packet/cable_number.rs +++ b/src/packet/cable_number.rs @@ -1,7 +1,7 @@ //! Enum representing the cable number of a packet. use crate::data::u4::U4; -use crate::packet::event_packet::MidiPacketParsingError; +use crate::packet::MidiPacketParsingError; /// The Cable Number (CN) is a value ranging from 0x0 to 0xF /// indicating the number assignment of the Embedded MIDI Jack associated diff --git a/src/packet/code_index_number.rs b/src/packet/code_index_number.rs index 98da2a5..65d326c 100644 --- a/src/packet/code_index_number.rs +++ b/src/packet/code_index_number.rs @@ -1,7 +1,7 @@ //! Enum representing the code index number of a packet. use crate::data::u4::U4; -use crate::packet::event_packet::MidiPacketParsingError; +use crate::packet::MidiPacketParsingError; /// The Code Index Number(CIN) indicates the classification /// of the bytes in the MIDI_x fields. diff --git a/src/packet/event_packet.rs b/src/packet/event_packet.rs deleted file mode 100644 index 21d93ca..0000000 --- a/src/packet/event_packet.rs +++ /dev/null @@ -1,103 +0,0 @@ -//! Representation of a USB MIDI event packet. - -use crate::packet::cable_number::CableNumber; -use crate::packet::code_index_number::CodeIndexNumber; - -/// A packet that communicates with the host. -/// -/// Currently supported is sending the specified normal midi -/// message over the supplied cable number -#[derive(Debug, Clone, Eq, PartialEq)] -pub struct UsbMidiEventPacket { - /// Raw packet data. - raw: [u8; 4], -} - -impl From for [u8; 4] { - fn from(value: UsbMidiEventPacket) -> [u8; 4] { - value.raw - } -} - -/// Error variants for parsing the packet. -#[derive(Debug)] -pub enum MidiPacketParsingError { - /// Invalid packet. - InvalidPacket, - /// Invalid note. - InvalidNote(u8), - /// Invalid cable number. - InvalidCableNumber(u8), - /// Invalid code index number. - InvalidCodeIndexNumber(u8), - /// Invalid event type. - InvalidEventType(u8), - /// Missing data packet. - MissingDataPacket, - /// Empty event. - EmptyEvent, - /// Invalid event status. - InvalidEventStatus, -} - -impl TryFrom<&[u8]> for UsbMidiEventPacket { - type Error = MidiPacketParsingError; - - fn try_from(value: &[u8]) -> Result { - let Ok(raw) = value.try_into() else { - return Err(MidiPacketParsingError::InvalidPacket); - }; - - Ok(Self { raw }) - } -} - -impl UsbMidiEventPacket { - /// Returns the cable number. - pub fn cable_number(&self) -> CableNumber { - let raw_cable_number = self.raw[0] >> 4; - - // Unwrap can't fail because of limited `raw_cable_number` value range. - CableNumber::try_from(raw_cable_number).unwrap_or_default() - } - - /// Returns a slice to the message bytes. The length is dependent on the message type. - pub fn as_message_bytes(&self) -> &[u8] { - let raw_cin = self.raw[0] & 0x0F; - - match CodeIndexNumber::try_from(raw_cin) { - Ok(cin) => { - let size = cin.event_size(); - &self.raw[1..1 + size] - } - - // Can't happen because of limited `raw_cin` value range. - Err(_) => &[], - } - } - - /// Returns a reference to the raw bytes. - pub fn as_raw_bytes(&self) -> &[u8] { - &self.raw - } - - /// Returns the raw bytes as owned array. - pub fn to_raw_bytes(&self) -> [u8; 4] { - self.raw - } - - /// Creates a packet from a slice of message bytes. - pub fn try_from_message_bytes( - cable: CableNumber, - bytes: &[u8], - ) -> Result { - let cin = CodeIndexNumber::try_from_event(bytes)?; - let event_size = cin.event_size(); - - let mut raw = [0; 4]; - raw[0] = (cable as u8) << 4 | cin as u8; - raw[1..1 + event_size].copy_from_slice(&bytes[..event_size]); - - Ok(Self { raw }) - } -} diff --git a/src/packet/mod.rs b/src/packet/mod.rs index 007d310..77cc8b7 100644 --- a/src/packet/mod.rs +++ b/src/packet/mod.rs @@ -2,5 +2,106 @@ pub mod cable_number; pub mod code_index_number; -pub mod event_packet; pub mod reader; + +use crate::packet::cable_number::CableNumber; +use crate::packet::code_index_number::CodeIndexNumber; + +/// A packet that communicates with the host. +/// +/// Currently supported is sending the specified normal midi +/// message over the supplied cable number +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct UsbMidiEventPacket { + /// Raw packet data. + raw: [u8; 4], +} + +impl From for [u8; 4] { + fn from(value: UsbMidiEventPacket) -> [u8; 4] { + value.raw + } +} + +/// Error variants for parsing the packet. +#[derive(Debug)] +pub enum MidiPacketParsingError { + /// Invalid packet. + InvalidPacket, + /// Invalid note. + InvalidNote(u8), + /// Invalid cable number. + InvalidCableNumber(u8), + /// Invalid code index number. + InvalidCodeIndexNumber(u8), + /// Invalid event type. + InvalidEventType(u8), + /// Missing data packet. + MissingDataPacket, + /// Empty event. + EmptyEvent, + /// Invalid event status. + InvalidEventStatus, +} + +impl TryFrom<&[u8]> for UsbMidiEventPacket { + type Error = MidiPacketParsingError; + + fn try_from(value: &[u8]) -> Result { + let Ok(raw) = value.try_into() else { + return Err(MidiPacketParsingError::InvalidPacket); + }; + + Ok(Self { raw }) + } +} + +impl UsbMidiEventPacket { + /// Returns the cable number. + pub fn cable_number(&self) -> CableNumber { + let raw_cable_number = self.raw[0] >> 4; + + // Unwrap can't fail because of limited `raw_cable_number` value range. + CableNumber::try_from(raw_cable_number).unwrap_or_default() + } + + /// Returns a slice to the message bytes. The length is dependent on the message type. + pub fn as_message_bytes(&self) -> &[u8] { + let raw_cin = self.raw[0] & 0x0F; + + match CodeIndexNumber::try_from(raw_cin) { + Ok(cin) => { + let size = cin.event_size(); + &self.raw[1..1 + size] + } + + // Can't happen because of limited `raw_cin` value range. + Err(_) => &[], + } + } + + /// Returns a reference to the raw bytes. + pub fn as_raw_bytes(&self) -> &[u8] { + &self.raw + } + + /// Returns the raw bytes as owned array. + pub fn to_raw_bytes(&self) -> [u8; 4] { + self.raw + } + + /// Creates a packet from a slice of message bytes. + pub fn try_from_message_bytes( + cable: CableNumber, + bytes: &[u8], + ) -> Result { + let cin = CodeIndexNumber::try_from_event(bytes)?; + let event_size = cin.event_size(); + + let mut raw = [0; 4]; + raw[0] = (cable as u8) << 4 | cin as u8; + raw[1..1 + event_size].copy_from_slice(&bytes[..event_size]); + + Ok(Self { raw }) + } +} diff --git a/src/packet/reader.rs b/src/packet/reader.rs index 3543b9b..b29dabe 100644 --- a/src/packet/reader.rs +++ b/src/packet/reader.rs @@ -1,7 +1,7 @@ //! Reader for received packets. use crate::class::{MAX_PACKET_SIZE, MIDI_PACKET_SIZE}; -use crate::packet::event_packet::{MidiPacketParsingError, UsbMidiEventPacket}; +use crate::packet::{MidiPacketParsingError, UsbMidiEventPacket}; /// Packet reader with internal buffer for received message. pub struct MidiPacketBufferReader<'a> { From 1da7e4d4dee84b8bfe721f71fc16fa8fb442bafd Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Sat, 21 Dec 2024 10:28:09 +0100 Subject: [PATCH 39/67] Prevent possible out of bounds access in UsbMidiEventPacket::try_from_message_bytes --- src/packet/mod.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/packet/mod.rs b/src/packet/mod.rs index 77cc8b7..bf1e75a 100644 --- a/src/packet/mod.rs +++ b/src/packet/mod.rs @@ -42,6 +42,8 @@ pub enum MidiPacketParsingError { EmptyEvent, /// Invalid event status. InvalidEventStatus, + /// Invalid event size. + InvalidEventSize, } impl TryFrom<&[u8]> for UsbMidiEventPacket { @@ -98,6 +100,10 @@ impl UsbMidiEventPacket { let cin = CodeIndexNumber::try_from_event(bytes)?; let event_size = cin.event_size(); + if bytes.len() < event_size { + return Err(MidiPacketParsingError::InvalidEventSize); + } + let mut raw = [0; 4]; raw[0] = (cable as u8) << 4 | cin as u8; raw[1..1 + event_size].copy_from_slice(&bytes[..event_size]); From 15d5de07a6cfa82a2574581fe5acaa14829d0145 Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Sat, 21 Dec 2024 10:46:18 +0100 Subject: [PATCH 40/67] Moved from_traits.rs code into parent module --- CHANGELOG.md | 3 ++- src/data/from_traits.rs | 14 -------------- src/data/mod.rs | 14 +++++++++++++- src/data/u7.rs | 2 +- src/message/mod.rs | 2 +- src/message/notes.rs | 2 +- 6 files changed, 18 insertions(+), 19 deletions(-) delete mode 100644 src/data/from_traits.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 96e1dcf..c5203c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,10 +31,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Renamed `midi_device` module to `class`. - Renamed `usb_midi` module to `packet` and moved it into crate root. - Renamed `midi_packet_reader` module to `reader`. -- Moved `usb_midi_event_packet` code into new `packet` module. +- Moved `usb_midi_event_packet` code into parent `packet` module. - Moved `channel` and `notes` modules into `message` module. - Moved `message` module to crate root. - Moved `byte` submodules into `data` module. +- Moved `from_traits` code into parent module. - Consolidated separate `InvalidCableNumber` struct into `MidiPacketParsingError`. - Consolidated separate `InvalidCodeIndexNumber` struct into `MidiPacketParsingError`. - Converted `CodeIndexNumber` struct to enum. diff --git a/src/data/from_traits.rs b/src/data/from_traits.rs deleted file mode 100644 index 50248da..0000000 --- a/src/data/from_traits.rs +++ /dev/null @@ -1,14 +0,0 @@ -//! Traits for type conversions. - -/// Like from, but will conceptually overflow if the value is too big -/// this is useful from going from higher ranges to lower ranges -pub trait FromOverFlow: Sized { - /// Convert with overflowing. - fn from_overflow(_: T) -> Self; -} - -/// Like from, but will clamp the value to a maximum value -pub trait FromClamped: Sized { - /// Convert with clamping. - fn from_clamped(_: T) -> Self; -} diff --git a/src/data/mod.rs b/src/data/mod.rs index fcdd7d3..fd68e9e 100644 --- a/src/data/mod.rs +++ b/src/data/mod.rs @@ -1,5 +1,17 @@ //! Primitives and structures used in USB MIDI data. -pub mod from_traits; pub mod u4; pub mod u7; + +/// Like from, but will conceptually overflow if the value is too big +/// this is useful from going from higher ranges to lower ranges +pub trait FromOverFlow: Sized { + /// Convert with overflowing. + fn from_overflow(_: T) -> Self; +} + +/// Like from, but will clamp the value to a maximum value +pub trait FromClamped: Sized { + /// Convert with clamping. + fn from_clamped(_: T) -> Self; +} diff --git a/src/data/u7.rs b/src/data/u7.rs index 278d15c..7b24cca 100644 --- a/src/data/u7.rs +++ b/src/data/u7.rs @@ -1,6 +1,6 @@ //! A primitive value with 7-bit length. -use crate::data::from_traits::{FromClamped, FromOverFlow}; +use crate::data::{FromClamped, FromOverFlow}; /// A primitive value that can be from 0-0x7F #[derive(Debug, Clone, Eq, PartialEq)] diff --git a/src/message/mod.rs b/src/message/mod.rs index 346578e..10c46dc 100644 --- a/src/message/mod.rs +++ b/src/message/mod.rs @@ -5,9 +5,9 @@ pub mod control_function; pub mod notes; pub mod raw; -use crate::data::from_traits::FromClamped; use crate::data::u4::U4; use crate::data::u7::U7; +use crate::data::FromClamped; use crate::message::channel::Channel; use crate::message::control_function::ControlFunction; use crate::message::notes::Note; diff --git a/src/message/notes.rs b/src/message/notes.rs index 89a38a8..c59925f 100644 --- a/src/message/notes.rs +++ b/src/message/notes.rs @@ -1,7 +1,7 @@ //! Enum representing the MIDI notes. -use crate::data::from_traits::FromOverFlow; use crate::data::u7::U7; +use crate::data::FromOverFlow; use num_enum::TryFromPrimitive; /// A simple enum type that represents all the midi 'notes'. From 248f2fc2a70cc86dc86a24f4b06cebabc9c5b2d6 Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Sat, 21 Dec 2024 10:51:56 +0100 Subject: [PATCH 41/67] Added FromOverFlow and FromClamped implementations for U4 --- CHANGELOG.md | 2 ++ src/data/u4.rs | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c5203c6..1a9a316 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - `CodeIndexNumber::try_from_event` function. - `CodeIndexNumber::event_size` function. - `CableNumber::Cable0` as default value. +- `FromOverFlow for U4` implementation. +- `FromClamped for U4` implementation. - Re-exports of common items in crate root. ### Changed diff --git a/src/data/u4.rs b/src/data/u4.rs index 10c6819..2043856 100644 --- a/src/data/u4.rs +++ b/src/data/u4.rs @@ -1,5 +1,7 @@ //! A primitive value with 4-bit length. +use crate::data::{FromClamped, FromOverFlow}; + /// A primitive value that can be from 0-0x0F pub struct U4(u8); @@ -24,6 +26,23 @@ impl From for u8 { } } +impl FromOverFlow for U4 { + fn from_overflow(value: u8) -> U4 { + const MASK: u8 = 0b0000_1111; + let value = MASK & value; + U4(value) + } +} + +impl FromClamped for U4 { + fn from_clamped(value: u8) -> U4 { + match U4::try_from(value) { + Ok(x) => x, + _ => U4::MAX, + } + } +} + impl U4 { /// Maximum value for the type. pub const MAX: U4 = U4(0x0F); From 0398975df20a31601ee76b16363b1a16a71f23c6 Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Sat, 21 Dec 2024 12:44:57 +0100 Subject: [PATCH 42/67] Renamed term event to payload in several locations --- CHANGELOG.md | 8 +++---- examples/example-esp32s3/src/main.rs | 4 ++-- src/packet/code_index_number.rs | 16 +++++++------- src/packet/mod.rs | 32 ++++++++++++++-------------- 4 files changed, 30 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a9a316..86b2b19 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,15 +12,15 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Added - `UsbMidiEventPacket::cable_number` function. -- `UsbMidiEventPacket::as_message_bytes` function. +- `UsbMidiEventPacket::payload_bytes` function. - `UsbMidiEventPacket::as_raw_bytes` function. - `UsbMidiEventPacket::to_raw_bytes` function. -- `UsbMidiEventPacket::try_from_message_bytes` function. +- `UsbMidiEventPacket::try_from_payload_bytes` function. - `TryFrom<&UsbMidiEventPacket>` implementation for `Message` type. - `Message::into_packet` function. - `Message::code_index_number` function. -- `CodeIndexNumber::try_from_event` function. -- `CodeIndexNumber::event_size` function. +- `CodeIndexNumber::try_from_payload` function. +- `CodeIndexNumber::payload_size` function. - `CableNumber::Cable0` as default value. - `FromOverFlow for U4` implementation. - `FromClamped for U4` implementation. diff --git a/examples/example-esp32s3/src/main.rs b/examples/example-esp32s3/src/main.rs index deaf93d..40a4a6e 100644 --- a/examples/example-esp32s3/src/main.rs +++ b/examples/example-esp32s3/src/main.rs @@ -50,7 +50,7 @@ fn main() -> ! { let buffer_reader = MidiPacketBufferReader::new(&buffer, size); for packet in buffer_reader.into_iter() { if let Ok(packet) = packet { - let message = MidiMessage::try_parse_slice(packet.as_message_bytes()); + let message = MidiMessage::try_parse_slice(packet.payload_bytes()); println!("Cable: {:?}, Message: {:?}", packet.cable_number(), message); } } @@ -74,7 +74,7 @@ fn main() -> ! { message.render_slice(&mut bytes); let packet = - UsbMidiEventPacket::try_from_message_bytes(CableNumber::Cable0, &bytes).unwrap(); + UsbMidiEventPacket::try_from_payload_bytes(CableNumber::Cable0, &bytes).unwrap(); let result = midi_class.send_packet(packet); println!("Send result {:?}", result); diff --git a/src/packet/code_index_number.rs b/src/packet/code_index_number.rs index 65d326c..6cb7fbf 100644 --- a/src/packet/code_index_number.rs +++ b/src/packet/code_index_number.rs @@ -92,10 +92,10 @@ impl From for U4 { } impl CodeIndexNumber { - /// Creates a new number from a MIDI event. - pub fn try_from_event(event: &[u8]) -> Result { - let Some(status) = event.first() else { - return Err(MidiPacketParsingError::EmptyEvent); + /// Creates a new number from a MIDI event payload. + pub fn try_from_payload(payload: &[u8]) -> Result { + let Some(status) = payload.first() else { + return Err(MidiPacketParsingError::EmptyPayload); }; if *status < 0xF0 { @@ -107,7 +107,7 @@ impl CodeIndexNumber { 0xC0 => Ok(Self::ProgramChange), 0xD0 => Ok(Self::ChannelPressure), 0xE0 => Ok(Self::PitchBendChange), - _ => Err(MidiPacketParsingError::InvalidEventStatus), + _ => Err(MidiPacketParsingError::InvalidPayloadStatus), } } else { match status { @@ -115,13 +115,13 @@ impl CodeIndexNumber { 0xF2 => Ok(Self::SystemCommon3Bytes), 0xF6 => Ok(Self::SystemCommon1Byte), 0xF8 | 0xFA | 0xFB | 0xFC | 0xFE | 0xFF => Ok(Self::SingleByte), - _ => Err(MidiPacketParsingError::InvalidEventStatus), + _ => Err(MidiPacketParsingError::InvalidPayloadStatus), } } } - /// Returns the size of the MIDI_x event in bytes. - pub fn event_size(&self) -> usize { + /// Returns the size of the MIDI_x event payload in bytes. + pub fn payload_size(&self) -> usize { match self { Self::SystemCommon1Byte | Self::SingleByte => 1, Self::SystemCommon2Bytes diff --git a/src/packet/mod.rs b/src/packet/mod.rs index bf1e75a..2f9f9ea 100644 --- a/src/packet/mod.rs +++ b/src/packet/mod.rs @@ -38,12 +38,12 @@ pub enum MidiPacketParsingError { InvalidEventType(u8), /// Missing data packet. MissingDataPacket, - /// Empty event. - EmptyEvent, - /// Invalid event status. - InvalidEventStatus, - /// Invalid event size. - InvalidEventSize, + /// Empty payload. + EmptyPayload, + /// Invalid payload status. + InvalidPayloadStatus, + /// Invalid payload size. + InvalidPayloadSize, } impl TryFrom<&[u8]> for UsbMidiEventPacket { @@ -67,13 +67,13 @@ impl UsbMidiEventPacket { CableNumber::try_from(raw_cable_number).unwrap_or_default() } - /// Returns a slice to the message bytes. The length is dependent on the message type. - pub fn as_message_bytes(&self) -> &[u8] { + /// Returns a slice to the event payload bytes. The length is dependent on the payload type. + pub fn payload_bytes(&self) -> &[u8] { let raw_cin = self.raw[0] & 0x0F; match CodeIndexNumber::try_from(raw_cin) { Ok(cin) => { - let size = cin.event_size(); + let size = cin.payload_size(); &self.raw[1..1 + size] } @@ -92,21 +92,21 @@ impl UsbMidiEventPacket { self.raw } - /// Creates a packet from a slice of message bytes. - pub fn try_from_message_bytes( + /// Creates a packet from a slice of event payload bytes. + pub fn try_from_payload_bytes( cable: CableNumber, bytes: &[u8], ) -> Result { - let cin = CodeIndexNumber::try_from_event(bytes)?; - let event_size = cin.event_size(); + let cin = CodeIndexNumber::try_from_payload(bytes)?; + let payload_size = cin.payload_size(); - if bytes.len() < event_size { - return Err(MidiPacketParsingError::InvalidEventSize); + if bytes.len() < payload_size { + return Err(MidiPacketParsingError::InvalidPayloadSize); } let mut raw = [0; 4]; raw[0] = (cable as u8) << 4 | cin as u8; - raw[1..1 + event_size].copy_from_slice(&bytes[..event_size]); + raw[1..1 + payload_size].copy_from_slice(&bytes[..payload_size]); Ok(Self { raw }) } From c43520da90d94ea21a8a26f88e97e488403b2984 Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Sat, 21 Dec 2024 12:47:29 +0100 Subject: [PATCH 43/67] Added UsbMidiEventPacket::header function --- CHANGELOG.md | 1 + src/packet/mod.rs | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 86b2b19..08ae4fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Added - `UsbMidiEventPacket::cable_number` function. +- `UsbMidiEventPacket::header` function. - `UsbMidiEventPacket::payload_bytes` function. - `UsbMidiEventPacket::as_raw_bytes` function. - `UsbMidiEventPacket::to_raw_bytes` function. diff --git a/src/packet/mod.rs b/src/packet/mod.rs index 2f9f9ea..c206fa8 100644 --- a/src/packet/mod.rs +++ b/src/packet/mod.rs @@ -67,6 +67,11 @@ impl UsbMidiEventPacket { CableNumber::try_from(raw_cable_number).unwrap_or_default() } + /// Returns the header byte. + pub fn header(&self) -> u8 { + self.raw[0] + } + /// Returns a slice to the event payload bytes. The length is dependent on the payload type. pub fn payload_bytes(&self) -> &[u8] { let raw_cin = self.raw[0] & 0x0F; From 77fb5c17501179720e922f0d6ed82f53361a898c Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Sat, 21 Dec 2024 12:52:51 +0100 Subject: [PATCH 44/67] Added next release focus items to changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 08ae4fd..52e601d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] +This release focuses on: + +- Increased usability by simplifying the internal module structure. +- Interfacing with third-party crates like `midi-types`. + **NOTE:** The `message` module containing the `Message` struct and related types is now gated behind the `message-types` feature. This feature is enabled by default. ### Added From abf51666b3fc293e0bdbb73ea44e5033dce983d5 Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Sat, 21 Dec 2024 12:58:40 +0100 Subject: [PATCH 45/67] Removed From for U4 implementation --- CHANGELOG.md | 1 + src/packet/cable_number.rs | 7 ------- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 52e601d..dcb9afa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -55,6 +55,7 @@ This release focuses on: - `UsbMidiEventPacket::message` field, use `Message::try_from(&UsbMidiEventPacket)` instead. - `UsbMidiEventPacket::from_midi` function, use `Message::into_packet` instead. - `CodeIndexNumber::find_from_message` function, use `Message::code_index_number` instead. +- `From for U4` implementation. ## [0.3.0] - 2024-05-27 diff --git a/src/packet/cable_number.rs b/src/packet/cable_number.rs index 78cb33c..fb128f0 100644 --- a/src/packet/cable_number.rs +++ b/src/packet/cable_number.rs @@ -1,6 +1,5 @@ //! Enum representing the cable number of a packet. -use crate::data::u4::U4; use crate::packet::MidiPacketParsingError; /// The Cable Number (CN) is a value ranging from 0x0 to 0xF @@ -61,12 +60,6 @@ impl From for u8 { } } -impl From for U4 { - fn from(value: CableNumber) -> U4 { - U4::from_overflowing_u8(u8::from(value)) - } -} - #[cfg(test)] mod tests { From d7a7b99d84597b5021cfa7320674545ce4a4760f Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Sat, 21 Dec 2024 13:02:59 +0100 Subject: [PATCH 46/67] Removed From for U4 implementation --- CHANGELOG.md | 1 + src/message/mod.rs | 3 +-- src/packet/code_index_number.rs | 7 ------- 3 files changed, 2 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dcb9afa..8119835 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -56,6 +56,7 @@ This release focuses on: - `UsbMidiEventPacket::from_midi` function, use `Message::into_packet` instead. - `CodeIndexNumber::find_from_message` function, use `Message::code_index_number` instead. - `From for U4` implementation. +- `From for U4` implementation. ## [0.3.0] - 2024-05-27 diff --git a/src/message/mod.rs b/src/message/mod.rs index 10c46dc..f0fae94 100644 --- a/src/message/mod.rs +++ b/src/message/mod.rs @@ -5,7 +5,6 @@ pub mod control_function; pub mod notes; pub mod raw; -use crate::data::u4::U4; use crate::data::u7::U7; use crate::data::FromClamped; use crate::message::channel::Channel; @@ -149,7 +148,7 @@ impl TryFrom<&UsbMidiEventPacket> for Message { impl Message { /// Create a packet from the message. pub fn into_packet(self, cable: CableNumber) -> UsbMidiEventPacket { - let cin = u8::from(U4::from(self.code_index_number())); + let cin = self.code_index_number() as u8; let mut raw = [0; 4]; raw[0] = (cable as u8) << 4 | cin; diff --git a/src/packet/code_index_number.rs b/src/packet/code_index_number.rs index 6cb7fbf..39871de 100644 --- a/src/packet/code_index_number.rs +++ b/src/packet/code_index_number.rs @@ -1,6 +1,5 @@ //! Enum representing the code index number of a packet. -use crate::data::u4::U4; use crate::packet::MidiPacketParsingError; /// The Code Index Number(CIN) indicates the classification @@ -85,12 +84,6 @@ impl TryFrom for CodeIndexNumber { } } -impl From for U4 { - fn from(value: CodeIndexNumber) -> U4 { - U4::from_overflowing_u8(value as u8) - } -} - impl CodeIndexNumber { /// Creates a new number from a MIDI event payload. pub fn try_from_payload(payload: &[u8]) -> Result { From 8d0a6517db14839b5dc41fdd3a8f6d419769d8b8 Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Sat, 21 Dec 2024 13:09:29 +0100 Subject: [PATCH 47/67] Moved data module into message module --- CHANGELOG.md | 4 ++-- src/lib.rs | 1 - src/message/control_function.rs | 2 +- src/{ => message}/data/mod.rs | 0 src/{ => message}/data/u4.rs | 2 +- src/{ => message}/data/u7.rs | 2 +- src/message/mod.rs | 7 ++++--- src/message/notes.rs | 4 ++-- src/message/raw.rs | 2 +- 9 files changed, 12 insertions(+), 12 deletions(-) rename src/{ => message}/data/mod.rs (100%) rename src/{ => message}/data/u4.rs (96%) rename src/{ => message}/data/u7.rs (95%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8119835..1185a1f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,8 +42,8 @@ This release focuses on: - Moved `usb_midi_event_packet` code into parent `packet` module. - Moved `channel` and `notes` modules into `message` module. - Moved `message` module to crate root. -- Moved `byte` submodules into `data` module. -- Moved `from_traits` code into parent module. +- Moved `byte` submodules into `message::data` module. +- Moved `from_traits` code into parent `data` module. - Consolidated separate `InvalidCableNumber` struct into `MidiPacketParsingError`. - Consolidated separate `InvalidCodeIndexNumber` struct into `MidiPacketParsingError`. - Converted `CodeIndexNumber` struct to enum. diff --git a/src/lib.rs b/src/lib.rs index fb3219f..74ed9fb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,7 +3,6 @@ #![no_std] pub mod class; -pub mod data; pub mod packet; #[cfg(feature = "message-types")] diff --git a/src/message/control_function.rs b/src/message/control_function.rs index 932e1a4..366d40e 100644 --- a/src/message/control_function.rs +++ b/src/message/control_function.rs @@ -1,6 +1,6 @@ //! Control function definitions. -use crate::data::u7::U7; +use crate::message::data::u7::U7; /// Custom type for a control function. #[derive(Debug, Clone, Eq, PartialEq)] diff --git a/src/data/mod.rs b/src/message/data/mod.rs similarity index 100% rename from src/data/mod.rs rename to src/message/data/mod.rs diff --git a/src/data/u4.rs b/src/message/data/u4.rs similarity index 96% rename from src/data/u4.rs rename to src/message/data/u4.rs index 2043856..0cbe855 100644 --- a/src/data/u4.rs +++ b/src/message/data/u4.rs @@ -1,6 +1,6 @@ //! A primitive value with 4-bit length. -use crate::data::{FromClamped, FromOverFlow}; +use crate::message::data::{FromClamped, FromOverFlow}; /// A primitive value that can be from 0-0x0F pub struct U4(u8); diff --git a/src/data/u7.rs b/src/message/data/u7.rs similarity index 95% rename from src/data/u7.rs rename to src/message/data/u7.rs index 7b24cca..2fa3b23 100644 --- a/src/data/u7.rs +++ b/src/message/data/u7.rs @@ -1,6 +1,6 @@ //! A primitive value with 7-bit length. -use crate::data::{FromClamped, FromOverFlow}; +use crate::message::data::{FromClamped, FromOverFlow}; /// A primitive value that can be from 0-0x7F #[derive(Debug, Clone, Eq, PartialEq)] diff --git a/src/message/mod.rs b/src/message/mod.rs index f0fae94..8327c45 100644 --- a/src/message/mod.rs +++ b/src/message/mod.rs @@ -2,13 +2,14 @@ pub mod channel; pub mod control_function; +pub mod data; pub mod notes; pub mod raw; -use crate::data::u7::U7; -use crate::data::FromClamped; use crate::message::channel::Channel; use crate::message::control_function::ControlFunction; +use crate::message::data::u7::U7; +use crate::message::data::FromClamped; use crate::message::notes::Note; use crate::message::raw::{Payload, Raw}; use crate::packet::cable_number::CableNumber; @@ -209,9 +210,9 @@ fn get_byte_at_position(data: &[u8], index: usize) -> Result Date: Sat, 21 Dec 2024 13:15:32 +0100 Subject: [PATCH 48/67] Re-export error types in crate root --- src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 74ed9fb..6f2b04e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,10 +8,10 @@ pub mod packet; #[cfg(feature = "message-types")] pub mod message; -pub use crate::class::MidiClass; +pub use crate::class::{MidiClass, MidiReadError}; pub use crate::packet::cable_number::CableNumber; pub use crate::packet::reader::MidiPacketBufferReader; -pub use crate::packet::UsbMidiEventPacket; +pub use crate::packet::{MidiPacketParsingError, UsbMidiEventPacket}; #[cfg(feature = "message-types")] pub use crate::message::Message; From fc748e4deeb5bd031648dca5d3f04ce1162c023f Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Sat, 21 Dec 2024 13:24:24 +0100 Subject: [PATCH 49/67] Include README as docs in crate root --- README.md | 4 ++-- src/lib.rs | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 20c859c..554230f 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ This crate requires the use of a HAL that implements the `usb-device` traits. Turn on an LED as long as note C2 is pressed. The example only shows the hardware-independent parts. -```rust +```rust ignore use usb_device::prelude::*; use usbd_midi::{ message::{channel::Channel, notes::Note}, @@ -72,7 +72,7 @@ the `usb-device` crate: Cargo.toml: -``` +```ignore usb-device = { version = ">=0.3.2", features = ["control-buffer-256"] } ``` diff --git a/src/lib.rs b/src/lib.rs index 6f2b04e..a49745e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,4 @@ -//! USB MIDI class implementation for [usb-device](https://crates.io/crates/usb-device). - +#![doc = include_str!("../README.md")] #![no_std] pub mod class; From 8c4a17b736e41c69abc8316ae8d6e6e5e469effa Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Sat, 21 Dec 2024 13:55:53 +0100 Subject: [PATCH 50/67] Made num_enum an optional dependency --- Cargo.toml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c743e8b..2df4025 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,14 +16,15 @@ keywords = ["usb", "midi"] [features] default = ["message-types"] -message-types = [] +message-types = ["dep:num_enum"] [dependencies] usb-device = "0.3" [dependencies.num_enum] -version = "0.7.2" +version = "0.7.3" default-features = false +optional = true [lints.rust] missing_docs = "warn" From c74e948131dfaf7ab5638e055ac0cbc1748ff0fe Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Sat, 21 Dec 2024 15:43:13 +0100 Subject: [PATCH 51/67] README example fix --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 554230f..2ca2b2c 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ loop { let buffer_reader = MidiPacketBufferReader::new(&buffer, size); for packet in buffer_reader.into_iter() { if let Ok(packet) = packet { - match packet.message { + match Message::try_from(&packet).unwrap() { Message::NoteOn(Channel1, Note::C2, ..) => { led.set_low().unwrap(); }, From 46c9ff57d1518ef34e07ee9df86b7715e5510615 Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Sun, 22 Dec 2024 10:29:33 +0100 Subject: [PATCH 52/67] Added more derives for error types --- src/class.rs | 1 + src/packet/mod.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/class.rs b/src/class.rs index 9248130..8971648 100644 --- a/src/class.rs +++ b/src/class.rs @@ -39,6 +39,7 @@ pub struct MidiClass<'a, B: UsbBus> { } /// Error variants for read operations. +#[derive(Debug, Clone, Eq, PartialEq)] pub enum MidiReadError { /// Parsing of the packet failed. ParsingFailed(MidiPacketParsingError), diff --git a/src/packet/mod.rs b/src/packet/mod.rs index c206fa8..12c716b 100644 --- a/src/packet/mod.rs +++ b/src/packet/mod.rs @@ -24,7 +24,7 @@ impl From for [u8; 4] { } /// Error variants for parsing the packet. -#[derive(Debug)] +#[derive(Debug, Clone, Eq, PartialEq)] pub enum MidiPacketParsingError { /// Invalid packet. InvalidPacket, From 1bc9fc4fe8f21edaa77361d64f77957fe40b3542 Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Sun, 22 Dec 2024 11:33:00 +0100 Subject: [PATCH 53/67] Added tests for code index number --- src/packet/code_index_number.rs | 46 ++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/src/packet/code_index_number.rs b/src/packet/code_index_number.rs index 39871de..315019c 100644 --- a/src/packet/code_index_number.rs +++ b/src/packet/code_index_number.rs @@ -86,6 +86,8 @@ impl TryFrom for CodeIndexNumber { impl CodeIndexNumber { /// Creates a new number from a MIDI event payload. + /// + /// The detection is based on the content and ignores the slice length. pub fn try_from_payload(payload: &[u8]) -> Result { let Some(status) = payload.first() else { return Err(MidiPacketParsingError::EmptyPayload); @@ -107,7 +109,7 @@ impl CodeIndexNumber { 0xF1 | 0xF3 => Ok(Self::SystemCommon2Bytes), 0xF2 => Ok(Self::SystemCommon3Bytes), 0xF6 => Ok(Self::SystemCommon1Byte), - 0xF8 | 0xFA | 0xFB | 0xFC | 0xFE | 0xFF => Ok(Self::SingleByte), + 0xF8 | 0xF9 | 0xFA | 0xFB | 0xFC | 0xFE | 0xFF => Ok(Self::SingleByte), _ => Err(MidiPacketParsingError::InvalidPayloadStatus), } } @@ -136,3 +138,45 @@ impl CodeIndexNumber { } } } + +#[cfg(test)] +mod tests { + use super::*; + + macro_rules! encode_payload_test { + ($($id:ident: $value:expr,)*) => { + $( + #[test] + fn $id() { + let (payload, expected) = $value; + let cin = CodeIndexNumber::try_from_payload(&payload); + assert_eq!(cin, expected); + } + )* + } + } + + encode_payload_test! { + note_off: ([0x80, 60, 64], Ok(CodeIndexNumber::NoteOff)), + note_on: ([0x90, 60, 64], Ok(CodeIndexNumber::NoteOn)), + poly_key_press: ([0xA0, 48, 32], Ok(CodeIndexNumber::PolyKeyPress)), + control_change: ([0xB0, 10, 127], Ok(CodeIndexNumber::ControlChange)), + program_change: ([0xC0, 5], Ok(CodeIndexNumber::ProgramChange)), + channel_pressure: ([0xD0, 54], Ok(CodeIndexNumber::ChannelPressure)), + pitch_bend: ([0xE0, 32, 96], Ok(CodeIndexNumber::PitchBendChange)), + mtc_quarter_frame: ([0xF1, 12], Ok(CodeIndexNumber::SystemCommon2Bytes)), + song_position_pointer: ([0xF2, 3, 8], Ok(CodeIndexNumber::SystemCommon3Bytes)), + song_select: ([0xF3, 15], Ok(CodeIndexNumber::SystemCommon2Bytes)), + tune_request: ([0xF6], Ok(CodeIndexNumber::SystemCommon1Byte)), + timing_clock: ([0xF8], Ok(CodeIndexNumber::SingleByte)), + tick: ([0xF9], Ok(CodeIndexNumber::SingleByte)), + start: ([0xFA], Ok(CodeIndexNumber::SingleByte)), + continue_: ([0xFB], Ok(CodeIndexNumber::SingleByte)), + stop: ([0xFC], Ok(CodeIndexNumber::SingleByte)), + active_sensing: ([0xFE], Ok(CodeIndexNumber::SingleByte)), + system_reset: ([0xFF], Ok(CodeIndexNumber::SingleByte)), + undefined_f4: ([0xF4], Err(MidiPacketParsingError::InvalidPayloadStatus)), + undefined_f5: ([0xF5], Err(MidiPacketParsingError::InvalidPayloadStatus)), + empty: ([], Err(MidiPacketParsingError::EmptyPayload)), + } +} From 5f081205c0bc89d8522d66871188f747ae0d771d Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Sun, 22 Dec 2024 12:26:52 +0100 Subject: [PATCH 54/67] Added support for SysEx in CodeIndexNumber::try_from_payload --- src/packet/code_index_number.rs | 38 +++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/src/packet/code_index_number.rs b/src/packet/code_index_number.rs index 315019c..57c00e3 100644 --- a/src/packet/code_index_number.rs +++ b/src/packet/code_index_number.rs @@ -102,13 +102,36 @@ impl CodeIndexNumber { 0xC0 => Ok(Self::ProgramChange), 0xD0 => Ok(Self::ChannelPressure), 0xE0 => Ok(Self::PitchBendChange), - _ => Err(MidiPacketParsingError::InvalidPayloadStatus), + _ => { + if payload.len() > 1 && payload[1] == 0xF7 { + Ok(Self::SysexEnds2Bytes) + } else if payload.len() > 2 && payload[2] == 0xF7 { + Ok(Self::SysexEnds3Bytes) + } else if payload.len() == 1 { + Ok(Self::SingleByte) + } else if payload.len() > 2 { + Ok(Self::SysexStartsOrContinues) + } else { + Err(MidiPacketParsingError::InvalidPayloadSize) + } + } } } else { match status { + 0xF0 => { + if payload.len() > 1 && payload[1] == 0xF7 { + Ok(Self::SysexEnds2Bytes) + } else if payload.len() > 2 && payload[2] == 0xF7 { + Ok(Self::SysexEnds3Bytes) + } else if payload.len() > 2 { + Ok(Self::SysexStartsOrContinues) + } else { + Err(MidiPacketParsingError::InvalidPayloadSize) + } + } 0xF1 | 0xF3 => Ok(Self::SystemCommon2Bytes), 0xF2 => Ok(Self::SystemCommon3Bytes), - 0xF6 => Ok(Self::SystemCommon1Byte), + 0xF6 | 0xF7 => Ok(Self::SystemCommon1Byte), 0xF8 | 0xF9 | 0xFA | 0xFB | 0xFC | 0xFE | 0xFF => Ok(Self::SingleByte), _ => Err(MidiPacketParsingError::InvalidPayloadStatus), } @@ -175,6 +198,17 @@ mod tests { stop: ([0xFC], Ok(CodeIndexNumber::SingleByte)), active_sensing: ([0xFE], Ok(CodeIndexNumber::SingleByte)), system_reset: ([0xFF], Ok(CodeIndexNumber::SingleByte)), + sysex_starts: ([0xF0, 1, 2], Ok(CodeIndexNumber::SysexStartsOrContinues)), + sysex_starts_1byte: ([0xF0], Err(MidiPacketParsingError::InvalidPayloadSize)), + sysex_starts_2byte: ([0xF0, 1], Err(MidiPacketParsingError::InvalidPayloadSize)), + sysex_continues_1byte: ([1], Ok(CodeIndexNumber::SingleByte)), + sysex_continues_2bytes: ([1, 2], Err(MidiPacketParsingError::InvalidPayloadSize)), + sysex_continues_3bytes: ([1, 2, 3], Ok(CodeIndexNumber::SysexStartsOrContinues)), + sysex_ends_1byte: ([0xF7], Ok(CodeIndexNumber::SystemCommon1Byte)), + sysex_ends_2bytes: ([1, 0xF7], Ok(CodeIndexNumber::SysexEnds2Bytes)), + sysex_ends_3bytes: ([1, 2, 0xF7], Ok(CodeIndexNumber::SysexEnds3Bytes)), + sysex_2bytes: ([0xF0, 0xF7], Ok(CodeIndexNumber::SysexEnds2Bytes)), + sysex_3bytes: ([0xF0, 1, 0xF7], Ok(CodeIndexNumber::SysexEnds3Bytes)), undefined_f4: ([0xF4], Err(MidiPacketParsingError::InvalidPayloadStatus)), undefined_f5: ([0xF5], Err(MidiPacketParsingError::InvalidPayloadStatus)), empty: ([], Err(MidiPacketParsingError::EmptyPayload)), From 1f2203fa0f8c608203a483d5ccd93ce84efbd23b Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Sun, 22 Dec 2024 14:06:12 +0100 Subject: [PATCH 55/67] Added functions to detect SysEx packets --- CHANGELOG.md | 3 +++ examples/example-esp32s3/Cargo.toml | 1 + examples/example-esp32s3/src/main.rs | 31 +++++++++++++++++++++++++--- src/packet/mod.rs | 26 +++++++++++++++++++++++ 4 files changed, 58 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1185a1f..258369e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,9 @@ This release focuses on: - `UsbMidiEventPacket::as_raw_bytes` function. - `UsbMidiEventPacket::to_raw_bytes` function. - `UsbMidiEventPacket::try_from_payload_bytes` function. +- `UsbMidiEventPacket::is_sysex` function. +- `UsbMidiEventPacket::is_sysex_start` function. +- `UsbMidiEventPacket::is_sysex_end` function. - `TryFrom<&UsbMidiEventPacket>` implementation for `Message` type. - `Message::into_packet` function. - `Message::code_index_number` function. diff --git a/examples/example-esp32s3/Cargo.toml b/examples/example-esp32s3/Cargo.toml index 0c9563b..b55c67c 100644 --- a/examples/example-esp32s3/Cargo.toml +++ b/examples/example-esp32s3/Cargo.toml @@ -14,3 +14,4 @@ esp-println = { version = "0.12.0", features = ["esp32s3", "log"] } usb-device = { version = "0.3.2", features = ["control-buffer-256"] } usbd-midi = { path = "../../" } midi-convert = "0.2.0" +heapless = "0.8.0" diff --git a/examples/example-esp32s3/src/main.rs b/examples/example-esp32s3/src/main.rs index 40a4a6e..39c4ad5 100644 --- a/examples/example-esp32s3/src/main.rs +++ b/examples/example-esp32s3/src/main.rs @@ -8,6 +8,7 @@ use core::ptr::addr_of_mut; use esp_backtrace as _; use esp_hal::{clock, gpio, otg_fs, xtensa_lx_rt, Config}; use esp_println::println; +use heapless::Vec; use midi_convert::midi_types::{Channel, MidiMessage, Note, Value7}; use midi_convert::{parse::MidiTryParseSlice, render_slice::MidiRenderSlice}; use usb_device::prelude::*; @@ -41,6 +42,8 @@ fn main() -> ! { let button = gpio::Input::new(peripherals.GPIO0, gpio::Pull::Up); let mut last_button_level = button.level(); + let mut sysex_buffer = Vec::::new(); + loop { if usb_dev.poll(&mut [&mut midi_class]) { // Receive messages. @@ -48,10 +51,32 @@ fn main() -> ! { if let Ok(size) = midi_class.read(&mut buffer) { let buffer_reader = MidiPacketBufferReader::new(&buffer, size); - for packet in buffer_reader.into_iter() { - if let Ok(packet) = packet { + for packet in buffer_reader.into_iter().flatten() { + if !packet.is_sysex() { let message = MidiMessage::try_parse_slice(packet.payload_bytes()); - println!("Cable: {:?}, Message: {:?}", packet.cable_number(), message); + println!( + "Regular Message, cable: {:?}, message: {:?}", + packet.cable_number(), + message + ); + } else { + if packet.is_sysex_start() { + println!("SysEx message start"); + sysex_buffer.clear(); + } + + match sysex_buffer.extend_from_slice(packet.payload_bytes()) { + Ok(_) => { + if packet.is_sysex_end() { + println!("SysEx message end"); + println!("Buffered SysEx message: {:?}", sysex_buffer); + } + } + Err(_) => { + println!("SysEx buffer overflow."); + break; + } + } } } } diff --git a/src/packet/mod.rs b/src/packet/mod.rs index 12c716b..9eb2008 100644 --- a/src/packet/mod.rs +++ b/src/packet/mod.rs @@ -115,4 +115,30 @@ impl UsbMidiEventPacket { Ok(Self { raw }) } + + /// Returns if the packet payload is part of a SysEx message. + pub fn is_sysex(&self) -> bool { + let Ok(cin) = CodeIndexNumber::try_from(self.raw[0] & 0x0F) else { + return false; + }; + + match cin { + CodeIndexNumber::SysexStartsOrContinues + | CodeIndexNumber::SysexEnds2Bytes + | CodeIndexNumber::SysexEnds3Bytes => true, + CodeIndexNumber::SystemCommon1Byte => self.raw[1] == 0xF7, + CodeIndexNumber::SingleByte => self.raw[1] < 0x80, + _ => false, + } + } + + /// Returns if the packet payload contains the start of a SysEx message. + pub fn is_sysex_start(&self) -> bool { + self.is_sysex() && self.raw[1] == 0xF0 + } + + /// Returns if the packet payload contains the end of a SysEx message. + pub fn is_sysex_end(&self) -> bool { + self.is_sysex() && (self.raw[1] == 0xF7 || self.raw[2] == 0xF7 || self.raw[3] == 0xF7) + } } From d19443fc81da496d87051950fb635ee9b33bd3cd Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Sun, 22 Dec 2024 15:29:01 +0100 Subject: [PATCH 56/67] ESP32-S3 example: added SysEx processing and some comments --- CHANGELOG.md | 1 + examples/example-esp32s3/src/main.rs | 92 +++++++++++++++++++++++++--- 2 files changed, 86 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 258369e..243e123 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ This release focuses on: - Increased usability by simplifying the internal module structure. - Interfacing with third-party crates like `midi-types`. +- Support for System Exclusive messages (SysEx). **NOTE:** The `message` module containing the `Message` struct and related types is now gated behind the `message-types` feature. This feature is enabled by default. diff --git a/examples/example-esp32s3/src/main.rs b/examples/example-esp32s3/src/main.rs index 39c4ad5..bfcf1fc 100644 --- a/examples/example-esp32s3/src/main.rs +++ b/examples/example-esp32s3/src/main.rs @@ -1,4 +1,4 @@ -//! Example for ESP32-S3. +//! Example for ESP32-S3. Tested on ESP32-S3-DevKitC-1. #![no_std] #![no_main] @@ -16,8 +16,12 @@ use usbd_midi::{CableNumber, MidiClass, MidiPacketBufferReader, UsbMidiEventPack static mut EP_MEMORY: [u32; 1024] = [0; 1024]; +// Size of the used SysEx buffers in bytes. +const SYSEX_BUFFER_SIZE: usize = 64; + #[xtensa_lx_rt::entry] fn main() -> ! { + // Some basic setup to run the MCU at maximum clock speed. let mut config = Config::default(); config.cpu_clock = clock::CpuClock::Clock240MHz; let peripherals = esp_hal::init(config); @@ -27,8 +31,11 @@ fn main() -> ! { unsafe { &mut *addr_of_mut!(EP_MEMORY) }, ); + // Create a MIDI class with 1 input and 1 output jack. let mut midi_class = MidiClass::new(&usb_bus_allocator, 1, 1).unwrap(); + // Build the device. It's important to use `0` for the class and subclass fields because + // otherwise the device will not enumerate correctly on certain hosts. let mut usb_dev = UsbDeviceBuilder::new(&usb_bus_allocator, UsbVidPid(0x16c0, 0x5e4)) .device_class(0) .device_sub_class(0) @@ -39,10 +46,12 @@ fn main() -> ! { .unwrap() .build(); + // This is the *BOOT* button on the ESP32-S3-DevKitC-1. let button = gpio::Input::new(peripherals.GPIO0, gpio::Pull::Up); let mut last_button_level = button.level(); - let mut sysex_buffer = Vec::::new(); + // Buffer for received SysEx messages from the host. + let mut sysex_receive_buffer = Vec::::new(); loop { if usb_dev.poll(&mut [&mut midi_class]) { @@ -53,6 +62,7 @@ fn main() -> ! { let buffer_reader = MidiPacketBufferReader::new(&buffer, size); for packet in buffer_reader.into_iter().flatten() { if !packet.is_sysex() { + // Just a regular 3-byte message that can be processed directly. let message = MidiMessage::try_parse_slice(packet.payload_bytes()); println!( "Regular Message, cable: {:?}, message: {:?}", @@ -60,16 +70,51 @@ fn main() -> ! { message ); } else { + // If a packet containing a SysEx payload is detected, the data is saved + // into a buffer and processed after the message is complete. if packet.is_sysex_start() { println!("SysEx message start"); - sysex_buffer.clear(); + sysex_receive_buffer.clear(); } - match sysex_buffer.extend_from_slice(packet.payload_bytes()) { + match sysex_receive_buffer.extend_from_slice(packet.payload_bytes()) { Ok(_) => { if packet.is_sysex_end() { println!("SysEx message end"); - println!("Buffered SysEx message: {:?}", sysex_buffer); + println!("Buffered SysEx message: {:?}", sysex_receive_buffer); + + // Process the SysEx message as request in a separate function + // and send an optional response back to the host. + if let Some(response) = + process_sysex(sysex_receive_buffer.as_ref()) + { + for chunk in response.chunks(3) { + let packet = UsbMidiEventPacket::try_from_payload_bytes( + CableNumber::Cable0, + chunk, + ); + match packet { + Ok(packet) => loop { + // Make sure to add some timeout in case the host + // does not read the data. + let result = + midi_class.send_packet(packet.clone()); + match result { + Ok(_) => break, + Err(err) => { + if err != UsbError::WouldBlock { + break; + } + } + } + }, + Err(err) => println!( + "SysEx response packet error: {:?}", + err + ), + } + } + } } } Err(_) => { @@ -82,9 +127,9 @@ fn main() -> ! { } } - // Send messages on button press. let button_level = button.level(); + // Send a message when the button state changes. if button_level != last_button_level { last_button_level = button_level; @@ -100,9 +145,42 @@ fn main() -> ! { let packet = UsbMidiEventPacket::try_from_payload_bytes(CableNumber::Cable0, &bytes).unwrap(); - let result = midi_class.send_packet(packet); + // Try to send the packet. + // An `UsbError::WouldBlock` is returned if the host has not read previous data. + let result = midi_class.send_packet(packet); println!("Send result {:?}", result); } } } + +/// Processes a SysEx request and returns an optional response. +pub fn process_sysex(request: &[u8]) -> Option> { + /// Identity request message. + /// + /// See section *DEVICE INQUIRY* of the *MIDI 1.0 Detailed Specification* for further details. + const IDENTITY_REQUEST: [u8; 6] = [0xF0, 0x7E, 0x7F, 0x06, 0x01, 0xF7]; + + if request == IDENTITY_REQUEST { + let mut response = Vec::::new(); + response + .extend_from_slice(&[ + 0xF0, 0x7E, 0x7F, 0x06, 0x02, // Header + 0x01, // Manufacturer ID + 0x02, // Family code + 0x03, // Family code + 0x04, // Family member code + 0x05, // Family member code + 0x00, // Software revision level + 0x00, // Software revision level + 0x00, // Software revision level + 0x00, // Software revision level + 0xF7, + ]) + .ok(); + + return Some(response); + } + + None +} From 7852a36f6a6e5eb1c5f3b928ad573331c15482d4 Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Sun, 22 Dec 2024 15:38:54 +0100 Subject: [PATCH 57/67] Added note to changelog about constants now being private. --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 243e123..782ad58 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,10 @@ This release focuses on: - Interfacing with third-party crates like `midi-types`. - Support for System Exclusive messages (SysEx). -**NOTE:** The `message` module containing the `Message` struct and related types is now gated behind the `message-types` feature. This feature is enabled by default. +**Important:** + +- The `message` module containing the `Message` struct and related types is now gated behind the `message-types` feature. This feature is enabled by default. +- The constants `USB_AUDIO_CLASS`, `USB_AUDIOCONTROL_SUBCLASS` and `USB_MIDISTREAMING_SUBCLASS` are now private to prevent them from being used in the device setup. Doing so would lead to incorrect enumeration on certain hosts (e.g. macOS). ### Added From 057574a6333bfa367c8c0140c68760a386760b43 Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Sun, 22 Dec 2024 16:13:12 +0100 Subject: [PATCH 58/67] ESP32-S3 example: added README --- examples/example-esp32s3/README.md | 31 ++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 examples/example-esp32s3/README.md diff --git a/examples/example-esp32s3/README.md b/examples/example-esp32s3/README.md new file mode 100644 index 0000000..3bc72f1 --- /dev/null +++ b/examples/example-esp32s3/README.md @@ -0,0 +1,31 @@ +# ESP32-S3 Example + +This example was developed and tested on an [ESP32-S3-DevKitC-1](https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32s3/esp32-s3-devkitc-1/index.html) using the [esp-hal crate](https://crates.io/crates/esp-hal). + +It features: + +- Sending and receiving of regular MIDI messages. +- Sending and receiving of MIDI System Exclusive messages with buffering. +- Conversion of USB MIDI packets from and to types provided by the [midi-types crate](https://crates.io/crates/midi-types). + +It does not provide a fully production-ready setup, especially time-critical tasks like polling the USB bus in an interrupt and managing bus timeouts are out of scope of this example. + +## Requirements + +To build the example, an installed toolchain for the Xtensa target is required. Please refer to the [Rust on ESP book](https://docs.esp-rs.org/book/) for further instructions. + +You can build the example by running: + + cargo build --release + +If [espflash](https://crates.io/crates/espflash) is installed, you can flash the example to the board and run it: + + cargo run --release + +## Functionality + +- Incoming MIDI messages are logged to the console. +- Pressing and releasing the *BOOT* button on the board sends MIDI messages. +- A received *Device Inquiry* SysEx request is responded to the host. + +Please note that all chosen vendor and product ids and names are just for demonstration purposes and should not be used with a real product. From 928429eb1060d3e17bccf8def783bb6c33be1abf Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Thu, 26 Dec 2024 11:40:03 +0100 Subject: [PATCH 59/67] Added tests for packet decoding --- src/packet/mod.rs | 67 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/src/packet/mod.rs b/src/packet/mod.rs index 9eb2008..f6ff19a 100644 --- a/src/packet/mod.rs +++ b/src/packet/mod.rs @@ -142,3 +142,70 @@ impl UsbMidiEventPacket { self.is_sysex() && (self.raw[1] == 0xF7 || self.raw[2] == 0xF7 || self.raw[3] == 0xF7) } } + +#[cfg(test)] +mod tests { + use super::*; + + mod decode { + use super::*; + + macro_rules! decode_packet_test { + ($($id:ident: $value:expr,)*) => { + $( + #[test] + fn $id() { + let (raw, expected) = $value; + let expected = ( + expected.0, + expected.1.as_slice(), + expected.2, expected.3, + expected.4 + ); + let packet = UsbMidiEventPacket::try_from(raw.as_slice()).unwrap(); + let decoded = ( + packet.cable_number(), + packet.payload_bytes(), + packet.is_sysex(), + packet.is_sysex_start(), + packet.is_sysex_end() + ); + assert_eq!(decoded, expected); + } + )* + } + } + + decode_packet_test! { + note_off: ([0x18, 0x80, 60, 64], (CableNumber::Cable1, [0x80, 60, 64], false, false, false)), + note_on: ([0x49, 0x92, 48, 20], (CableNumber::Cable4, [0x92, 48, 20], false, false, false)), + poly_key_press: ([0x0A, 0xA0, 15, 74], (CableNumber::Cable0, [0xA0, 15, 74], false, false, false)), + control_change: ([0x0B, 0xB0, 64, 127], (CableNumber::Cable0, [0xB0, 64, 127], false, false, false)), + program_change: ([0x0C, 0xC0, 5, 0], (CableNumber::Cable0, [0xC0, 5], false, false, false)), + channel_pressure: ([0x0D, 0xD0, 85, 0], (CableNumber::Cable0, [0xD0, 85], false, false, false)), + pitch_bend: ([0x0E, 0xE0, 40, 120], (CableNumber::Cable0, [0xE0, 40, 120], false, false, false)), + mtc_quarter_frame: ([0x02, 0xF1, 27, 0], (CableNumber::Cable0, [0xF1, 27], false, false, false)), + song_position_pointer: ([0x03, 0xF2, 38, 17], (CableNumber::Cable0, [0xF2, 38, 17], false, false, false)), + song_select: ([0x02, 0xF3, 2, 0], (CableNumber::Cable0, [0xF3, 2], false, false, false)), + tune_request: ([0x05, 0xF6, 0, 0], (CableNumber::Cable0, [0xF6], false, false, false)), + timing_clock: ([0x0F, 0xF8, 0, 0], (CableNumber::Cable0, [0xF8], false, false, false)), + tick: ([0x0F, 0xF9, 0, 0], (CableNumber::Cable0, [0xF9], false, false, false)), + start: ([0x0F, 0xFA, 0, 0], (CableNumber::Cable0, [0xFA], false, false, false)), + continue_: ([0x0F, 0xFB, 0, 0], (CableNumber::Cable0, [0xFB], false, false, false)), + stop: ([0x0F, 0xFC, 0, 0], (CableNumber::Cable0, [0xFC], false, false, false)), + active_sensing: ([0x0F, 0xFE, 0, 0], (CableNumber::Cable0, [0xFE], false, false, false)), + system_reset: ([0x0F, 0xFF, 0, 0], (CableNumber::Cable0, [0xFF], false, false, false)), + sysex_starts: ([0x04, 0xF0, 1, 2], (CableNumber::Cable0, [0xF0, 1, 2], true, true, false)), + sysex_continues_1byte: ([0x0F, 1, 0, 0], (CableNumber::Cable0, [1], true, false, false)), + sysex_continues_3bytes: ([0x04, 1, 2, 3], (CableNumber::Cable0, [1, 2, 3], true, false, false)), + sysex_ends_1byte: ([0x05, 0xF7, 0, 0], (CableNumber::Cable0, [0xF7], true, false, true)), + sysex_ends_2bytes: ([0x06, 1, 0xF7, 0], (CableNumber::Cable0, [1, 0xF7], true, false, true)), + sysex_ends_3bytes: ([0x07, 1, 2, 0xF7], (CableNumber::Cable0, [1, 2, 0xF7], true, false, true)), + sysex_2bytes: ([0x06, 0xF0, 0xF7, 0], (CableNumber::Cable0, [0xF0, 0xF7], true, true, true)), + sysex_3bytes: ([0x07, 0xF0, 1, 0xF7], (CableNumber::Cable0, [0xF0, 1, 0xF7], true, true, true)), + undefined_f4: ([0x02, 0xF4, 1, 0], (CableNumber::Cable0, [0xF4, 1], false, false, false)), + undefined_f5: ([0x03, 0xF5, 1, 2], (CableNumber::Cable0, [0xF5, 1, 2], false, false, false)), + empty: ([0x00, 0, 0, 0], (CableNumber::Cable0, [0, 0, 0], false, false, false)), + } + } +} From 85b0cc9f566040d562fee0001731eca5c74d8499 Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Fri, 27 Dec 2024 11:20:15 +0100 Subject: [PATCH 60/67] Added tests for packet encoding --- src/packet/code_index_number.rs | 2 +- src/packet/mod.rs | 64 +++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/src/packet/code_index_number.rs b/src/packet/code_index_number.rs index 57c00e3..d466aec 100644 --- a/src/packet/code_index_number.rs +++ b/src/packet/code_index_number.rs @@ -200,7 +200,7 @@ mod tests { system_reset: ([0xFF], Ok(CodeIndexNumber::SingleByte)), sysex_starts: ([0xF0, 1, 2], Ok(CodeIndexNumber::SysexStartsOrContinues)), sysex_starts_1byte: ([0xF0], Err(MidiPacketParsingError::InvalidPayloadSize)), - sysex_starts_2byte: ([0xF0, 1], Err(MidiPacketParsingError::InvalidPayloadSize)), + sysex_starts_2bytes: ([0xF0, 1], Err(MidiPacketParsingError::InvalidPayloadSize)), sysex_continues_1byte: ([1], Ok(CodeIndexNumber::SingleByte)), sysex_continues_2bytes: ([1, 2], Err(MidiPacketParsingError::InvalidPayloadSize)), sysex_continues_3bytes: ([1, 2, 3], Ok(CodeIndexNumber::SysexStartsOrContinues)), diff --git a/src/packet/mod.rs b/src/packet/mod.rs index f6ff19a..edf70ac 100644 --- a/src/packet/mod.rs +++ b/src/packet/mod.rs @@ -208,4 +208,68 @@ mod tests { empty: ([0x00, 0, 0, 0], (CableNumber::Cable0, [0, 0, 0], false, false, false)), } } + + mod encode { + use super::*; + + macro_rules! encode_packet_test { + ($($id:ident: $value:expr,)*) => { + $( + #[test] + fn $id() { + let ((cable, payload), expected) = $value; + let payload = payload.as_slice(); + let encoded = UsbMidiEventPacket::try_from_payload_bytes(cable, payload); + let expected: Result<[u8; 4], MidiPacketParsingError> = expected; + assert_eq!(encoded, expected.map( + |v| UsbMidiEventPacket::try_from(v.as_slice()).unwrap()) + ); + } + )* + } + } + + encode_packet_test! { + note_off: ((CableNumber::Cable3, [0x80, 33, 75]), Ok([0x38, 0x80, 33, 75])), + note_on: ((CableNumber::Cable2, [0x96, 67, 14]), Ok([0x29, 0x96, 67, 14])), + poly_key_press: ((CableNumber::Cable0, [0xA0, 48, 72]), Ok([0x0A, 0xA0, 48, 72])), + control_change: ((CableNumber::Cable0, [0xB0, 10, 127]), Ok([0x0B, 0xB0, 10, 127])), + program_change: ((CableNumber::Cable0, [0xC0, 36]), Ok([0x0C, 0xC0, 36, 0])), + program_change_extra: ((CableNumber::Cable0, [0xC0, 36, 54]), Ok([0x0C, 0xC0, 36, 0])), + channel_pressure: ((CableNumber::Cable0, [0xD0, 115]), Ok([0x0D, 0xD0, 115, 0])), + channel_pressure_extra: ((CableNumber::Cable0, [0xD0, 115, 27]), Ok([0x0D, 0xD0, 115, 0])), + pitch_bend: ((CableNumber::Cable0, [0xE0, 93, 46]), Ok([0x0E, 0xE0, 93, 46])), + mtc_quarter_frame: ((CableNumber::Cable0, [0xF1, 102, 46]), Ok([0x02, 0xF1, 102, 0])), + mtc_quarter_frame_extra: ((CableNumber::Cable0, [0xF1, 102, 46, 7]), Ok([0x02, 0xF1, 102, 0])), + song_position_pointer: ((CableNumber::Cable0, [0xF2, 42, 74]), Ok([0x03, 0xF2, 42, 74])), + song_select: ((CableNumber::Cable0, [0xF3, 24]), Ok([0x02, 0xF3, 24, 0])), + song_select_extra: ((CableNumber::Cable0, [0xF3, 24, 96]), Ok([0x02, 0xF3, 24, 0])), + tune_request: ((CableNumber::Cable0, [0xF6]), Ok([0x05, 0xF6, 0, 0])), + tune_request_extra: ((CableNumber::Cable0, [0xF6, 67, 72]), Ok([0x05, 0xF6, 0, 0])), + timing_clock: ((CableNumber::Cable0, [0xF8]), Ok([0x0F, 0xF8, 0, 0])), + timing_clock_extra: ((CableNumber::Cable0, [0xF8, 38, 126]), Ok([0x0F, 0xF8, 0, 0])), + tick: ((CableNumber::Cable0, [0xF9]), Ok([0x0F, 0xF9, 0, 0])), + start: ((CableNumber::Cable0, [0xFA]), Ok([0x0F, 0xFA, 0, 0])), + continue_: ((CableNumber::Cable0, [0xFB]), Ok([0x0F, 0xFB, 0, 0])), + stop: ((CableNumber::Cable0, [0xFC]), Ok([0x0F, 0xFC, 0, 0])), + active_sensing: ((CableNumber::Cable0, [0xFE]), Ok([0x0F, 0xFE, 0, 0])), + system_reset: ((CableNumber::Cable0, [0xFF]), Ok([0x0F, 0xFF, 0, 0])), + sysex_starts: ((CableNumber::Cable0, [0xF0, 1, 2]), Ok([0x04, 0xF0, 1, 2])), + sysex_starts_1byte: ((CableNumber::Cable0, [0xF0]), Err(MidiPacketParsingError::InvalidPayloadSize)), + sysex_starts_2bytes: ((CableNumber::Cable0, [0xF0, 1]), Err(MidiPacketParsingError::InvalidPayloadSize)), + sysex_continues_1byte: ((CableNumber::Cable0, [1]), Ok([0x0F, 1, 0, 0])), + sysex_continues_2bytes: ((CableNumber::Cable0, [1, 2]), Err(MidiPacketParsingError::InvalidPayloadSize)), + sysex_continues_3bytes: ((CableNumber::Cable0, [1, 2, 3]), Ok([0x04, 1, 2, 3])), + sysex_ends_1byte: ((CableNumber::Cable0, [0xF7]), Ok([0x05, 0xF7, 0, 0])), + sysex_ends_2bytes: ((CableNumber::Cable0, [1, 0xF7]), Ok([0x06, 1, 0xF7, 0])), + sysex_ends_3bytes: ((CableNumber::Cable0, [1, 2, 0xF7]), Ok([0x07, 1, 2, 0xF7])), + sysex_2bytes: ((CableNumber::Cable0, [0xF0, 0xF7]), Ok([0x06, 0xF0, 0xF7, 0])), + sysex_3bytes: ((CableNumber::Cable0, [0xF0, 1, 0xF7]), Ok([0x07, 0xF0, 1, 0xF7])), + undefined_f4: ((CableNumber::Cable0, [0xF4]), Err(MidiPacketParsingError::InvalidPayloadStatus)), + undefined_f5: ((CableNumber::Cable0, [0xF5]), Err(MidiPacketParsingError::InvalidPayloadStatus)), + note_off_missing_1byte: ((CableNumber::Cable3, [0x80, 26]), Err(MidiPacketParsingError::InvalidPayloadSize)), + note_off_missing_2bytes: ((CableNumber::Cable3, [0x80]), Err(MidiPacketParsingError::InvalidPayloadSize)), + empty: ((CableNumber::Cable0, []), Err(MidiPacketParsingError::EmptyPayload)), + } + } } From d1f1e01ea244efa496e3f16649bb3ac952a2e87a Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Sun, 29 Dec 2024 11:51:59 +0100 Subject: [PATCH 61/67] Renamed MidiPacketBufferReader to UsbMidiPacketReader --- CHANGELOG.md | 1 + examples/example-esp32s3/src/main.rs | 4 ++-- src/lib.rs | 2 +- src/packet/reader.rs | 8 ++++---- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 782ad58..c43377e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,6 +46,7 @@ This release focuses on: - Renamed `midi_device` module to `class`. - Renamed `usb_midi` module to `packet` and moved it into crate root. - Renamed `midi_packet_reader` module to `reader`. +- Renamed `MidiPacketBufferReader` to `UsbMidiPacketReader`. - Moved `usb_midi_event_packet` code into parent `packet` module. - Moved `channel` and `notes` modules into `message` module. - Moved `message` module to crate root. diff --git a/examples/example-esp32s3/src/main.rs b/examples/example-esp32s3/src/main.rs index bfcf1fc..3b9bc45 100644 --- a/examples/example-esp32s3/src/main.rs +++ b/examples/example-esp32s3/src/main.rs @@ -12,7 +12,7 @@ use heapless::Vec; use midi_convert::midi_types::{Channel, MidiMessage, Note, Value7}; use midi_convert::{parse::MidiTryParseSlice, render_slice::MidiRenderSlice}; use usb_device::prelude::*; -use usbd_midi::{CableNumber, MidiClass, MidiPacketBufferReader, UsbMidiEventPacket}; +use usbd_midi::{CableNumber, MidiClass, UsbMidiEventPacket, UsbMidiPacketReader}; static mut EP_MEMORY: [u32; 1024] = [0; 1024]; @@ -59,7 +59,7 @@ fn main() -> ! { let mut buffer = [0; 64]; if let Ok(size) = midi_class.read(&mut buffer) { - let buffer_reader = MidiPacketBufferReader::new(&buffer, size); + let buffer_reader = UsbMidiPacketReader::new(&buffer, size); for packet in buffer_reader.into_iter().flatten() { if !packet.is_sysex() { // Just a regular 3-byte message that can be processed directly. diff --git a/src/lib.rs b/src/lib.rs index a49745e..dca228c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,7 +9,7 @@ pub mod message; pub use crate::class::{MidiClass, MidiReadError}; pub use crate::packet::cable_number::CableNumber; -pub use crate::packet::reader::MidiPacketBufferReader; +pub use crate::packet::reader::UsbMidiPacketReader; pub use crate::packet::{MidiPacketParsingError, UsbMidiEventPacket}; #[cfg(feature = "message-types")] diff --git a/src/packet/reader.rs b/src/packet/reader.rs index b29dabe..b9b74b4 100644 --- a/src/packet/reader.rs +++ b/src/packet/reader.rs @@ -4,16 +4,16 @@ use crate::class::{MAX_PACKET_SIZE, MIDI_PACKET_SIZE}; use crate::packet::{MidiPacketParsingError, UsbMidiEventPacket}; /// Packet reader with internal buffer for received message. -pub struct MidiPacketBufferReader<'a> { +pub struct UsbMidiPacketReader<'a> { buffer: &'a [u8; MAX_PACKET_SIZE], position: usize, raw_bytes_received: usize, } -impl<'a> MidiPacketBufferReader<'a> { +impl<'a> UsbMidiPacketReader<'a> { /// Creates a new reader. pub fn new(buffer: &'a [u8; MAX_PACKET_SIZE], raw_bytes_received: usize) -> Self { - MidiPacketBufferReader { + UsbMidiPacketReader { buffer, position: 0, raw_bytes_received, @@ -21,7 +21,7 @@ impl<'a> MidiPacketBufferReader<'a> { } } -impl Iterator for MidiPacketBufferReader<'_> { +impl Iterator for UsbMidiPacketReader<'_> { type Item = Result; fn next(&mut self) -> Option { From cdb7416e5c689ffa4522c6e4f77d70973610c928 Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Sun, 29 Dec 2024 11:59:59 +0100 Subject: [PATCH 62/67] Renamed MidiPacketParsingError to UsbMidiEventPacketError --- CHANGELOG.md | 5 +++-- src/class.rs | 4 ++-- src/lib.rs | 2 +- src/message/mod.rs | 20 ++++++++++---------- src/packet/cable_number.rs | 6 +++--- src/packet/code_index_number.rs | 28 ++++++++++++++-------------- src/packet/mod.rs | 28 ++++++++++++++-------------- src/packet/reader.rs | 4 ++-- 8 files changed, 49 insertions(+), 48 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c43377e..6e91ac0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,13 +47,14 @@ This release focuses on: - Renamed `usb_midi` module to `packet` and moved it into crate root. - Renamed `midi_packet_reader` module to `reader`. - Renamed `MidiPacketBufferReader` to `UsbMidiPacketReader`. +- Renamed `MidiPacketParsingError` to `UsbMidiEventPacketError` - Moved `usb_midi_event_packet` code into parent `packet` module. - Moved `channel` and `notes` modules into `message` module. - Moved `message` module to crate root. - Moved `byte` submodules into `message::data` module. - Moved `from_traits` code into parent `data` module. -- Consolidated separate `InvalidCableNumber` struct into `MidiPacketParsingError`. -- Consolidated separate `InvalidCodeIndexNumber` struct into `MidiPacketParsingError`. +- Consolidated separate `InvalidCableNumber` struct into `UsbMidiEventPacketError`. +- Consolidated separate `InvalidCodeIndexNumber` struct into `UsbMidiEventPacketError`. - Converted `CodeIndexNumber` struct to enum. - Moved descriptor constants into class module and made them private. diff --git a/src/class.rs b/src/class.rs index 8971648..bea9c16 100644 --- a/src/class.rs +++ b/src/class.rs @@ -3,7 +3,7 @@ use usb_device::class_prelude::*; use usb_device::Result; -use crate::packet::{MidiPacketParsingError, UsbMidiEventPacket}; +use crate::packet::{UsbMidiEventPacket, UsbMidiEventPacketError}; // Constants for use in descriptors. const USB_AUDIO_CLASS: u8 = 0x01; @@ -42,7 +42,7 @@ pub struct MidiClass<'a, B: UsbBus> { #[derive(Debug, Clone, Eq, PartialEq)] pub enum MidiReadError { /// Parsing of the packet failed. - ParsingFailed(MidiPacketParsingError), + ParsingFailed(UsbMidiEventPacketError), /// USB stack error returned from `usb-device`. UsbError(UsbError), } diff --git a/src/lib.rs b/src/lib.rs index dca228c..35c91c9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,7 +10,7 @@ pub mod message; pub use crate::class::{MidiClass, MidiReadError}; pub use crate::packet::cable_number::CableNumber; pub use crate::packet::reader::UsbMidiPacketReader; -pub use crate::packet::{MidiPacketParsingError, UsbMidiEventPacket}; +pub use crate::packet::{UsbMidiEventPacketError, UsbMidiEventPacket}; #[cfg(feature = "message-types")] pub use crate::message::Message; diff --git a/src/message/mod.rs b/src/message/mod.rs index 8327c45..5505c31 100644 --- a/src/message/mod.rs +++ b/src/message/mod.rs @@ -14,7 +14,7 @@ use crate::message::notes::Note; use crate::message::raw::{Payload, Raw}; use crate::packet::cable_number::CableNumber; use crate::packet::code_index_number::CodeIndexNumber; -use crate::packet::{MidiPacketParsingError, UsbMidiEventPacket}; +use crate::packet::{UsbMidiEventPacket, UsbMidiEventPacketError}; type Velocity = U7; @@ -92,12 +92,12 @@ impl From for Raw { } impl TryFrom<&[u8]> for Message { - type Error = MidiPacketParsingError; + type Error = UsbMidiEventPacketError; fn try_from(data: &[u8]) -> Result { let status_byte = match data.first() { Some(byte) => byte, - None => return Err(MidiPacketParsingError::MissingDataPacket), + None => return Err(UsbMidiEventPacketError::MissingDataPacket), }; let event_type = status_byte & 0b1111_0000; @@ -133,13 +133,13 @@ impl TryFrom<&[u8]> for Message { ControlFunction(get_u7_at(data, 1)?), get_u7_at(data, 2)?, )), - _ => Err(MidiPacketParsingError::InvalidEventType(event_type)), + _ => Err(UsbMidiEventPacketError::InvalidEventType(event_type)), } } } impl TryFrom<&UsbMidiEventPacket> for Message { - type Error = MidiPacketParsingError; + type Error = UsbMidiEventPacketError; fn try_from(value: &UsbMidiEventPacket) -> Result { Self::try_from(&value.as_raw_bytes()[1..]) @@ -188,23 +188,23 @@ impl Message { } } -fn get_note(data: &[u8]) -> Result { +fn get_note(data: &[u8]) -> Result { let note_byte = get_byte_at_position(data, 1)?; match Note::try_from(note_byte) { Ok(note) => Ok(note), - Err(_) => Err(MidiPacketParsingError::InvalidNote(note_byte)), + Err(_) => Err(UsbMidiEventPacketError::InvalidNote(note_byte)), } } -fn get_u7_at(data: &[u8], index: usize) -> Result { +fn get_u7_at(data: &[u8], index: usize) -> Result { let data_byte = get_byte_at_position(data, index)?; Ok(U7::from_clamped(data_byte)) } -fn get_byte_at_position(data: &[u8], index: usize) -> Result { +fn get_byte_at_position(data: &[u8], index: usize) -> Result { match data.get(index) { Some(byte) => Ok(*byte), - None => Err(MidiPacketParsingError::MissingDataPacket), + None => Err(UsbMidiEventPacketError::MissingDataPacket), } } diff --git a/src/packet/cable_number.rs b/src/packet/cable_number.rs index fb128f0..3e8745d 100644 --- a/src/packet/cable_number.rs +++ b/src/packet/cable_number.rs @@ -1,6 +1,6 @@ //! Enum representing the cable number of a packet. -use crate::packet::MidiPacketParsingError; +use crate::packet::UsbMidiEventPacketError; /// The Cable Number (CN) is a value ranging from 0x0 to 0xF /// indicating the number assignment of the Embedded MIDI Jack associated @@ -29,7 +29,7 @@ pub enum CableNumber { } impl TryFrom for CableNumber { - type Error = MidiPacketParsingError; + type Error = UsbMidiEventPacketError; fn try_from(value: u8) -> Result { match value { @@ -49,7 +49,7 @@ impl TryFrom for CableNumber { x if x == CableNumber::Cable13 as u8 => Ok(CableNumber::Cable13), x if x == CableNumber::Cable14 as u8 => Ok(CableNumber::Cable14), x if x == CableNumber::Cable15 as u8 => Ok(CableNumber::Cable15), - _ => Err(MidiPacketParsingError::InvalidCableNumber(value)), + _ => Err(UsbMidiEventPacketError::InvalidCableNumber(value)), } } } diff --git a/src/packet/code_index_number.rs b/src/packet/code_index_number.rs index d466aec..2be49dc 100644 --- a/src/packet/code_index_number.rs +++ b/src/packet/code_index_number.rs @@ -1,6 +1,6 @@ //! Enum representing the code index number of a packet. -use crate::packet::MidiPacketParsingError; +use crate::packet::UsbMidiEventPacketError; /// The Code Index Number(CIN) indicates the classification /// of the bytes in the MIDI_x fields. @@ -43,7 +43,7 @@ pub enum CodeIndexNumber { } impl TryFrom for CodeIndexNumber { - type Error = MidiPacketParsingError; + type Error = UsbMidiEventPacketError; fn try_from(value: u8) -> Result { match value { @@ -79,7 +79,7 @@ impl TryFrom for CodeIndexNumber { Ok(CodeIndexNumber::PitchBendChange) } x if x == CodeIndexNumber::SingleByte as u8 => Ok(CodeIndexNumber::SingleByte), - _ => Err(MidiPacketParsingError::InvalidCodeIndexNumber(value)), + _ => Err(UsbMidiEventPacketError::InvalidCodeIndexNumber(value)), } } } @@ -88,9 +88,9 @@ impl CodeIndexNumber { /// Creates a new number from a MIDI event payload. /// /// The detection is based on the content and ignores the slice length. - pub fn try_from_payload(payload: &[u8]) -> Result { + pub fn try_from_payload(payload: &[u8]) -> Result { let Some(status) = payload.first() else { - return Err(MidiPacketParsingError::EmptyPayload); + return Err(UsbMidiEventPacketError::EmptyPayload); }; if *status < 0xF0 { @@ -112,7 +112,7 @@ impl CodeIndexNumber { } else if payload.len() > 2 { Ok(Self::SysexStartsOrContinues) } else { - Err(MidiPacketParsingError::InvalidPayloadSize) + Err(UsbMidiEventPacketError::InvalidPayloadSize) } } } @@ -126,14 +126,14 @@ impl CodeIndexNumber { } else if payload.len() > 2 { Ok(Self::SysexStartsOrContinues) } else { - Err(MidiPacketParsingError::InvalidPayloadSize) + Err(UsbMidiEventPacketError::InvalidPayloadSize) } } 0xF1 | 0xF3 => Ok(Self::SystemCommon2Bytes), 0xF2 => Ok(Self::SystemCommon3Bytes), 0xF6 | 0xF7 => Ok(Self::SystemCommon1Byte), 0xF8 | 0xF9 | 0xFA | 0xFB | 0xFC | 0xFE | 0xFF => Ok(Self::SingleByte), - _ => Err(MidiPacketParsingError::InvalidPayloadStatus), + _ => Err(UsbMidiEventPacketError::InvalidPayloadStatus), } } } @@ -199,18 +199,18 @@ mod tests { active_sensing: ([0xFE], Ok(CodeIndexNumber::SingleByte)), system_reset: ([0xFF], Ok(CodeIndexNumber::SingleByte)), sysex_starts: ([0xF0, 1, 2], Ok(CodeIndexNumber::SysexStartsOrContinues)), - sysex_starts_1byte: ([0xF0], Err(MidiPacketParsingError::InvalidPayloadSize)), - sysex_starts_2bytes: ([0xF0, 1], Err(MidiPacketParsingError::InvalidPayloadSize)), + sysex_starts_1byte: ([0xF0], Err(UsbMidiEventPacketError::InvalidPayloadSize)), + sysex_starts_2bytes: ([0xF0, 1], Err(UsbMidiEventPacketError::InvalidPayloadSize)), sysex_continues_1byte: ([1], Ok(CodeIndexNumber::SingleByte)), - sysex_continues_2bytes: ([1, 2], Err(MidiPacketParsingError::InvalidPayloadSize)), + sysex_continues_2bytes: ([1, 2], Err(UsbMidiEventPacketError::InvalidPayloadSize)), sysex_continues_3bytes: ([1, 2, 3], Ok(CodeIndexNumber::SysexStartsOrContinues)), sysex_ends_1byte: ([0xF7], Ok(CodeIndexNumber::SystemCommon1Byte)), sysex_ends_2bytes: ([1, 0xF7], Ok(CodeIndexNumber::SysexEnds2Bytes)), sysex_ends_3bytes: ([1, 2, 0xF7], Ok(CodeIndexNumber::SysexEnds3Bytes)), sysex_2bytes: ([0xF0, 0xF7], Ok(CodeIndexNumber::SysexEnds2Bytes)), sysex_3bytes: ([0xF0, 1, 0xF7], Ok(CodeIndexNumber::SysexEnds3Bytes)), - undefined_f4: ([0xF4], Err(MidiPacketParsingError::InvalidPayloadStatus)), - undefined_f5: ([0xF5], Err(MidiPacketParsingError::InvalidPayloadStatus)), - empty: ([], Err(MidiPacketParsingError::EmptyPayload)), + undefined_f4: ([0xF4], Err(UsbMidiEventPacketError::InvalidPayloadStatus)), + undefined_f5: ([0xF5], Err(UsbMidiEventPacketError::InvalidPayloadStatus)), + empty: ([], Err(UsbMidiEventPacketError::EmptyPayload)), } } diff --git a/src/packet/mod.rs b/src/packet/mod.rs index edf70ac..17a11eb 100644 --- a/src/packet/mod.rs +++ b/src/packet/mod.rs @@ -25,7 +25,7 @@ impl From for [u8; 4] { /// Error variants for parsing the packet. #[derive(Debug, Clone, Eq, PartialEq)] -pub enum MidiPacketParsingError { +pub enum UsbMidiEventPacketError { /// Invalid packet. InvalidPacket, /// Invalid note. @@ -47,11 +47,11 @@ pub enum MidiPacketParsingError { } impl TryFrom<&[u8]> for UsbMidiEventPacket { - type Error = MidiPacketParsingError; + type Error = UsbMidiEventPacketError; fn try_from(value: &[u8]) -> Result { let Ok(raw) = value.try_into() else { - return Err(MidiPacketParsingError::InvalidPacket); + return Err(UsbMidiEventPacketError::InvalidPacket); }; Ok(Self { raw }) @@ -101,12 +101,12 @@ impl UsbMidiEventPacket { pub fn try_from_payload_bytes( cable: CableNumber, bytes: &[u8], - ) -> Result { + ) -> Result { let cin = CodeIndexNumber::try_from_payload(bytes)?; let payload_size = cin.payload_size(); if bytes.len() < payload_size { - return Err(MidiPacketParsingError::InvalidPayloadSize); + return Err(UsbMidiEventPacketError::InvalidPayloadSize); } let mut raw = [0; 4]; @@ -220,7 +220,7 @@ mod tests { let ((cable, payload), expected) = $value; let payload = payload.as_slice(); let encoded = UsbMidiEventPacket::try_from_payload_bytes(cable, payload); - let expected: Result<[u8; 4], MidiPacketParsingError> = expected; + let expected: Result<[u8; 4], UsbMidiEventPacketError> = expected; assert_eq!(encoded, expected.map( |v| UsbMidiEventPacket::try_from(v.as_slice()).unwrap()) ); @@ -255,21 +255,21 @@ mod tests { active_sensing: ((CableNumber::Cable0, [0xFE]), Ok([0x0F, 0xFE, 0, 0])), system_reset: ((CableNumber::Cable0, [0xFF]), Ok([0x0F, 0xFF, 0, 0])), sysex_starts: ((CableNumber::Cable0, [0xF0, 1, 2]), Ok([0x04, 0xF0, 1, 2])), - sysex_starts_1byte: ((CableNumber::Cable0, [0xF0]), Err(MidiPacketParsingError::InvalidPayloadSize)), - sysex_starts_2bytes: ((CableNumber::Cable0, [0xF0, 1]), Err(MidiPacketParsingError::InvalidPayloadSize)), + sysex_starts_1byte: ((CableNumber::Cable0, [0xF0]), Err(UsbMidiEventPacketError::InvalidPayloadSize)), + sysex_starts_2bytes: ((CableNumber::Cable0, [0xF0, 1]), Err(UsbMidiEventPacketError::InvalidPayloadSize)), sysex_continues_1byte: ((CableNumber::Cable0, [1]), Ok([0x0F, 1, 0, 0])), - sysex_continues_2bytes: ((CableNumber::Cable0, [1, 2]), Err(MidiPacketParsingError::InvalidPayloadSize)), + sysex_continues_2bytes: ((CableNumber::Cable0, [1, 2]), Err(UsbMidiEventPacketError::InvalidPayloadSize)), sysex_continues_3bytes: ((CableNumber::Cable0, [1, 2, 3]), Ok([0x04, 1, 2, 3])), sysex_ends_1byte: ((CableNumber::Cable0, [0xF7]), Ok([0x05, 0xF7, 0, 0])), sysex_ends_2bytes: ((CableNumber::Cable0, [1, 0xF7]), Ok([0x06, 1, 0xF7, 0])), sysex_ends_3bytes: ((CableNumber::Cable0, [1, 2, 0xF7]), Ok([0x07, 1, 2, 0xF7])), sysex_2bytes: ((CableNumber::Cable0, [0xF0, 0xF7]), Ok([0x06, 0xF0, 0xF7, 0])), sysex_3bytes: ((CableNumber::Cable0, [0xF0, 1, 0xF7]), Ok([0x07, 0xF0, 1, 0xF7])), - undefined_f4: ((CableNumber::Cable0, [0xF4]), Err(MidiPacketParsingError::InvalidPayloadStatus)), - undefined_f5: ((CableNumber::Cable0, [0xF5]), Err(MidiPacketParsingError::InvalidPayloadStatus)), - note_off_missing_1byte: ((CableNumber::Cable3, [0x80, 26]), Err(MidiPacketParsingError::InvalidPayloadSize)), - note_off_missing_2bytes: ((CableNumber::Cable3, [0x80]), Err(MidiPacketParsingError::InvalidPayloadSize)), - empty: ((CableNumber::Cable0, []), Err(MidiPacketParsingError::EmptyPayload)), + undefined_f4: ((CableNumber::Cable0, [0xF4]), Err(UsbMidiEventPacketError::InvalidPayloadStatus)), + undefined_f5: ((CableNumber::Cable0, [0xF5]), Err(UsbMidiEventPacketError::InvalidPayloadStatus)), + note_off_missing_1byte: ((CableNumber::Cable3, [0x80, 26]), Err(UsbMidiEventPacketError::InvalidPayloadSize)), + note_off_missing_2bytes: ((CableNumber::Cable3, [0x80]), Err(UsbMidiEventPacketError::InvalidPayloadSize)), + empty: ((CableNumber::Cable0, []), Err(UsbMidiEventPacketError::EmptyPayload)), } } } diff --git a/src/packet/reader.rs b/src/packet/reader.rs index b9b74b4..0e6712d 100644 --- a/src/packet/reader.rs +++ b/src/packet/reader.rs @@ -1,7 +1,7 @@ //! Reader for received packets. use crate::class::{MAX_PACKET_SIZE, MIDI_PACKET_SIZE}; -use crate::packet::{MidiPacketParsingError, UsbMidiEventPacket}; +use crate::packet::{UsbMidiEventPacketError, UsbMidiEventPacket}; /// Packet reader with internal buffer for received message. pub struct UsbMidiPacketReader<'a> { @@ -22,7 +22,7 @@ impl<'a> UsbMidiPacketReader<'a> { } impl Iterator for UsbMidiPacketReader<'_> { - type Item = Result; + type Item = Result; fn next(&mut self) -> Option { if self.position <= MAX_PACKET_SIZE && self.position < self.raw_bytes_received { From d9728d85ee37bd8ccc918da0b3c6a9d1f2b98bd4 Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Sun, 29 Dec 2024 12:04:24 +0100 Subject: [PATCH 63/67] Examples update --- README.md | 6 +++--- examples/example-esp32s3/src/main.rs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 2ca2b2c..82e93e0 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ use usbd_midi::{ message::{channel::Channel, notes::Note}, Message, MidiClass, - MidiPacketBufferReader, + UsbMidiPacketReader, }; // Prerequisites, must be setup according to the used board. @@ -46,8 +46,8 @@ loop { let mut buffer = [0; 64]; if let Ok(size) = midi.read(&mut buffer) { - let buffer_reader = MidiPacketBufferReader::new(&buffer, size); - for packet in buffer_reader.into_iter() { + let packet_reader = UsbMidiPacketReader::new(&buffer, size); + for packet in packet_reader.into_iter() { if let Ok(packet) = packet { match Message::try_from(&packet).unwrap() { Message::NoteOn(Channel1, Note::C2, ..) => { diff --git a/examples/example-esp32s3/src/main.rs b/examples/example-esp32s3/src/main.rs index 3b9bc45..10433e8 100644 --- a/examples/example-esp32s3/src/main.rs +++ b/examples/example-esp32s3/src/main.rs @@ -59,8 +59,8 @@ fn main() -> ! { let mut buffer = [0; 64]; if let Ok(size) = midi_class.read(&mut buffer) { - let buffer_reader = UsbMidiPacketReader::new(&buffer, size); - for packet in buffer_reader.into_iter().flatten() { + let packet_reader = UsbMidiPacketReader::new(&buffer, size); + for packet in packet_reader.into_iter().flatten() { if !packet.is_sysex() { // Just a regular 3-byte message that can be processed directly. let message = MidiMessage::try_parse_slice(packet.payload_bytes()); From 9b57fdca4a5e2414d007ce91504bb94aa1c55fa4 Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Sun, 29 Dec 2024 12:08:13 +0100 Subject: [PATCH 64/67] Renamed MidiReadError to UsbMidiReadError --- CHANGELOG.md | 1 + src/class.rs | 2 +- src/lib.rs | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e91ac0..e02db81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,7 @@ This release focuses on: - Renamed `midi_packet_reader` module to `reader`. - Renamed `MidiPacketBufferReader` to `UsbMidiPacketReader`. - Renamed `MidiPacketParsingError` to `UsbMidiEventPacketError` +- Renamed `MidiReadError` to `UsbMidiReadError` - Moved `usb_midi_event_packet` code into parent `packet` module. - Moved `channel` and `notes` modules into `message` module. - Moved `message` module to crate root. diff --git a/src/class.rs b/src/class.rs index bea9c16..9b7197c 100644 --- a/src/class.rs +++ b/src/class.rs @@ -40,7 +40,7 @@ pub struct MidiClass<'a, B: UsbBus> { /// Error variants for read operations. #[derive(Debug, Clone, Eq, PartialEq)] -pub enum MidiReadError { +pub enum UsbMidiReadError { /// Parsing of the packet failed. ParsingFailed(UsbMidiEventPacketError), /// USB stack error returned from `usb-device`. diff --git a/src/lib.rs b/src/lib.rs index 35c91c9..305f3a3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,10 +7,10 @@ pub mod packet; #[cfg(feature = "message-types")] pub mod message; -pub use crate::class::{MidiClass, MidiReadError}; +pub use crate::class::{MidiClass, UsbMidiReadError}; pub use crate::packet::cable_number::CableNumber; pub use crate::packet::reader::UsbMidiPacketReader; -pub use crate::packet::{UsbMidiEventPacketError, UsbMidiEventPacket}; +pub use crate::packet::{UsbMidiEventPacket, UsbMidiEventPacketError}; #[cfg(feature = "message-types")] pub use crate::message::Message; From f718a27afd5aee71533aa8adf2c63f38d7c72da2 Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Sun, 29 Dec 2024 12:15:28 +0100 Subject: [PATCH 65/67] Renamed MidiClass to UsbMidiClass --- CHANGELOG.md | 5 +++-- README.md | 4 ++-- examples/example-esp32s3/src/main.rs | 4 ++-- src/class.rs | 14 +++++++------- src/lib.rs | 2 +- 5 files changed, 15 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e02db81..c370c30 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,8 +41,8 @@ This release focuses on: ### Changed -- Set edition to 2021. -- Renamed `MidiClass::send_message` function to `MidiClass::send_packet`. +- Renamed `MidiClass` to `UsbMidiClass`. +- Renamed `UsbMidiClass::send_message` function to `UsbMidiClass::send_packet`. - Renamed `midi_device` module to `class`. - Renamed `usb_midi` module to `packet` and moved it into crate root. - Renamed `midi_packet_reader` module to `reader`. @@ -58,6 +58,7 @@ This release focuses on: - Consolidated separate `InvalidCodeIndexNumber` struct into `UsbMidiEventPacketError`. - Converted `CodeIndexNumber` struct to enum. - Moved descriptor constants into class module and made them private. +- Set edition to 2021. ### Removed diff --git a/README.md b/README.md index 82e93e0..b138db2 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ use usb_device::prelude::*; use usbd_midi::{ message::{channel::Channel, notes::Note}, Message, - MidiClass, + UsbMidiClass, UsbMidiPacketReader, }; @@ -26,7 +26,7 @@ let mut led = todo!(); // Must implement `embedded_hal::digital::OutputPin`. let usb_bus = todo!(); // Must be of type `usb_device::bus::UsbBusAllocator`. // Create a MIDI class with 1 input and 1 output jack. -let mut midi = MidiClass::new(&usb_bus, 1, 1).unwrap(); +let mut midi = UsbMidiClass::new(&usb_bus, 1, 1).unwrap(); let mut usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x16c0, 0x5e4)) .device_class(0) diff --git a/examples/example-esp32s3/src/main.rs b/examples/example-esp32s3/src/main.rs index 10433e8..be6809b 100644 --- a/examples/example-esp32s3/src/main.rs +++ b/examples/example-esp32s3/src/main.rs @@ -12,7 +12,7 @@ use heapless::Vec; use midi_convert::midi_types::{Channel, MidiMessage, Note, Value7}; use midi_convert::{parse::MidiTryParseSlice, render_slice::MidiRenderSlice}; use usb_device::prelude::*; -use usbd_midi::{CableNumber, MidiClass, UsbMidiEventPacket, UsbMidiPacketReader}; +use usbd_midi::{CableNumber, UsbMidiClass, UsbMidiEventPacket, UsbMidiPacketReader}; static mut EP_MEMORY: [u32; 1024] = [0; 1024]; @@ -32,7 +32,7 @@ fn main() -> ! { ); // Create a MIDI class with 1 input and 1 output jack. - let mut midi_class = MidiClass::new(&usb_bus_allocator, 1, 1).unwrap(); + let mut midi_class = UsbMidiClass::new(&usb_bus_allocator, 1, 1).unwrap(); // Build the device. It's important to use `0` for the class and subclass fields because // otherwise the device will not enumerate correctly on certain hosts. diff --git a/src/class.rs b/src/class.rs index 9b7197c..0cf68a9 100644 --- a/src/class.rs +++ b/src/class.rs @@ -29,7 +29,7 @@ pub const MIDI_PACKET_SIZE: usize = 4; pub const MAX_PACKET_SIZE: usize = 64; /// Packet-level implementation of a USB MIDI device. -pub struct MidiClass<'a, B: UsbBus> { +pub struct UsbMidiClass<'a, B: UsbBus> { standard_ac: InterfaceNumber, standard_mc: InterfaceNumber, standard_bulkout: EndpointOut<'a, B>, @@ -47,23 +47,23 @@ pub enum UsbMidiReadError { UsbError(UsbError), } -/// Error returned when passing invalid arguments to `MidiClass::new`. +/// Error returned when passing invalid arguments to `UsbMidiClass::new`. #[derive(Debug)] pub struct InvalidArguments; -impl MidiClass<'_, B> { - /// Creates a new MidiClass with the provided UsbBus and `n_in/out_jacks` embedded input/output jacks +impl UsbMidiClass<'_, B> { + /// Creates a new UsbMidiClass with the provided UsbBus and `n_in/out_jacks` embedded input/output jacks /// (or "cables", depending on the terminology). /// Note that a maximum of 16 in and 16 out jacks is supported. pub fn new( alloc: &UsbBusAllocator, n_in_jacks: u8, n_out_jacks: u8, - ) -> core::result::Result, InvalidArguments> { + ) -> core::result::Result, InvalidArguments> { if n_in_jacks > 16 || n_out_jacks > 16 { return Err(InvalidArguments); } - Ok(MidiClass { + Ok(UsbMidiClass { standard_ac: alloc.interface(), standard_mc: alloc.interface(), standard_bulkout: alloc.bulk(MAX_PACKET_SIZE as u16), @@ -114,7 +114,7 @@ impl MidiClass<'_, B> { } } -impl UsbClass for MidiClass<'_, B> { +impl UsbClass for UsbMidiClass<'_, B> { fn get_configuration_descriptors(&self, writer: &mut DescriptorWriter) -> Result<()> { // AUDIO CONTROL STANDARD writer.interface( diff --git a/src/lib.rs b/src/lib.rs index 305f3a3..7db71d4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,7 +7,7 @@ pub mod packet; #[cfg(feature = "message-types")] pub mod message; -pub use crate::class::{MidiClass, UsbMidiReadError}; +pub use crate::class::{UsbMidiClass, UsbMidiReadError}; pub use crate::packet::cable_number::CableNumber; pub use crate::packet::reader::UsbMidiPacketReader; pub use crate::packet::{UsbMidiEventPacket, UsbMidiEventPacketError}; From ae3e4faba0e8e93275c203f99bd66227679f37ae Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Fri, 3 Jan 2025 18:50:09 +0100 Subject: [PATCH 66/67] Run cargo fmt --- src/packet/reader.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/packet/reader.rs b/src/packet/reader.rs index 0e6712d..a665c99 100644 --- a/src/packet/reader.rs +++ b/src/packet/reader.rs @@ -1,7 +1,7 @@ //! Reader for received packets. use crate::class::{MAX_PACKET_SIZE, MIDI_PACKET_SIZE}; -use crate::packet::{UsbMidiEventPacketError, UsbMidiEventPacket}; +use crate::packet::{UsbMidiEventPacket, UsbMidiEventPacketError}; /// Packet reader with internal buffer for received message. pub struct UsbMidiPacketReader<'a> { From 60e817bdcc03a63031a33cb9f614dcba726c1a79 Mon Sep 17 00:00:00 2001 From: Oliver Rockstedt Date: Fri, 3 Jan 2025 18:52:21 +0100 Subject: [PATCH 67/67] Preparing for 0.4.0 release --- CHANGELOG.md | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c370c30..6069d29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). -## [Unreleased] +## [0.4.0] - 2025-01-03 This release focuses on: diff --git a/Cargo.toml b/Cargo.toml index 2df4025..d1720e5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "usbd-midi" -version = "0.3.0" +version = "0.4.0" authors = [ "Beau Trepp ", "Florian Jung ",