diff options
author | Clemens Ladisch <clemens@ladisch.de> | 2007-08-10 03:40:09 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@perex.cz> | 2007-10-16 09:58:37 -0400 |
commit | bf8c1382c0339e95e89394f59a149610dd2d828f (patch) | |
tree | 09b0f3a7284335981465e7ebd9a495bcb11a4c45 /sound/core/seq | |
parent | 0b664f7206fac9676559e0012d8accc2dc0fc9fd (diff) |
[ALSA] seq_midi_event: fix parsing of missing data bytes
Reorganize the encoder logic to prevent status bytes that appear where
data bytes are expected from being interpreted as data bytes.
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Jaroslav Kysela <perex@suse.cz>
Diffstat (limited to 'sound/core/seq')
-rw-r--r-- | sound/core/seq/seq_midi_event.c | 80 |
1 files changed, 41 insertions, 39 deletions
diff --git a/sound/core/seq/seq_midi_event.c b/sound/core/seq/seq_midi_event.c index 45ba6fc4646a..a15f5e68e0b6 100644 --- a/sound/core/seq/seq_midi_event.c +++ b/sound/core/seq/seq_midi_event.c | |||
@@ -65,32 +65,32 @@ static struct status_event_list { | |||
65 | void (*decode)(struct snd_seq_event *ev, unsigned char *buf); | 65 | void (*decode)(struct snd_seq_event *ev, unsigned char *buf); |
66 | } status_event[] = { | 66 | } status_event[] = { |
67 | /* 0x80 - 0xef */ | 67 | /* 0x80 - 0xef */ |
68 | {SNDRV_SEQ_EVENT_NOTEOFF, 2, note_event, note_decode}, | 68 | {SNDRV_SEQ_EVENT_NOTEOFF, 2, note_event, note_decode}, |
69 | {SNDRV_SEQ_EVENT_NOTEON, 2, note_event, note_decode}, | 69 | {SNDRV_SEQ_EVENT_NOTEON, 2, note_event, note_decode}, |
70 | {SNDRV_SEQ_EVENT_KEYPRESS, 2, note_event, note_decode}, | 70 | {SNDRV_SEQ_EVENT_KEYPRESS, 2, note_event, note_decode}, |
71 | {SNDRV_SEQ_EVENT_CONTROLLER, 2, two_param_ctrl_event, two_param_decode}, | 71 | {SNDRV_SEQ_EVENT_CONTROLLER, 2, two_param_ctrl_event, two_param_decode}, |
72 | {SNDRV_SEQ_EVENT_PGMCHANGE, 1, one_param_ctrl_event, one_param_decode}, | 72 | {SNDRV_SEQ_EVENT_PGMCHANGE, 1, one_param_ctrl_event, one_param_decode}, |
73 | {SNDRV_SEQ_EVENT_CHANPRESS, 1, one_param_ctrl_event, one_param_decode}, | 73 | {SNDRV_SEQ_EVENT_CHANPRESS, 1, one_param_ctrl_event, one_param_decode}, |
74 | {SNDRV_SEQ_EVENT_PITCHBEND, 2, pitchbend_ctrl_event, pitchbend_decode}, | 74 | {SNDRV_SEQ_EVENT_PITCHBEND, 2, pitchbend_ctrl_event, pitchbend_decode}, |
75 | /* invalid */ | 75 | /* invalid */ |
76 | {SNDRV_SEQ_EVENT_NONE, 0, NULL, NULL}, | 76 | {SNDRV_SEQ_EVENT_NONE, -1, NULL, NULL}, |
77 | /* 0xf0 - 0xff */ | 77 | /* 0xf0 - 0xff */ |
78 | {SNDRV_SEQ_EVENT_SYSEX, 1, NULL, NULL}, /* sysex: 0xf0 */ | 78 | {SNDRV_SEQ_EVENT_SYSEX, 1, NULL, NULL}, /* sysex: 0xf0 */ |
79 | {SNDRV_SEQ_EVENT_QFRAME, 1, one_param_event, one_param_decode}, /* 0xf1 */ | 79 | {SNDRV_SEQ_EVENT_QFRAME, 1, one_param_event, one_param_decode}, /* 0xf1 */ |
80 | {SNDRV_SEQ_EVENT_SONGPOS, 2, songpos_event, songpos_decode}, /* 0xf2 */ | 80 | {SNDRV_SEQ_EVENT_SONGPOS, 2, songpos_event, songpos_decode}, /* 0xf2 */ |
81 | {SNDRV_SEQ_EVENT_SONGSEL, 1, one_param_event, one_param_decode}, /* 0xf3 */ | 81 | {SNDRV_SEQ_EVENT_SONGSEL, 1, one_param_event, one_param_decode}, /* 0xf3 */ |
82 | {SNDRV_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xf4 */ | 82 | {SNDRV_SEQ_EVENT_NONE, -1, NULL, NULL}, /* 0xf4 */ |
83 | {SNDRV_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xf5 */ | 83 | {SNDRV_SEQ_EVENT_NONE, -1, NULL, NULL}, /* 0xf5 */ |
84 | {SNDRV_SEQ_EVENT_TUNE_REQUEST, 0, NULL, NULL}, /* 0xf6 */ | 84 | {SNDRV_SEQ_EVENT_TUNE_REQUEST, 0, NULL, NULL}, /* 0xf6 */ |
85 | {SNDRV_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xf7 */ | 85 | {SNDRV_SEQ_EVENT_NONE, -1, NULL, NULL}, /* 0xf7 */ |
86 | {SNDRV_SEQ_EVENT_CLOCK, 0, NULL, NULL}, /* 0xf8 */ | 86 | {SNDRV_SEQ_EVENT_CLOCK, 0, NULL, NULL}, /* 0xf8 */ |
87 | {SNDRV_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xf9 */ | 87 | {SNDRV_SEQ_EVENT_NONE, -1, NULL, NULL}, /* 0xf9 */ |
88 | {SNDRV_SEQ_EVENT_START, 0, NULL, NULL}, /* 0xfa */ | 88 | {SNDRV_SEQ_EVENT_START, 0, NULL, NULL}, /* 0xfa */ |
89 | {SNDRV_SEQ_EVENT_CONTINUE, 0, NULL, NULL}, /* 0xfb */ | 89 | {SNDRV_SEQ_EVENT_CONTINUE, 0, NULL, NULL}, /* 0xfb */ |
90 | {SNDRV_SEQ_EVENT_STOP, 0, NULL, NULL}, /* 0xfc */ | 90 | {SNDRV_SEQ_EVENT_STOP, 0, NULL, NULL}, /* 0xfc */ |
91 | {SNDRV_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xfd */ | 91 | {SNDRV_SEQ_EVENT_NONE, -1, NULL, NULL}, /* 0xfd */ |
92 | {SNDRV_SEQ_EVENT_SENSING, 0, NULL, NULL}, /* 0xfe */ | 92 | {SNDRV_SEQ_EVENT_SENSING, 0, NULL, NULL}, /* 0xfe */ |
93 | {SNDRV_SEQ_EVENT_RESET, 0, NULL, NULL}, /* 0xff */ | 93 | {SNDRV_SEQ_EVENT_RESET, 0, NULL, NULL}, /* 0xff */ |
94 | }; | 94 | }; |
95 | 95 | ||
96 | static int extra_decode_ctrl14(struct snd_midi_event *dev, unsigned char *buf, int len, | 96 | static int extra_decode_ctrl14(struct snd_midi_event *dev, unsigned char *buf, int len, |
@@ -256,25 +256,27 @@ int snd_midi_event_encode_byte(struct snd_midi_event *dev, int c, | |||
256 | } | 256 | } |
257 | 257 | ||
258 | spin_lock_irqsave(&dev->lock, flags); | 258 | spin_lock_irqsave(&dev->lock, flags); |
259 | if (dev->qlen > 0) { | 259 | if ((c & 0x80) && |
260 | /* rest of command */ | 260 | (c != MIDI_CMD_COMMON_SYSEX_END || dev->type != ST_SYSEX)) { |
261 | dev->buf[dev->read++] = c; | ||
262 | if (dev->type != ST_SYSEX) | ||
263 | dev->qlen--; | ||
264 | } else { | ||
265 | /* new command */ | 261 | /* new command */ |
262 | dev->buf[0] = c; | ||
263 | if ((c & 0xf0) == 0xf0) /* system messages */ | ||
264 | dev->type = (c & 0x0f) + ST_SPECIAL; | ||
265 | else | ||
266 | dev->type = (c >> 4) & 0x07; | ||
266 | dev->read = 1; | 267 | dev->read = 1; |
267 | if (c & 0x80) { | 268 | dev->qlen = status_event[dev->type].qlen; |
268 | dev->buf[0] = c; | 269 | } else { |
269 | if ((c & 0xf0) == 0xf0) /* special events */ | 270 | if (dev->qlen > 0) { |
270 | dev->type = (c & 0x0f) + ST_SPECIAL; | 271 | /* rest of command */ |
271 | else | ||
272 | dev->type = (c >> 4) & 0x07; | ||
273 | dev->qlen = status_event[dev->type].qlen; | ||
274 | } else { | ||
275 | /* process this byte as argument */ | ||
276 | dev->buf[dev->read++] = c; | 272 | dev->buf[dev->read++] = c; |
273 | if (dev->type != ST_SYSEX) | ||
274 | dev->qlen--; | ||
275 | } else { | ||
276 | /* running status */ | ||
277 | dev->buf[1] = c; | ||
277 | dev->qlen = status_event[dev->type].qlen - 1; | 278 | dev->qlen = status_event[dev->type].qlen - 1; |
279 | dev->read = 2; | ||
278 | } | 280 | } |
279 | } | 281 | } |
280 | if (dev->qlen == 0) { | 282 | if (dev->qlen == 0) { |