Commit 8820a4cf authored by Takashi Sakamoto's avatar Takashi Sakamoto Committed by Takashi Iwai

ALSA: firewire-digi00x: handle all MIDI messages on streaming packets

At a commit 9dc5d31c ("ALSA: firewire-digi00x: handle MIDI messages in
isochronous packets"), a functionality to handle MIDI messages on
isochronous packet was supported. But this includes some of my
misunderstanding. This commit is to fix them.

For digi00x series, first data channel of data blocks in rx/tx packet
includes MIDI messages. The data channel has 0x80 in 8 bit of its MSB,
however it's against IEC 61883-6. Unique data format is applied:
 - Upper 4 bits of LSB represent port number.
  - 0x0: port 1.
  - 0x2: port 2.
  - 0xe: console port.
 - Lower 4 bits of LSB represent the number of included MIDI message bytes;
   0x0/0x1/0x2.
 - Two bytes of middle of this data channel have MIDI bytes.

Especially, MIDI messages from/to console surface are also transferred by
isochronous packets, as well as physical MIDI ports.
Signed-off-by: default avatarTakashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 13e005f9
...@@ -28,6 +28,9 @@ ...@@ -28,6 +28,9 @@
*/ */
#define MAX_MIDI_RX_BLOCKS 8 #define MAX_MIDI_RX_BLOCKS 8
/* 3 = MAX(DOT_MIDI_IN_PORTS, DOT_MIDI_OUT_PORTS) + 1. */
#define MAX_MIDI_PORTS 3
/* /*
* The double-oh-three algorithm was discovered by Robin Gareus and Damien * The double-oh-three algorithm was discovered by Robin Gareus and Damien
* Zammit in 2012, with reverse-engineering for Digi 003 Rack. * Zammit in 2012, with reverse-engineering for Digi 003 Rack.
...@@ -42,10 +45,8 @@ struct amdtp_dot { ...@@ -42,10 +45,8 @@ struct amdtp_dot {
unsigned int pcm_channels; unsigned int pcm_channels;
struct dot_state state; struct dot_state state;
unsigned int midi_ports; struct snd_rawmidi_substream *midi[MAX_MIDI_PORTS];
/* 2 = MAX(DOT_MIDI_IN_PORTS, DOT_MIDI_OUT_PORTS) */ int midi_fifo_used[MAX_MIDI_PORTS];
struct snd_rawmidi_substream *midi[2];
int midi_fifo_used[2];
int midi_fifo_limit; int midi_fifo_limit;
void (*transfer_samples)(struct amdtp_stream *s, void (*transfer_samples)(struct amdtp_stream *s,
...@@ -124,8 +125,8 @@ int amdtp_dot_set_parameters(struct amdtp_stream *s, unsigned int rate, ...@@ -124,8 +125,8 @@ int amdtp_dot_set_parameters(struct amdtp_stream *s, unsigned int rate,
return -EBUSY; return -EBUSY;
/* /*
* A first data channel is for MIDI conformant data channel, the rest is * A first data channel is for MIDI messages, the rest is Multi Bit
* Multi Bit Linear Audio data channel. * Linear Audio data channel.
*/ */
err = amdtp_stream_set_parameters(s, rate, pcm_channels + 1); err = amdtp_stream_set_parameters(s, rate, pcm_channels + 1);
if (err < 0) if (err < 0)
...@@ -135,11 +136,6 @@ int amdtp_dot_set_parameters(struct amdtp_stream *s, unsigned int rate, ...@@ -135,11 +136,6 @@ int amdtp_dot_set_parameters(struct amdtp_stream *s, unsigned int rate,
p->pcm_channels = pcm_channels; p->pcm_channels = pcm_channels;
if (s->direction == AMDTP_IN_STREAM)
p->midi_ports = DOT_MIDI_IN_PORTS;
else
p->midi_ports = DOT_MIDI_OUT_PORTS;
/* /*
* We do not know the actual MIDI FIFO size of most devices. Just * We do not know the actual MIDI FIFO size of most devices. Just
* assume two bytes, i.e., one byte can be received over the bus while * assume two bytes, i.e., one byte can be received over the bus while
...@@ -281,13 +277,25 @@ static void write_midi_messages(struct amdtp_stream *s, __be32 *buffer, ...@@ -281,13 +277,25 @@ static void write_midi_messages(struct amdtp_stream *s, __be32 *buffer,
b = (u8 *)&buffer[0]; b = (u8 *)&buffer[0];
len = 0; len = 0;
if (port < p->midi_ports && if (port < MAX_MIDI_PORTS &&
midi_ratelimit_per_packet(s, port) && midi_ratelimit_per_packet(s, port) &&
p->midi[port] != NULL) p->midi[port] != NULL)
len = snd_rawmidi_transmit(p->midi[port], b + 1, 2); len = snd_rawmidi_transmit(p->midi[port], b + 1, 2);
if (len > 0) { if (len > 0) {
b[3] = (0x10 << port) | len; /*
* Upper 4 bits of LSB represent port number.
* - 0000b: physical MIDI port 1.
* - 0010b: physical MIDI port 2.
* - 1110b: console MIDI port.
*/
if (port == 2)
b[3] = 0xe0;
else if (port == 1)
b[3] = 0x20;
else
b[3] = 0x00;
b[3] |= len;
midi_use_bytes(s, port, len); midi_use_bytes(s, port, len);
} else { } else {
b[1] = 0; b[1] = 0;
...@@ -309,11 +317,22 @@ static void read_midi_messages(struct amdtp_stream *s, __be32 *buffer, ...@@ -309,11 +317,22 @@ static void read_midi_messages(struct amdtp_stream *s, __be32 *buffer,
for (f = 0; f < data_blocks; f++) { for (f = 0; f < data_blocks; f++) {
b = (u8 *)&buffer[0]; b = (u8 *)&buffer[0];
port = b[3] >> 4;
len = b[3] & 0x0f;
if (port < p->midi_ports && p->midi[port] && len > 0) len = b[3] & 0x0f;
snd_rawmidi_receive(p->midi[port], b + 1, len); if (len > 0) {
/*
* Upper 4 bits of LSB represent port number.
* - 0000b: physical MIDI port 1. Use port 0.
* - 1110b: console MIDI port. Use port 2.
*/
if (b[3] >> 4 > 0)
port = 2;
else
port = 0;
if (port < MAX_MIDI_PORTS && p->midi[port])
snd_rawmidi_receive(p->midi[port], b + 1, len);
}
buffer += s->data_block_quadlets; buffer += s->data_block_quadlets;
} }
...@@ -364,7 +383,7 @@ void amdtp_dot_midi_trigger(struct amdtp_stream *s, unsigned int port, ...@@ -364,7 +383,7 @@ void amdtp_dot_midi_trigger(struct amdtp_stream *s, unsigned int port,
{ {
struct amdtp_dot *p = s->protocol; struct amdtp_dot *p = s->protocol;
if (port < p->midi_ports) if (port < MAX_MIDI_PORTS)
ACCESS_ONCE(p->midi[port]) = midi; ACCESS_ONCE(p->midi[port]) = midi;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment