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 18 MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>, Jaroslav Kysela <perex@perex.cz>"); 19 MODULE_DESCRIPTION("MIDI byte <-> sequencer event coder"); 20 MODULE_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 */ 33 static void note_event(struct snd_midi_event *dev, struct snd_seq_event *ev); 34 static void one_param_ctrl_event(struct snd_midi_event *dev, struct snd_seq_event *ev); 35 static void pitchbend_ctrl_event(struct snd_midi_event *dev, struct snd_seq_event *ev); 36 static void two_param_ctrl_event(struct snd_midi_event *dev, struct snd_seq_event *ev); 37 static void one_param_event(struct snd_midi_event *dev, struct snd_seq_event *ev); 38 static void songpos_event(struct snd_midi_event *dev, struct snd_seq_event *ev); 39 static void note_decode(struct snd_seq_event *ev, unsigned char *buf); 40 static void one_param_decode(struct snd_seq_event *ev, unsigned char *buf); 41 static void pitchbend_decode(struct snd_seq_event *ev, unsigned char *buf); 42 static void two_param_decode(struct snd_seq_event *ev, unsigned char *buf); 43 static void songpos_decode(struct snd_seq_event *ev, unsigned char *buf); 44 45 /* 46 * event list 47 */ 48 static 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 83 static int extra_decode_ctrl14(struct snd_midi_event *dev, unsigned char *buf, int len, 84 struct snd_seq_event *ev); 85 static int extra_decode_xrpn(struct snd_midi_event *dev, unsigned char *buf, int count, 86 struct snd_seq_event *ev); 87 88 static 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 102 int 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 } 124 EXPORT_SYMBOL(snd_midi_event_new); 125 126 void snd_midi_event_free(struct snd_midi_event *dev) 127 { 128 if (dev != NULL) { 129 kfree(dev->buf); 130 kfree(dev); 131 } 132 } 133 EXPORT_SYMBOL(snd_midi_event_free); 134 135 /* 136 * initialize record 137 */ 138 static 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 145 void snd_midi_event_reset_encode(struct snd_midi_event *dev) 146 { 147 guard(spinlock_irqsave)(&dev->lock); 148 reset_encode(dev); 149 } 150 EXPORT_SYMBOL(snd_midi_event_reset_encode); 151 152 void snd_midi_event_reset_decode(struct snd_midi_event *dev) 153 { 154 guard(spinlock_irqsave)(&dev->lock); 155 dev->lastcmd = 0xff; 156 } 157 EXPORT_SYMBOL(snd_midi_event_reset_decode); 158 159 void snd_midi_event_no_status(struct snd_midi_event *dev, int on) 160 { 161 dev->nostat = on ? 1 : 0; 162 } 163 EXPORT_SYMBOL(snd_midi_event_no_status); 164 165 /* 166 * read one byte and encode to sequencer event: 167 * return true if MIDI bytes are encoded to an event 168 * false data is not finished 169 */ 170 bool snd_midi_event_encode_byte(struct snd_midi_event *dev, unsigned char c, 171 struct snd_seq_event *ev) 172 { 173 bool rc = false; 174 175 if (c >= MIDI_CMD_COMMON_CLOCK) { 176 /* real-time event */ 177 ev->type = status_event[ST_SPECIAL + c - 0xf0].event; 178 ev->flags &= ~SNDRV_SEQ_EVENT_LENGTH_MASK; 179 ev->flags |= SNDRV_SEQ_EVENT_LENGTH_FIXED; 180 return ev->type != SNDRV_SEQ_EVENT_NONE; 181 } 182 183 guard(spinlock_irqsave)(&dev->lock); 184 if ((c & 0x80) && 185 (c != MIDI_CMD_COMMON_SYSEX_END || dev->type != ST_SYSEX)) { 186 /* new command */ 187 dev->buf[0] = c; 188 if ((c & 0xf0) == 0xf0) /* system messages */ 189 dev->type = (c & 0x0f) + ST_SPECIAL; 190 else 191 dev->type = (c >> 4) & 0x07; 192 dev->read = 1; 193 dev->qlen = status_event[dev->type].qlen; 194 } else { 195 if (dev->qlen > 0) { 196 /* rest of command */ 197 dev->buf[dev->read++] = c; 198 if (dev->type != ST_SYSEX) 199 dev->qlen--; 200 } else { 201 /* running status */ 202 dev->buf[1] = c; 203 dev->qlen = status_event[dev->type].qlen - 1; 204 dev->read = 2; 205 } 206 } 207 if (dev->qlen == 0) { 208 ev->type = status_event[dev->type].event; 209 ev->flags &= ~SNDRV_SEQ_EVENT_LENGTH_MASK; 210 ev->flags |= SNDRV_SEQ_EVENT_LENGTH_FIXED; 211 if (status_event[dev->type].encode) /* set data values */ 212 status_event[dev->type].encode(dev, ev); 213 if (dev->type >= ST_SPECIAL) 214 dev->type = ST_INVALID; 215 rc = true; 216 } else if (dev->type == ST_SYSEX) { 217 if (c == MIDI_CMD_COMMON_SYSEX_END || 218 dev->read >= dev->bufsize) { 219 ev->flags &= ~SNDRV_SEQ_EVENT_LENGTH_MASK; 220 ev->flags |= SNDRV_SEQ_EVENT_LENGTH_VARIABLE; 221 ev->type = SNDRV_SEQ_EVENT_SYSEX; 222 ev->data.ext.len = dev->read; 223 ev->data.ext.ptr = dev->buf; 224 if (c != MIDI_CMD_COMMON_SYSEX_END) 225 dev->read = 0; /* continue to parse */ 226 else 227 reset_encode(dev); /* all parsed */ 228 rc = true; 229 } 230 } 231 232 return rc; 233 } 234 EXPORT_SYMBOL(snd_midi_event_encode_byte); 235 236 /* encode note event */ 237 static void note_event(struct snd_midi_event *dev, struct snd_seq_event *ev) 238 { 239 ev->data.note.channel = dev->buf[0] & 0x0f; 240 ev->data.note.note = dev->buf[1]; 241 ev->data.note.velocity = dev->buf[2]; 242 } 243 244 /* encode one parameter controls */ 245 static void one_param_ctrl_event(struct snd_midi_event *dev, struct snd_seq_event *ev) 246 { 247 ev->data.control.channel = dev->buf[0] & 0x0f; 248 ev->data.control.value = dev->buf[1]; 249 } 250 251 /* encode pitch wheel change */ 252 static void pitchbend_ctrl_event(struct snd_midi_event *dev, struct snd_seq_event *ev) 253 { 254 ev->data.control.channel = dev->buf[0] & 0x0f; 255 ev->data.control.value = (int)dev->buf[2] * 128 + (int)dev->buf[1] - 8192; 256 } 257 258 /* encode midi control change */ 259 static void two_param_ctrl_event(struct snd_midi_event *dev, struct snd_seq_event *ev) 260 { 261 ev->data.control.channel = dev->buf[0] & 0x0f; 262 ev->data.control.param = dev->buf[1]; 263 ev->data.control.value = dev->buf[2]; 264 } 265 266 /* encode one parameter value*/ 267 static void one_param_event(struct snd_midi_event *dev, struct snd_seq_event *ev) 268 { 269 ev->data.control.value = dev->buf[1]; 270 } 271 272 /* encode song position */ 273 static void songpos_event(struct snd_midi_event *dev, struct snd_seq_event *ev) 274 { 275 ev->data.control.value = (int)dev->buf[2] * 128 + (int)dev->buf[1]; 276 } 277 278 /* 279 * decode from a sequencer event to midi bytes 280 * return the size of decoded midi events 281 */ 282 long snd_midi_event_decode(struct snd_midi_event *dev, unsigned char *buf, long count, 283 struct snd_seq_event *ev) 284 { 285 unsigned int cmd, type; 286 287 if (ev->type == SNDRV_SEQ_EVENT_NONE) 288 return -ENOENT; 289 290 for (type = 0; type < ARRAY_SIZE(status_event); type++) { 291 if (ev->type == status_event[type].event) 292 goto __found; 293 } 294 for (type = 0; type < ARRAY_SIZE(extra_event); type++) { 295 if (ev->type == extra_event[type].event) 296 return extra_event[type].decode(dev, buf, count, ev); 297 } 298 return -ENOENT; 299 300 __found: 301 if (type >= ST_SPECIAL) 302 cmd = 0xf0 + (type - ST_SPECIAL); 303 else 304 /* data.note.channel and data.control.channel is identical */ 305 cmd = 0x80 | (type << 4) | (ev->data.note.channel & 0x0f); 306 307 308 if (cmd == MIDI_CMD_COMMON_SYSEX) { 309 snd_midi_event_reset_decode(dev); 310 return snd_seq_expand_var_event(ev, count, buf, 1, 0); 311 } else { 312 int qlen; 313 unsigned char xbuf[4]; 314 unsigned long flags; 315 316 spin_lock_irqsave(&dev->lock, flags); 317 if ((cmd & 0xf0) == 0xf0 || dev->lastcmd != cmd || dev->nostat) { 318 dev->lastcmd = cmd; 319 spin_unlock_irqrestore(&dev->lock, flags); 320 xbuf[0] = cmd; 321 if (status_event[type].decode) 322 status_event[type].decode(ev, xbuf + 1); 323 qlen = status_event[type].qlen + 1; 324 } else { 325 spin_unlock_irqrestore(&dev->lock, flags); 326 if (status_event[type].decode) 327 status_event[type].decode(ev, xbuf + 0); 328 qlen = status_event[type].qlen; 329 } 330 if (count < qlen) 331 return -ENOMEM; 332 memcpy(buf, xbuf, qlen); 333 return qlen; 334 } 335 } 336 EXPORT_SYMBOL(snd_midi_event_decode); 337 338 339 /* decode note event */ 340 static void note_decode(struct snd_seq_event *ev, unsigned char *buf) 341 { 342 buf[0] = ev->data.note.note & 0x7f; 343 buf[1] = ev->data.note.velocity & 0x7f; 344 } 345 346 /* decode one parameter controls */ 347 static void one_param_decode(struct snd_seq_event *ev, unsigned char *buf) 348 { 349 buf[0] = ev->data.control.value & 0x7f; 350 } 351 352 /* decode pitch wheel change */ 353 static void pitchbend_decode(struct snd_seq_event *ev, unsigned char *buf) 354 { 355 int value = ev->data.control.value + 8192; 356 buf[0] = value & 0x7f; 357 buf[1] = (value >> 7) & 0x7f; 358 } 359 360 /* decode midi control change */ 361 static void two_param_decode(struct snd_seq_event *ev, unsigned char *buf) 362 { 363 buf[0] = ev->data.control.param & 0x7f; 364 buf[1] = ev->data.control.value & 0x7f; 365 } 366 367 /* decode song position */ 368 static void songpos_decode(struct snd_seq_event *ev, unsigned char *buf) 369 { 370 buf[0] = ev->data.control.value & 0x7f; 371 buf[1] = (ev->data.control.value >> 7) & 0x7f; 372 } 373 374 /* decode 14bit control */ 375 static int extra_decode_ctrl14(struct snd_midi_event *dev, unsigned char *buf, 376 int count, struct snd_seq_event *ev) 377 { 378 unsigned char cmd; 379 int idx = 0; 380 381 cmd = MIDI_CMD_CONTROL|(ev->data.control.channel & 0x0f); 382 if (ev->data.control.param < 0x20) { 383 if (count < 4) 384 return -ENOMEM; 385 if (dev->nostat && count < 6) 386 return -ENOMEM; 387 if (cmd != dev->lastcmd || dev->nostat) { 388 if (count < 5) 389 return -ENOMEM; 390 buf[idx++] = dev->lastcmd = cmd; 391 } 392 buf[idx++] = ev->data.control.param; 393 buf[idx++] = (ev->data.control.value >> 7) & 0x7f; 394 if (dev->nostat) 395 buf[idx++] = cmd; 396 buf[idx++] = ev->data.control.param + 0x20; 397 buf[idx++] = ev->data.control.value & 0x7f; 398 } else { 399 if (count < 2) 400 return -ENOMEM; 401 if (cmd != dev->lastcmd || dev->nostat) { 402 if (count < 3) 403 return -ENOMEM; 404 buf[idx++] = dev->lastcmd = cmd; 405 } 406 buf[idx++] = ev->data.control.param & 0x7f; 407 buf[idx++] = ev->data.control.value & 0x7f; 408 } 409 return idx; 410 } 411 412 /* decode reg/nonreg param */ 413 static int extra_decode_xrpn(struct snd_midi_event *dev, unsigned char *buf, 414 int count, struct snd_seq_event *ev) 415 { 416 unsigned char cmd; 417 const char *cbytes; 418 static const char cbytes_nrpn[4] = { MIDI_CTL_NONREG_PARM_NUM_MSB, 419 MIDI_CTL_NONREG_PARM_NUM_LSB, 420 MIDI_CTL_MSB_DATA_ENTRY, 421 MIDI_CTL_LSB_DATA_ENTRY }; 422 static const char cbytes_rpn[4] = { MIDI_CTL_REGIST_PARM_NUM_MSB, 423 MIDI_CTL_REGIST_PARM_NUM_LSB, 424 MIDI_CTL_MSB_DATA_ENTRY, 425 MIDI_CTL_LSB_DATA_ENTRY }; 426 unsigned char bytes[4]; 427 int idx = 0, i; 428 429 if (count < 8) 430 return -ENOMEM; 431 if (dev->nostat && count < 12) 432 return -ENOMEM; 433 cmd = MIDI_CMD_CONTROL|(ev->data.control.channel & 0x0f); 434 bytes[0] = (ev->data.control.param & 0x3f80) >> 7; 435 bytes[1] = ev->data.control.param & 0x007f; 436 bytes[2] = (ev->data.control.value & 0x3f80) >> 7; 437 bytes[3] = ev->data.control.value & 0x007f; 438 if (cmd != dev->lastcmd && !dev->nostat) { 439 if (count < 9) 440 return -ENOMEM; 441 buf[idx++] = dev->lastcmd = cmd; 442 } 443 cbytes = ev->type == SNDRV_SEQ_EVENT_NONREGPARAM ? cbytes_nrpn : cbytes_rpn; 444 for (i = 0; i < 4; i++) { 445 if (dev->nostat) 446 buf[idx++] = dev->lastcmd = cmd; 447 buf[idx++] = cbytes[i]; 448 buf[idx++] = bytes[i]; 449 } 450 return idx; 451 } 452