Allow creating multiple MIDI in and out jacks

This commit is contained in:
Florian Jung 2021-03-21 22:25:09 +01:00
parent 49484f0b15
commit 0dfe89da04

View file

@ -16,7 +16,9 @@ pub struct MidiClass<'a,B: UsbBus> {
standard_ac: InterfaceNumber, standard_ac: InterfaceNumber,
standard_mc: InterfaceNumber, standard_mc: InterfaceNumber,
standard_bulkout: EndpointOut<'a, B>, standard_bulkout: EndpointOut<'a, B>,
standard_bulkin: EndpointIn<'a,B> standard_bulkin: EndpointIn<'a,B>,
n_in_jacks: u8,
n_out_jacks: u8,
} }
pub enum MidiReadError { pub enum MidiReadError {
@ -24,15 +26,25 @@ pub enum MidiReadError {
UsbError(UsbError) UsbError(UsbError)
} }
#[derive(Debug)]
pub struct InvalidArguments;
impl<B: UsbBus> MidiClass<'_, B> { impl<B: UsbBus> MidiClass<'_, B> {
/// Creates a new MidiClass with the provided UsbBus /// Creates a new MidiClass with the provided UsbBus and `n_in/out_jacks` embedded input/output jacks (or "cables",
pub fn new(alloc: &UsbBusAllocator<B>) -> MidiClass<'_, B> { /// depending on the terminology).
MidiClass { /// Note that a maximum of 16 in and 16 out jacks are supported.
pub fn new(alloc: &UsbBusAllocator<B>, n_in_jacks: u8, n_out_jacks: u8) -> core::result::Result<MidiClass<'_, B>, InvalidArguments> {
if n_in_jacks >= 16 || n_out_jacks >= 16 {
return Err(InvalidArguments);
}
Ok(MidiClass {
standard_ac: alloc.interface(), standard_ac: alloc.interface(),
standard_mc: alloc.interface(), standard_mc: alloc.interface(),
standard_bulkout : alloc.bulk(MAX_PACKET_SIZE as u16), standard_bulkout : alloc.bulk(MAX_PACKET_SIZE as u16),
standard_bulkin: alloc.bulk(MAX_PACKET_SIZE as u16) standard_bulkin: alloc.bulk(MAX_PACKET_SIZE as u16),
} n_in_jacks,
n_out_jacks
})
} }
pub fn send_message(&mut self, usb_midi:UsbMidiEventPacket) -> Result<usize> { pub fn send_message(&mut self, usb_midi:UsbMidiEventPacket) -> Result<usize> {
@ -43,14 +55,21 @@ impl<B: UsbBus> MidiClass<'_, B> {
pub fn read(&mut self, buffer: &mut [u8]) -> Result<usize> { pub fn read(&mut self, buffer: &mut [u8]) -> Result<usize> {
self.standard_bulkout.read(buffer) self.standard_bulkout.read(buffer)
} }
/// calculates the index'th midi in jack id
fn in_jack_id(&self, index: u8) -> u8 {
return index + 1;
}
/// calculates the index'th midi in jack id
fn out_jack_id(&self, index: u8) -> u8 {
return self.n_in_jacks + index + 1;
}
} }
impl<B: UsbBus> UsbClass<B> for MidiClass<'_, B> { impl<B: UsbBus> UsbClass<B> for MidiClass<'_, B> {
fn get_configuration_descriptors(&self, writer: &mut DescriptorWriter) -> Result<()> { fn get_configuration_descriptors(&self, writer: &mut DescriptorWriter) -> Result<()> {
//AUDIO CONTROL STANDARD //AUDIO CONTROL STANDARD
writer.interface( writer.interface(
self.standard_ac, self.standard_ac,
USB_AUDIO_CLASS, USB_AUDIO_CLASS,
@ -79,64 +98,80 @@ impl<B: UsbBus> UsbClass<B> for MidiClass<'_, B> {
0, //no protocol 0, //no protocol
)?; //Num endpoints? )?; //Num endpoints?
//Streaming extra info let midi_streaming_start_byte = writer.position();
let midi_streaming_total_length =
7 + self.n_in_jacks as usize * MIDI_IN_SIZE as usize + self.n_out_jacks as usize * MIDI_OUT_SIZE as usize
+ 7 + (4+self.n_in_jacks as usize) + 7 + (4+self.n_out_jacks as usize);
writer.write( //Streaming extra info
writer.write( // len = 7
CS_INTERFACE, CS_INTERFACE,
&[ &[
MS_HEADER_SUBTYPE, MS_HEADER_SUBTYPE,
0x00,0x01, //REVISION 0x00,0x01, //REVISION
(0x07 + MIDI_OUT_SIZE),0x00 //Total size of class specific descriptors? (little endian?) (midi_streaming_total_length & 0xFF) as u8, ((midi_streaming_total_length >> 8) & 0xFF) as u8
] ]
)?; )?;
//JACKS //JACKS
for i in 0..self.n_in_jacks {
writer.write( // len = 6 = MIDI_IN_SIZE
CS_INTERFACE,
&[
MIDI_IN_JACK_SUBTYPE,
EMBEDDED,
self.in_jack_id(i), // id
0x00
]
)?;
}
writer.write( for i in 0..self.n_out_jacks {
CS_INTERFACE, writer.write ( // len = 9 = MIDI_OUT_SIZE
&[ CS_INTERFACE,
MIDI_IN_JACK_SUBTYPE, &[
EMBEDDED, MIDI_OUT_JACK_SUBTYPE,
0x01, // id EMBEDDED,
0x00 self.out_jack_id(i), //id
] 0x01, // 1 pin
)?; self.in_jack_id(i), // pin 1
0x01, //sorta vague source pin?
0x00
]
)?;
}
writer.write ( let mut endpoint_data = [
CS_INTERFACE, MS_GENERAL,
&[ 0, // number of jacks. must be filled in!
MIDI_OUT_JACK_SUBTYPE, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 // jack mappings. must be filled in and cropped.
EMBEDDED, ];
0x01,//id
0x01, // 1 pin
0x01, // pin 1
0x01, //sorta vague source pin?
0x00
]
)?;
writer.endpoint(&self.standard_bulkout)?; writer.endpoint(&self.standard_bulkout)?; // len = 7
writer.write( endpoint_data[1] = self.n_in_jacks;
for i in 0..self.n_in_jacks {
endpoint_data[2 + i as usize] = self.in_jack_id(i);
}
writer.write( // len = 4 + self.n_in_jacks
CS_ENDPOINT, CS_ENDPOINT,
&[ &endpoint_data[0..2+self.n_in_jacks as usize]
MS_GENERAL,
0x01,
0x01
]
)?; )?;
writer.endpoint(&self.standard_bulkin)?; writer.endpoint(&self.standard_bulkin)?; // len = 7
endpoint_data[1] = self.n_out_jacks;
writer.write( for i in 0..self.n_out_jacks {
endpoint_data[2 + i as usize] = self.out_jack_id(i);
}
writer.write( // len = 4 + self.n_out_jacks
CS_ENDPOINT, CS_ENDPOINT,
&[ &endpoint_data[0..2+self.n_out_jacks as usize]
MS_GENERAL,
0x01,
0x01
]
)?; )?;
let midi_streaming_end_byte = writer.position();
assert!(midi_streaming_end_byte - midi_streaming_start_byte == midi_streaming_total_length);
Ok(()) Ok(())
} }
} }