mirror of
https://github.com/italicsjenga/usbd-midi.git
synced 2024-12-23 12:21:30 +11:00
Allow creating multiple MIDI in and out jacks
This commit is contained in:
parent
49484f0b15
commit
0dfe89da04
|
@ -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(())
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue