Skip to content

Commit e9f280e

Browse files
committed
ALSA: seq: oss: Send fragmented SysEx messages immediately
JIRA: https://issues.redhat.com/browse/RHEL-76110 commit 20ce9de Author: Takashi Iwai <tiwai@suse.de> Date: Tue Dec 31 12:55:18 2024 +0100 ALSA: seq: oss: Send fragmented SysEx messages immediately The recent bug report spotted on the old OSS sequencer code that tries to combine incoming SysEx messages to a single sequencer event. This is good, per se, but it has more demerits: - The sysex message delivery is delayed until the very last event - The use of internal buffer forced the serialization The recent fix in commit 0179488 ("ALSA: seq: oss: Fix races at processing SysEx messages") addressed the latter, but a better fix is to handle the sysex messages immediately, i.e. just send each incoming fragmented sysex message as is. And this patch implements that. This resulted in a significant cleanup as well. Note that the only caller of snd_seq_oss_synth_sysex() is snd_seq_oss_process_event(), and all its callers dispatch the event immediately, so we can just put the passed buffer pointer to the event record to be handled. Reported-and-tested-by: Kun Hu <huk23@m.fudan.edu.cn> Link: https://lore.kernel.org/2B7E93E4-B13A-4AE4-8E87-306A8EE9BBB7@m.fudan.edu.cn Link: https://patch.msgid.link/20241231115523.15796-1-tiwai@suse.de Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <jkysela@redhat.com>
1 parent 9fb03a0 commit e9f280e

File tree

2 files changed

+14
-67
lines changed

2 files changed

+14
-67
lines changed

sound/core/seq/oss/seq_oss_device.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ struct seq_oss_chinfo {
5555
struct seq_oss_synthinfo {
5656
struct snd_seq_oss_arg arg;
5757
struct seq_oss_chinfo *ch;
58-
struct seq_oss_synth_sysex *sysex;
5958
int nr_voices;
6059
int opened;
6160
int is_midi;

sound/core/seq/oss/seq_oss_synth.c

Lines changed: 14 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,6 @@
2626
* definition of synth info records
2727
*/
2828

29-
/* sysex buffer */
30-
struct seq_oss_synth_sysex {
31-
int len;
32-
int skip;
33-
unsigned char buf[MAX_SYSEX_BUFLEN];
34-
};
35-
3629
/* synth info */
3730
struct seq_oss_synth {
3831
int seq_device;
@@ -66,7 +59,6 @@ static struct seq_oss_synth midi_synth_dev = {
6659
};
6760

6861
static DEFINE_SPINLOCK(register_lock);
69-
static DEFINE_MUTEX(sysex_mutex);
7062

7163
/*
7264
* prototypes
@@ -319,8 +311,6 @@ snd_seq_oss_synth_cleanup(struct seq_oss_devinfo *dp)
319311
}
320312
snd_use_lock_free(&rec->use_lock);
321313
}
322-
kfree(info->sysex);
323-
info->sysex = NULL;
324314
kfree(info->ch);
325315
info->ch = NULL;
326316
}
@@ -396,8 +386,6 @@ snd_seq_oss_synth_reset(struct seq_oss_devinfo *dp, int dev)
396386
info = get_synthinfo_nospec(dp, dev);
397387
if (!info || !info->opened)
398388
return;
399-
if (info->sysex)
400-
info->sysex->len = 0; /* reset sysex */
401389
reset_channels(info);
402390
if (info->is_midi) {
403391
if (midi_synth_dev.opened <= 0)
@@ -409,8 +397,6 @@ snd_seq_oss_synth_reset(struct seq_oss_devinfo *dp, int dev)
409397
dp->file_mode) < 0) {
410398
midi_synth_dev.opened--;
411399
info->opened = 0;
412-
kfree(info->sysex);
413-
info->sysex = NULL;
414400
kfree(info->ch);
415401
info->ch = NULL;
416402
}
@@ -483,64 +469,26 @@ snd_seq_oss_synth_info(struct seq_oss_devinfo *dp, int dev)
483469

484470
/*
485471
* receive OSS 6 byte sysex packet:
486-
* the full sysex message will be sent if it reaches to the end of data
487-
* (0xff).
472+
* the event is filled and prepared for sending immediately
473+
* (i.e. sysex messages are fragmented)
488474
*/
489475
int
490476
snd_seq_oss_synth_sysex(struct seq_oss_devinfo *dp, int dev, unsigned char *buf, struct snd_seq_event *ev)
491477
{
492-
int i, send;
493-
unsigned char *dest;
494-
struct seq_oss_synth_sysex *sysex;
495-
struct seq_oss_synthinfo *info;
478+
unsigned char *p;
479+
int len = 6;
496480

497-
info = snd_seq_oss_synth_info(dp, dev);
498-
if (!info)
499-
return -ENXIO;
481+
p = memchr(buf, 0xff, 6);
482+
if (p)
483+
len = p - buf + 1;
500484

501-
guard(mutex)(&sysex_mutex);
502-
sysex = info->sysex;
503-
if (sysex == NULL) {
504-
sysex = kzalloc(sizeof(*sysex), GFP_KERNEL);
505-
if (sysex == NULL)
506-
return -ENOMEM;
507-
info->sysex = sysex;
508-
}
509-
510-
send = 0;
511-
dest = sysex->buf + sysex->len;
512-
/* copy 6 byte packet to the buffer */
513-
for (i = 0; i < 6; i++) {
514-
if (buf[i] == 0xff) {
515-
send = 1;
516-
break;
517-
}
518-
dest[i] = buf[i];
519-
sysex->len++;
520-
if (sysex->len >= MAX_SYSEX_BUFLEN) {
521-
sysex->len = 0;
522-
sysex->skip = 1;
523-
break;
524-
}
525-
}
526-
527-
if (sysex->len && send) {
528-
if (sysex->skip) {
529-
sysex->skip = 0;
530-
sysex->len = 0;
531-
return -EINVAL; /* skip */
532-
}
533-
/* copy the data to event record and send it */
534-
ev->flags = SNDRV_SEQ_EVENT_LENGTH_VARIABLE;
535-
if (snd_seq_oss_synth_addr(dp, dev, ev))
536-
return -EINVAL;
537-
ev->data.ext.len = sysex->len;
538-
ev->data.ext.ptr = sysex->buf;
539-
sysex->len = 0;
540-
return 0;
541-
}
542-
543-
return -EINVAL; /* skip */
485+
/* copy the data to event record and send it */
486+
if (snd_seq_oss_synth_addr(dp, dev, ev))
487+
return -EINVAL;
488+
ev->flags = SNDRV_SEQ_EVENT_LENGTH_VARIABLE;
489+
ev->data.ext.len = len;
490+
ev->data.ext.ptr = buf;
491+
return 0;
544492
}
545493

546494
/*

0 commit comments

Comments
 (0)