cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

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}