diff options
author | Clemens Ladisch <clemens@ladisch.de> | 2014-11-25 16:54:10 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2015-01-16 16:51:23 -0500 |
commit | 25ca917c0fcdd1d2c4a701905e11751275186310 (patch) | |
tree | fb080f775928a406611e1ae7b0053bdf79aee5f1 /sound | |
parent | 5c697e5b46efea2c0a5da55208bc71db46698fd1 (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.c | 61 | ||||
-rw-r--r-- | sound/firewire/amdtp.h | 2 |
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 | } |
230 | EXPORT_SYMBOL(amdtp_stream_set_parameters); | 244 | EXPORT_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 | */ | ||
494 | static 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 | |||
509 | static 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 | |||
470 | static void amdtp_fill_midi(struct amdtp_stream *s, | 514 | static 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; |