commit 317c9ed2f8acdb612a53bc7ccc581ebf7814a878 Author: beau trepp Date: Sun Sep 15 15:53:49 2019 +0800 Initial midi device implementation diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fa8d85a --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +Cargo.lock +target diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..f1e7323 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "usbd-midi" +version = "0.1.0" +authors = ["beau trepp "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +embedded-hal = "0.2.2" +nb = "0.1.2" +usb-device = {version = "0.2.3", path = "../usb-device" } \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..4adf35f --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,5 @@ +#![no_std] +mod midi_device; + +pub use usb_device::{Result,UsbError}; +pub use crate::midi_device::*; \ No newline at end of file diff --git a/src/midi_device.rs b/src/midi_device.rs new file mode 100644 index 0000000..59766c2 --- /dev/null +++ b/src/midi_device.rs @@ -0,0 +1,156 @@ +use usb_device::class_prelude::*; +use usb_device::Result; + +pub const USB_CLASS_NONE : u8 = 0x00; +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 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; + +pub struct MidiClass<'a,B: UsbBus> { + standard_ac: InterfaceNumber, + standard_mc: InterfaceNumber, + //standard_bulkout: EndpointOut<'a, B>, + standard_bulkin: EndpointIn<'a,B> +} + + +impl MidiClass<'_, B> { + /// Creates a new MidiClass with the provided UsbBus + pub fn new(alloc: &UsbBusAllocator) -> MidiClass<'_, B> { + MidiClass { + standard_ac: alloc.interface(), + standard_mc: alloc.interface(), + //standard_bulkout : alloc.bulk(64), + standard_bulkin: alloc.bulk(64) + } + } + + pub fn note_on(&mut self, chan: u8, note: u8, vel : u8) -> Result { + self.standard_bulkin.write( + &[ + 0x09,//Note-on message (usb-midi) + 0x90 | (chan & 0x0f),// (note-on, normal midi) + note & 0x7f, //note + vel & 0x7f //vel + ]) + } + + pub fn note_off(&mut self, chan: u8, note: u8, vel : u8) -> Result { + self.standard_bulkin.write( + &[ + 0x08,//Note-on message (usb-midi) + 0x80 | (chan & 0x0f),// (note-on, normal midi) + note & 0x7f, //note + vel & 0x7f //vel + ]) + } + +} + +impl UsbClass for MidiClass<'_, B> { + + fn get_configuration_descriptors(&self, writer: &mut DescriptorWriter) -> Result<()> { + + //AUDIO CONTROL STANDARD + + writer.interface( + self.standard_ac, + USB_AUDIO_CLASS, + USB_AUDIOCONTROL_SUBCLASS, + 0 //no protocol, + )?; + + // AUDIO CONTROL EXTRA INFO + writer.write( + CS_INTERFACE, + &[ + HEADER_SUBTYPE, + 0x00,0x01, // REVISION + 0x09,0x00, //SIZE of class specific descriptions + 0x01, //Number of streaming interfaces + 0x01 // MIDIStreaming interface 1 belongs to this AC interface + ] + )?; + + //Streaming Standard + + writer.interface( + self.standard_mc, + USB_AUDIO_CLASS, + USB_MIDISTREAMING_SUBCLASS, + 0, //no protocol + )?; //Num endpoints? + + //Streaming extra info + + writer.write( + CS_INTERFACE, + &[ + MS_HEADER_SUBTYPE, + 0x00,0x01, //REVISION + (0x07 + MIDI_OUT_SIZE),0x00 //Total size of class specific descriptors? (little endian?) + ] + )?; + + //JACKS + +/* writer.write( + CS_INTERFACE, + &[ + MIDI_IN_JACK_SUBTYPE, + EMBEDDED, + 0x01, // id + 0x00 + ] + )?; */ + + writer.write ( + CS_INTERFACE, + &[ + MIDI_OUT_JACK_SUBTYPE, + EMBEDDED, + 0x01,//id + 0x01, // 1 pin + 0x01, // pin 1 + 0x01, //sorta vague source pin? + 0x00 + ] + )?; + +/* writer.endpoint(&self.standard_bulkout)?; + + writer.write( + CS_ENDPOINT, + &[ + MS_GENERAL, + 0x01, + 0x01 + ] + )?; */ + + writer.endpoint(&self.standard_bulkin)?; + + writer.write( + CS_ENDPOINT, + &[ + MS_GENERAL, + 0x01, + 0x01 + ] + )?; + Ok(()) + } + +} \ No newline at end of file