aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2014-11-25 16:54:10 -0500
committerTakashi Iwai <tiwai@suse.de>2015-01-16 16:51:23 -0500
commit25ca917c0fcdd1d2c4a701905e11751275186310 (patch)
treefb080f775928a406611e1ae7b0053bdf79aee5f1 /sound
parent5c697e5b46efea2c0a5da55208bc71db46698fd1 (diff)
ALSA: firewire-lib: limit the MIDI data rate
Do no send MIDI bytes at the full rate at which FireWire packets happen to be sent, but restrict them to the actual rate of a real MIDI port. This is required by the specification, and prevents data loss when the device's buffer overruns. Signed-off-by: Clemens Ladisch <clemens@ladisch.de> Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Tested-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r--sound/firewire/amdtp.c61
-rw-r--r--sound/firewire/amdtp.h2
2 files changed, 57 insertions, 6 deletions
diff --git a/sound/firewire/amdtp.c b/sound/firewire/amdtp.c
index ef399cadb8a5..0d580186ef1a 100644
--- a/sound/firewire/amdtp.c
+++ b/sound/firewire/amdtp.c
@@ -22,6 +22,12 @@
22#define TICKS_PER_SECOND (TICKS_PER_CYCLE * CYCLES_PER_SECOND) 22#define TICKS_PER_SECOND (TICKS_PER_CYCLE * CYCLES_PER_SECOND)
23 23
24/* 24/*
25 * Nominally 3125 bytes/second, but the MIDI port's clock might be
26 * 1% too slow, and the bus clock 100 ppm too fast.
27 */
28#define MIDI_BYTES_PER_SECOND 3093
29
30/*
25 * Several devices look only at the first eight data blocks. 31 * Several devices look only at the first eight data blocks.
26 * In any case, this is more than enough for the MIDI data rate. 32 * In any case, this is more than enough for the MIDI data rate.
27 */ 33 */
@@ -226,6 +232,14 @@ sfc_found:
226 for (i = 0; i < pcm_channels; i++) 232 for (i = 0; i < pcm_channels; i++)
227 s->pcm_positions[i] = i; 233 s->pcm_positions[i] = i;
228 s->midi_position = s->pcm_channels; 234 s->midi_position = s->pcm_channels;
235
236 /*
237 * We do not know the actual MIDI FIFO size of most devices. Just
238 * assume two bytes, i.e., one byte can be received over the bus while
239 * the previous one is transmitted over MIDI.
240 * (The value here is adjusted for midi_ratelimit_per_packet().)
241 */
242 s->midi_fifo_limit = rate - MIDI_BYTES_PER_SECOND * s->syt_interval + 1;
229} 243}
230EXPORT_SYMBOL(amdtp_stream_set_parameters); 244EXPORT_SYMBOL(amdtp_stream_set_parameters);
231 245
@@ -467,6 +481,36 @@ static void amdtp_fill_pcm_silence(struct amdtp_stream *s,
467 } 481 }
468} 482}
469 483
484/*
485 * To avoid sending MIDI bytes at too high a rate, assume that the receiving
486 * device has a FIFO, and track how much it is filled. This values increases
487 * by one whenever we send one byte in a packet, but the FIFO empties at
488 * a constant rate independent of our packet rate. One packet has syt_interval
489 * samples, so the number of bytes that empty out of the FIFO, per packet(!),
490 * is MIDI_BYTES_PER_SECOND * syt_interval / sample_rate. To avoid storing
491 * fractional values, the values in midi_fifo_used[] are measured in bytes
492 * multiplied by the sample rate.
493 */
494static bool midi_ratelimit_per_packet(struct amdtp_stream *s, unsigned int port)
495{
496 int used;
497
498 used = s->midi_fifo_used[port];
499 if (used == 0) /* common shortcut */
500 return true;
501
502 used -= MIDI_BYTES_PER_SECOND * s->syt_interval;
503 used = max(used, 0);
504 s->midi_fifo_used[port] = used;
505
506 return used < s->midi_fifo_limit;
507}
508
509static void midi_rate_use_one_byte(struct amdtp_stream *s, unsigned int port)
510{
511 s->midi_fifo_used[port] += amdtp_rate_table[s->sfc];
512}
513
470static void amdtp_fill_midi(struct amdtp_stream *s, 514static void amdtp_fill_midi(struct amdtp_stream *s,
471 __be32 *buffer, unsigned int frames) 515 __be32 *buffer, unsigned int frames)
472{ 516{
@@ -474,16 +518,21 @@ static void amdtp_fill_midi(struct amdtp_stream *s,
474 u8 *b; 518 u8 *b;
475 519
476 for (f = 0; f < frames; f++) { 520 for (f = 0; f < frames; f++) {
477 buffer[s->midi_position] = 0;
478 b = (u8 *)&buffer[s->midi_position]; 521 b = (u8 *)&buffer[s->midi_position];
479 522
480 port = (s->data_block_counter + f) % 8; 523 port = (s->data_block_counter + f) % 8;
481 if ((f >= MAX_MIDI_RX_BLOCKS) || 524 if (f < MAX_MIDI_RX_BLOCKS &&
482 (s->midi[port] == NULL) || 525 midi_ratelimit_per_packet(s, port) &&
483 (snd_rawmidi_transmit(s->midi[port], b + 1, 1) <= 0)) 526 s->midi[port] != NULL &&
484 b[0] = 0x80; 527 snd_rawmidi_transmit(s->midi[port], &b[1], 1) == 1) {
485 else 528 midi_rate_use_one_byte(s, port);
486 b[0] = 0x81; 529 b[0] = 0x81;
530 } else {
531 b[0] = 0x80;
532 b[1] = 0;
533 }
534 b[2] = 0;
535 b[3] = 0;
487 536
488 buffer += s->data_block_quadlets; 537 buffer += s->data_block_quadlets;
489 } 538 }
diff --git a/sound/firewire/amdtp.h b/sound/firewire/amdtp.h
index cd4c4dfb3951..8a03a91e728b 100644
--- a/sound/firewire/amdtp.h
+++ b/sound/firewire/amdtp.h
@@ -148,6 +148,8 @@ struct amdtp_stream {
148 bool double_pcm_frames; 148 bool double_pcm_frames;
149 149
150 struct snd_rawmidi_substream *midi[AMDTP_MAX_CHANNELS_FOR_MIDI * 8]; 150 struct snd_rawmidi_substream *midi[AMDTP_MAX_CHANNELS_FOR_MIDI * 8];
151 int midi_fifo_limit;
152 int midi_fifo_used[AMDTP_MAX_CHANNELS_FOR_MIDI * 8];
151 153
152 /* quirk: fixed interval of dbc between previos/current packets. */ 154 /* quirk: fixed interval of dbc between previos/current packets. */
153 unsigned int tx_dbc_interval; 155 unsigned int tx_dbc_interval;