aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2007-08-10 03:40:09 -0400
committerJaroslav Kysela <perex@perex.cz>2007-10-16 09:58:37 -0400
commitbf8c1382c0339e95e89394f59a149610dd2d828f (patch)
tree09b0f3a7284335981465e7ebd9a495bcb11a4c45 /sound/core
parent0b664f7206fac9676559e0012d8accc2dc0fc9fd (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')
-rw-r--r--sound/core/seq/seq_midi_event.c80
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
96static int extra_decode_ctrl14(struct snd_midi_event *dev, unsigned char *buf, int len, 96static 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) {