seq_midi_event.c (13661B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * MIDI byte <-> sequencer event coder 4 * 5 * Copyright (C) 1998,99 Takashi Iwai <tiwai@suse.de>, 6 * Jaroslav Kysela <perex@perex.cz> 7 */ 8 9#include <linux/slab.h> 10#include <linux/errno.h> 11#include <linux/string.h> 12#include <linux/module.h> 13#include <sound/core.h> 14#include <sound/seq_kernel.h> 15#include <sound/seq_midi_event.h> 16#include <sound/asoundef.h> 17 18MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>, Jaroslav Kysela <perex@perex.cz>"); 19MODULE_DESCRIPTION("MIDI byte <-> sequencer event coder"); 20MODULE_LICENSE("GPL"); 21 22/* event type, index into status_event[] */ 23/* from 0 to 6 are normal commands (note off, on, etc.) for 0x9?-0xe? */ 24#define ST_INVALID 7 25#define ST_SPECIAL 8 26#define ST_SYSEX ST_SPECIAL 27/* from 8 to 15 are events for 0xf0-0xf7 */ 28 29 30/* 31 * prototypes 32 */ 33static void note_event(struct snd_midi_event *dev, struct snd_seq_event *ev); 34static void one_param_ctrl_event(struct snd_midi_event *dev, struct snd_seq_event *ev); 35static void pitchbend_ctrl_event(struct snd_midi_event *dev, struct snd_seq_event *ev); 36static void two_param_ctrl_event(struct snd_midi_event *dev, struct snd_seq_event *ev); 37static void one_param_event(struct snd_midi_event *dev, struct snd_seq_event *ev); 38static void songpos_event(struct snd_midi_event *dev, struct snd_seq_event *ev); 39static void note_decode(struct snd_seq_event *ev, unsigned char *buf); 40static void one_param_decode(struct snd_seq_event *ev, unsigned char *buf); 41static void pitchbend_decode(struct snd_seq_event *ev, unsigned char *buf); 42static void two_param_decode(struct snd_seq_event *ev, unsigned char *buf); 43static void songpos_decode(struct snd_seq_event *ev, unsigned char *buf); 44 45/* 46 * event list 47 */ 48static struct status_event_list { 49 int event; 50 int qlen; 51 void (*encode)(struct snd_midi_event *dev, struct snd_seq_event *ev); 52 void (*decode)(struct snd_seq_event *ev, unsigned char *buf); 53} status_event[] = { 54 /* 0x80 - 0xef */ 55 {SNDRV_SEQ_EVENT_NOTEOFF, 2, note_event, note_decode}, 56 {SNDRV_SEQ_EVENT_NOTEON, 2, note_event, note_decode}, 57 {SNDRV_SEQ_EVENT_KEYPRESS, 2, note_event, note_decode}, 58 {SNDRV_SEQ_EVENT_CONTROLLER, 2, two_param_ctrl_event, two_param_decode}, 59 {SNDRV_SEQ_EVENT_PGMCHANGE, 1, one_param_ctrl_event, one_param_decode}, 60 {SNDRV_SEQ_EVENT_CHANPRESS, 1, one_param_ctrl_event, one_param_decode}, 61 {SNDRV_SEQ_EVENT_PITCHBEND, 2, pitchbend_ctrl_event, pitchbend_decode}, 62 /* invalid */ 63 {SNDRV_SEQ_EVENT_NONE, -1, NULL, NULL}, 64 /* 0xf0 - 0xff */ 65 {SNDRV_SEQ_EVENT_SYSEX, 1, NULL, NULL}, /* sysex: 0xf0 */ 66 {SNDRV_SEQ_EVENT_QFRAME, 1, one_param_event, one_param_decode}, /* 0xf1 */ 67 {SNDRV_SEQ_EVENT_SONGPOS, 2, songpos_event, songpos_decode}, /* 0xf2 */ 68 {SNDRV_SEQ_EVENT_SONGSEL, 1, one_param_event, one_param_decode}, /* 0xf3 */ 69 {SNDRV_SEQ_EVENT_NONE, -1, NULL, NULL}, /* 0xf4 */ 70 {SNDRV_SEQ_EVENT_NONE, -1, NULL, NULL}, /* 0xf5 */ 71 {SNDRV_SEQ_EVENT_TUNE_REQUEST, 0, NULL, NULL}, /* 0xf6 */ 72 {SNDRV_SEQ_EVENT_NONE, -1, NULL, NULL}, /* 0xf7 */ 73 {SNDRV_SEQ_EVENT_CLOCK, 0, NULL, NULL}, /* 0xf8 */ 74 {SNDRV_SEQ_EVENT_NONE, -1, NULL, NULL}, /* 0xf9 */ 75 {SNDRV_SEQ_EVENT_START, 0, NULL, NULL}, /* 0xfa */ 76 {SNDRV_SEQ_EVENT_CONTINUE, 0, NULL, NULL}, /* 0xfb */ 77 {SNDRV_SEQ_EVENT_STOP, 0, NULL, NULL}, /* 0xfc */ 78 {SNDRV_SEQ_EVENT_NONE, -1, NULL, NULL}, /* 0xfd */ 79 {SNDRV_SEQ_EVENT_SENSING, 0, NULL, NULL}, /* 0xfe */ 80 {SNDRV_SEQ_EVENT_RESET, 0, NULL, NULL}, /* 0xff */ 81}; 82 83static int extra_decode_ctrl14(struct snd_midi_event *dev, unsigned char *buf, int len, 84 struct snd_seq_event *ev); 85static int extra_decode_xrpn(struct snd_midi_event *dev, unsigned char *buf, int count, 86 struct snd_seq_event *ev); 87 88static struct extra_event_list { 89 int event; 90 int (*decode)(struct snd_midi_event *dev, unsigned char *buf, int len, 91 struct snd_seq_event *ev); 92} extra_event[] = { 93 {SNDRV_SEQ_EVENT_CONTROL14, extra_decode_ctrl14}, 94 {SNDRV_SEQ_EVENT_NONREGPARAM, extra_decode_xrpn}, 95 {SNDRV_SEQ_EVENT_REGPARAM, extra_decode_xrpn}, 96}; 97 98/* 99 * new/delete record 100 */ 101 102int snd_midi_event_new(int bufsize, struct snd_midi_event **rdev) 103{ 104 struct snd_midi_event *dev; 105 106 *rdev = NULL; 107 dev = kzalloc(sizeof(*dev), GFP_KERNEL); 108 if (dev == NULL) 109 return -ENOMEM; 110 if (bufsize > 0) { 111 dev->buf = kmalloc(bufsize, GFP_KERNEL); 112 if (dev->buf == NULL) { 113 kfree(dev); 114 return -ENOMEM; 115 } 116 } 117 dev->bufsize = bufsize; 118 dev->lastcmd = 0xff; 119 dev->type = ST_INVALID; 120 spin_lock_init(&dev->lock); 121 *rdev = dev; 122 return 0; 123} 124EXPORT_SYMBOL(snd_midi_event_new); 125 126void snd_midi_event_free(struct snd_midi_event *dev) 127{ 128 if (dev != NULL) { 129 kfree(dev->buf); 130 kfree(dev); 131 } 132} 133EXPORT_SYMBOL(snd_midi_event_free); 134 135/* 136 * initialize record 137 */ 138static inline void reset_encode(struct snd_midi_event *dev) 139{ 140 dev->read = 0; 141 dev->qlen = 0; 142 dev->type = ST_INVALID; 143} 144 145void snd_midi_event_reset_encode(struct snd_midi_event *dev) 146{ 147 unsigned long flags; 148 149 spin_lock_irqsave(&dev->lock, flags); 150 reset_encode(dev); 151 spin_unlock_irqrestore(&dev->lock, flags); 152} 153EXPORT_SYMBOL(snd_midi_event_reset_encode); 154 155void snd_midi_event_reset_decode(struct snd_midi_event *dev) 156{ 157 unsigned long flags; 158 159 spin_lock_irqsave(&dev->lock, flags); 160 dev->lastcmd = 0xff; 161 spin_unlock_irqrestore(&dev->lock, flags); 162} 163EXPORT_SYMBOL(snd_midi_event_reset_decode); 164 165void snd_midi_event_no_status(struct snd_midi_event *dev, int on) 166{ 167 dev->nostat = on ? 1 : 0; 168} 169EXPORT_SYMBOL(snd_midi_event_no_status); 170 171/* 172 * read one byte and encode to sequencer event: 173 * return true if MIDI bytes are encoded to an event 174 * false data is not finished 175 */ 176bool snd_midi_event_encode_byte(struct snd_midi_event *dev, unsigned char c, 177 struct snd_seq_event *ev) 178{ 179 bool rc = false; 180 unsigned long flags; 181 182 if (c >= MIDI_CMD_COMMON_CLOCK) { 183 /* real-time event */ 184 ev->type = status_event[ST_SPECIAL + c - 0xf0].event; 185 ev->flags &= ~SNDRV_SEQ_EVENT_LENGTH_MASK; 186 ev->flags |= SNDRV_SEQ_EVENT_LENGTH_FIXED; 187 return ev->type != SNDRV_SEQ_EVENT_NONE; 188 } 189 190 spin_lock_irqsave(&dev->lock, flags); 191 if ((c & 0x80) && 192 (c != MIDI_CMD_COMMON_SYSEX_END || dev->type != ST_SYSEX)) { 193 /* new command */ 194 dev->buf[0] = c; 195 if ((c & 0xf0) == 0xf0) /* system messages */ 196 dev->type = (c & 0x0f) + ST_SPECIAL; 197 else 198 dev->type = (c >> 4) & 0x07; 199 dev->read = 1; 200 dev->qlen = status_event[dev->type].qlen; 201 } else { 202 if (dev->qlen > 0) { 203 /* rest of command */ 204 dev->buf[dev->read++] = c; 205 if (dev->type != ST_SYSEX) 206 dev->qlen--; 207 } else { 208 /* running status */ 209 dev->buf[1] = c; 210 dev->qlen = status_event[dev->type].qlen - 1; 211 dev->read = 2; 212 } 213 } 214 if (dev->qlen == 0) { 215 ev->type = status_event[dev->type].event; 216 ev->flags &= ~SNDRV_SEQ_EVENT_LENGTH_MASK; 217 ev->flags |= SNDRV_SEQ_EVENT_LENGTH_FIXED; 218 if (status_event[dev->type].encode) /* set data values */ 219 status_event[dev->type].encode(dev, ev); 220 if (dev->type >= ST_SPECIAL) 221 dev->type = ST_INVALID; 222 rc = true; 223 } else if (dev->type == ST_SYSEX) { 224 if (c == MIDI_CMD_COMMON_SYSEX_END || 225 dev->read >= dev->bufsize) { 226 ev->flags &= ~SNDRV_SEQ_EVENT_LENGTH_MASK; 227 ev->flags |= SNDRV_SEQ_EVENT_LENGTH_VARIABLE; 228 ev->type = SNDRV_SEQ_EVENT_SYSEX; 229 ev->data.ext.len = dev->read; 230 ev->data.ext.ptr = dev->buf; 231 if (c != MIDI_CMD_COMMON_SYSEX_END) 232 dev->read = 0; /* continue to parse */ 233 else 234 reset_encode(dev); /* all parsed */ 235 rc = true; 236 } 237 } 238 239 spin_unlock_irqrestore(&dev->lock, flags); 240 return rc; 241} 242EXPORT_SYMBOL(snd_midi_event_encode_byte); 243 244/* encode note event */ 245static void note_event(struct snd_midi_event *dev, struct snd_seq_event *ev) 246{ 247 ev->data.note.channel = dev->buf[0] & 0x0f; 248 ev->data.note.note = dev->buf[1]; 249 ev->data.note.velocity = dev->buf[2]; 250} 251 252/* encode one parameter controls */ 253static void one_param_ctrl_event(struct snd_midi_event *dev, struct snd_seq_event *ev) 254{ 255 ev->data.control.channel = dev->buf[0] & 0x0f; 256 ev->data.control.value = dev->buf[1]; 257} 258 259/* encode pitch wheel change */ 260static void pitchbend_ctrl_event(struct snd_midi_event *dev, struct snd_seq_event *ev) 261{ 262 ev->data.control.channel = dev->buf[0] & 0x0f; 263 ev->data.control.value = (int)dev->buf[2] * 128 + (int)dev->buf[1] - 8192; 264} 265 266/* encode midi control change */ 267static void two_param_ctrl_event(struct snd_midi_event *dev, struct snd_seq_event *ev) 268{ 269 ev->data.control.channel = dev->buf[0] & 0x0f; 270 ev->data.control.param = dev->buf[1]; 271 ev->data.control.value = dev->buf[2]; 272} 273 274/* encode one parameter value*/ 275static void one_param_event(struct snd_midi_event *dev, struct snd_seq_event *ev) 276{ 277 ev->data.control.value = dev->buf[1]; 278} 279 280/* encode song position */ 281static void songpos_event(struct snd_midi_event *dev, struct snd_seq_event *ev) 282{ 283 ev->data.control.value = (int)dev->buf[2] * 128 + (int)dev->buf[1]; 284} 285 286/* 287 * decode from a sequencer event to midi bytes 288 * return the size of decoded midi events 289 */ 290long snd_midi_event_decode(struct snd_midi_event *dev, unsigned char *buf, long count, 291 struct snd_seq_event *ev) 292{ 293 unsigned int cmd, type; 294 295 if (ev->type == SNDRV_SEQ_EVENT_NONE) 296 return -ENOENT; 297 298 for (type = 0; type < ARRAY_SIZE(status_event); type++) { 299 if (ev->type == status_event[type].event) 300 goto __found; 301 } 302 for (type = 0; type < ARRAY_SIZE(extra_event); type++) { 303 if (ev->type == extra_event[type].event) 304 return extra_event[type].decode(dev, buf, count, ev); 305 } 306 return -ENOENT; 307 308 __found: 309 if (type >= ST_SPECIAL) 310 cmd = 0xf0 + (type - ST_SPECIAL); 311 else 312 /* data.note.channel and data.control.channel is identical */ 313 cmd = 0x80 | (type << 4) | (ev->data.note.channel & 0x0f); 314 315 316 if (cmd == MIDI_CMD_COMMON_SYSEX) { 317 snd_midi_event_reset_decode(dev); 318 return snd_seq_expand_var_event(ev, count, buf, 1, 0); 319 } else { 320 int qlen; 321 unsigned char xbuf[4]; 322 unsigned long flags; 323 324 spin_lock_irqsave(&dev->lock, flags); 325 if ((cmd & 0xf0) == 0xf0 || dev->lastcmd != cmd || dev->nostat) { 326 dev->lastcmd = cmd; 327 spin_unlock_irqrestore(&dev->lock, flags); 328 xbuf[0] = cmd; 329 if (status_event[type].decode) 330 status_event[type].decode(ev, xbuf + 1); 331 qlen = status_event[type].qlen + 1; 332 } else { 333 spin_unlock_irqrestore(&dev->lock, flags); 334 if (status_event[type].decode) 335 status_event[type].decode(ev, xbuf + 0); 336 qlen = status_event[type].qlen; 337 } 338 if (count < qlen) 339 return -ENOMEM; 340 memcpy(buf, xbuf, qlen); 341 return qlen; 342 } 343} 344EXPORT_SYMBOL(snd_midi_event_decode); 345 346 347/* decode note event */ 348static void note_decode(struct snd_seq_event *ev, unsigned char *buf) 349{ 350 buf[0] = ev->data.note.note & 0x7f; 351 buf[1] = ev->data.note.velocity & 0x7f; 352} 353 354/* decode one parameter controls */ 355static void one_param_decode(struct snd_seq_event *ev, unsigned char *buf) 356{ 357 buf[0] = ev->data.control.value & 0x7f; 358} 359 360/* decode pitch wheel change */ 361static void pitchbend_decode(struct snd_seq_event *ev, unsigned char *buf) 362{ 363 int value = ev->data.control.value + 8192; 364 buf[0] = value & 0x7f; 365 buf[1] = (value >> 7) & 0x7f; 366} 367 368/* decode midi control change */ 369static void two_param_decode(struct snd_seq_event *ev, unsigned char *buf) 370{ 371 buf[0] = ev->data.control.param & 0x7f; 372 buf[1] = ev->data.control.value & 0x7f; 373} 374 375/* decode song position */ 376static void songpos_decode(struct snd_seq_event *ev, unsigned char *buf) 377{ 378 buf[0] = ev->data.control.value & 0x7f; 379 buf[1] = (ev->data.control.value >> 7) & 0x7f; 380} 381 382/* decode 14bit control */ 383static int extra_decode_ctrl14(struct snd_midi_event *dev, unsigned char *buf, 384 int count, struct snd_seq_event *ev) 385{ 386 unsigned char cmd; 387 int idx = 0; 388 389 cmd = MIDI_CMD_CONTROL|(ev->data.control.channel & 0x0f); 390 if (ev->data.control.param < 0x20) { 391 if (count < 4) 392 return -ENOMEM; 393 if (dev->nostat && count < 6) 394 return -ENOMEM; 395 if (cmd != dev->lastcmd || dev->nostat) { 396 if (count < 5) 397 return -ENOMEM; 398 buf[idx++] = dev->lastcmd = cmd; 399 } 400 buf[idx++] = ev->data.control.param; 401 buf[idx++] = (ev->data.control.value >> 7) & 0x7f; 402 if (dev->nostat) 403 buf[idx++] = cmd; 404 buf[idx++] = ev->data.control.param + 0x20; 405 buf[idx++] = ev->data.control.value & 0x7f; 406 } else { 407 if (count < 2) 408 return -ENOMEM; 409 if (cmd != dev->lastcmd || dev->nostat) { 410 if (count < 3) 411 return -ENOMEM; 412 buf[idx++] = dev->lastcmd = cmd; 413 } 414 buf[idx++] = ev->data.control.param & 0x7f; 415 buf[idx++] = ev->data.control.value & 0x7f; 416 } 417 return idx; 418} 419 420/* decode reg/nonreg param */ 421static int extra_decode_xrpn(struct snd_midi_event *dev, unsigned char *buf, 422 int count, struct snd_seq_event *ev) 423{ 424 unsigned char cmd; 425 const char *cbytes; 426 static const char cbytes_nrpn[4] = { MIDI_CTL_NONREG_PARM_NUM_MSB, 427 MIDI_CTL_NONREG_PARM_NUM_LSB, 428 MIDI_CTL_MSB_DATA_ENTRY, 429 MIDI_CTL_LSB_DATA_ENTRY }; 430 static const char cbytes_rpn[4] = { MIDI_CTL_REGIST_PARM_NUM_MSB, 431 MIDI_CTL_REGIST_PARM_NUM_LSB, 432 MIDI_CTL_MSB_DATA_ENTRY, 433 MIDI_CTL_LSB_DATA_ENTRY }; 434 unsigned char bytes[4]; 435 int idx = 0, i; 436 437 if (count < 8) 438 return -ENOMEM; 439 if (dev->nostat && count < 12) 440 return -ENOMEM; 441 cmd = MIDI_CMD_CONTROL|(ev->data.control.channel & 0x0f); 442 bytes[0] = (ev->data.control.param & 0x3f80) >> 7; 443 bytes[1] = ev->data.control.param & 0x007f; 444 bytes[2] = (ev->data.control.value & 0x3f80) >> 7; 445 bytes[3] = ev->data.control.value & 0x007f; 446 if (cmd != dev->lastcmd && !dev->nostat) { 447 if (count < 9) 448 return -ENOMEM; 449 buf[idx++] = dev->lastcmd = cmd; 450 } 451 cbytes = ev->type == SNDRV_SEQ_EVENT_NONREGPARAM ? cbytes_nrpn : cbytes_rpn; 452 for (i = 0; i < 4; i++) { 453 if (dev->nostat) 454 buf[idx++] = dev->lastcmd = cmd; 455 buf[idx++] = cbytes[i]; 456 buf[idx++] = bytes[i]; 457 } 458 return idx; 459}