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_mc: InterfaceNumber,
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 {
@ -24,15 +26,25 @@ pub enum MidiReadError {
UsbError(UsbError)
}
#[derive(Debug)]
pub struct InvalidArguments;
impl<B: UsbBus> MidiClass<'_, B> {
/// Creates a new MidiClass with the provided UsbBus
pub fn new(alloc: &UsbBusAllocator<B>) -> MidiClass<'_, B> {
MidiClass {
/// Creates a new MidiClass 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 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_mc: alloc.interface(),
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> {
@ -43,14 +55,21 @@ impl<B: UsbBus> MidiClass<'_, B> {
pub fn read(&mut self, buffer: &mut [u8]) -> Result<usize> {
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> {
fn get_configuration_descriptors(&self, writer: &mut DescriptorWriter) -> Result<()> {
//AUDIO CONTROL STANDARD
writer.interface(
self.standard_ac,
USB_AUDIO_CLASS,
@ -79,64 +98,80 @@ impl<B: UsbBus> UsbClass<B> for MidiClass<'_, B> {
0, //no protocol
)?; //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,
&[
MS_HEADER_SUBTYPE,
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
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(
CS_INTERFACE,
&[
MIDI_IN_JACK_SUBTYPE,
EMBEDDED,
0x01, // id
0x00
]
)?;
for i in 0..self.n_out_jacks {
writer.write ( // len = 9 = MIDI_OUT_SIZE
CS_INTERFACE,
&[
MIDI_OUT_JACK_SUBTYPE,
EMBEDDED,
self.out_jack_id(i), //id
0x01, // 1 pin
self.in_jack_id(i), // pin 1
0x01, //sorta vague source pin?
0x00
]
)?;
}
writer.write (
CS_INTERFACE,
&[
MIDI_OUT_JACK_SUBTYPE,
EMBEDDED,
0x01,//id
0x01, // 1 pin
0x01, // pin 1
0x01, //sorta vague source pin?
0x00
]
)?;
let mut endpoint_data = [
MS_GENERAL,
0, // number of jacks. must be filled in!
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 // jack mappings. must be filled in and cropped.
];
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,
&[
MS_GENERAL,
0x01,
0x01
]
&endpoint_data[0..2+self.n_in_jacks as usize]
)?;
writer.endpoint(&self.standard_bulkin)?;
writer.write(
writer.endpoint(&self.standard_bulkin)?; // len = 7
endpoint_data[1] = self.n_out_jacks;
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,
&[
MS_GENERAL,
0x01,
0x01
]
&endpoint_data[0..2+self.n_out_jacks as usize]
)?;
let midi_streaming_end_byte = writer.position();
assert!(midi_streaming_end_byte - midi_streaming_start_byte == midi_streaming_total_length);
Ok(())
}
}
}