Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ALSA: seq: ump: Optimize conversions from SysEx to UMP

The current conversion from the legacy SysEx event to UMP SysEx packet
in the sequencer core has a couple of issues:

* The first packet trims the SysEx start byte (0xf0), hence it
contains only 5 bytes instead of 6. This isn't wrong, per
specification, but it's strange not to fill 6 bytes.

* When the SysEx end marker (0xf7) is placed at the first byte of the
next packet, it'll end up with an empty data just with the END
status. It can be rather folded into the previous packet with the
END status.

This patch tries to address those issues. The first packet may have 6
bytes even with the SysEx start, and an empty packet with the SysEx
end marker is omitted.

Fixes: e9e02819a98a ("ALSA: seq: Automatic conversion of UMP events")
Cc: <stable@vger.kernel.org>
Link: https://patch.msgid.link/20240726143455.3254-1-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>

+25 -16
+25 -16
sound/core/seq/seq_ump_convert.c
··· 1192 1192 { 1193 1193 struct snd_seq_ump_event ev_cvt; 1194 1194 unsigned char status; 1195 - u8 buf[6], *xbuf; 1195 + u8 buf[8], *xbuf; 1196 1196 int offset = 0; 1197 1197 int len, err; 1198 + bool finished = false; 1198 1199 1199 1200 if (!snd_seq_ev_is_variable(event)) 1200 1201 return 0; 1201 1202 1202 1203 setup_ump_event(&ev_cvt, event); 1203 - for (;;) { 1204 + while (!finished) { 1204 1205 len = snd_seq_expand_var_event_at(event, sizeof(buf), buf, offset); 1205 1206 if (len <= 0) 1206 1207 break; 1207 - if (WARN_ON(len > 6)) 1208 + if (WARN_ON(len > sizeof(buf))) 1208 1209 break; 1209 - offset += len; 1210 + 1210 1211 xbuf = buf; 1212 + status = UMP_SYSEX_STATUS_CONTINUE; 1213 + /* truncate the sysex start-marker */ 1211 1214 if (*xbuf == UMP_MIDI1_MSG_SYSEX_START) { 1212 1215 status = UMP_SYSEX_STATUS_START; 1213 - xbuf++; 1214 1216 len--; 1215 - if (len > 0 && xbuf[len - 1] == UMP_MIDI1_MSG_SYSEX_END) { 1216 - status = UMP_SYSEX_STATUS_SINGLE; 1217 - len--; 1218 - } 1219 - } else { 1220 - if (xbuf[len - 1] == UMP_MIDI1_MSG_SYSEX_END) { 1221 - status = UMP_SYSEX_STATUS_END; 1222 - len--; 1223 - } else { 1224 - status = UMP_SYSEX_STATUS_CONTINUE; 1225 - } 1217 + offset++; 1218 + xbuf++; 1226 1219 } 1220 + 1221 + /* if the last of this packet or the 1st byte of the next packet 1222 + * is the end-marker, finish the transfer with this packet 1223 + */ 1224 + if (len > 0 && len < 8 && 1225 + xbuf[len - 1] == UMP_MIDI1_MSG_SYSEX_END) { 1226 + if (status == UMP_SYSEX_STATUS_START) 1227 + status = UMP_SYSEX_STATUS_SINGLE; 1228 + else 1229 + status = UMP_SYSEX_STATUS_END; 1230 + len--; 1231 + finished = true; 1232 + } 1233 + 1234 + len = min(len, 6); 1227 1235 fill_sysex7_ump(dest_port, ev_cvt.ump, status, xbuf, len); 1228 1236 err = __snd_seq_deliver_single_event(dest, dest_port, 1229 1237 (struct snd_seq_event *)&ev_cvt, 1230 1238 atomic, hop); 1231 1239 if (err < 0) 1232 1240 return err; 1241 + offset += len; 1233 1242 } 1234 1243 return 0; 1235 1244 }