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_oss_synth.c (14532B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * OSS compatible sequencer driver
      4 *
      5 * synth device handlers
      6 *
      7 * Copyright (C) 1998,99 Takashi Iwai <tiwai@suse.de>
      8 */
      9
     10#include "seq_oss_synth.h"
     11#include "seq_oss_midi.h"
     12#include "../seq_lock.h"
     13#include <linux/init.h>
     14#include <linux/module.h>
     15#include <linux/slab.h>
     16#include <linux/nospec.h>
     17
     18/*
     19 * constants
     20 */
     21#define SNDRV_SEQ_OSS_MAX_SYNTH_NAME	30
     22#define MAX_SYSEX_BUFLEN		128
     23
     24
     25/*
     26 * definition of synth info records
     27 */
     28
     29/* sysex buffer */
     30struct seq_oss_synth_sysex {
     31	int len;
     32	int skip;
     33	unsigned char buf[MAX_SYSEX_BUFLEN];
     34};
     35
     36/* synth info */
     37struct seq_oss_synth {
     38	int seq_device;
     39
     40	/* for synth_info */
     41	int synth_type;
     42	int synth_subtype;
     43	int nr_voices;
     44
     45	char name[SNDRV_SEQ_OSS_MAX_SYNTH_NAME];
     46	struct snd_seq_oss_callback oper;
     47
     48	int opened;
     49
     50	void *private_data;
     51	snd_use_lock_t use_lock;
     52};
     53
     54
     55/*
     56 * device table
     57 */
     58static int max_synth_devs;
     59static struct seq_oss_synth *synth_devs[SNDRV_SEQ_OSS_MAX_SYNTH_DEVS];
     60static struct seq_oss_synth midi_synth_dev = {
     61	.seq_device = -1,
     62	.synth_type = SYNTH_TYPE_MIDI,
     63	.synth_subtype = 0,
     64	.nr_voices = 16,
     65	.name = "MIDI",
     66};
     67
     68static DEFINE_SPINLOCK(register_lock);
     69
     70/*
     71 * prototypes
     72 */
     73static struct seq_oss_synth *get_synthdev(struct seq_oss_devinfo *dp, int dev);
     74static void reset_channels(struct seq_oss_synthinfo *info);
     75
     76/*
     77 * global initialization
     78 */
     79void __init
     80snd_seq_oss_synth_init(void)
     81{
     82	snd_use_lock_init(&midi_synth_dev.use_lock);
     83}
     84
     85/*
     86 * registration of the synth device
     87 */
     88int
     89snd_seq_oss_synth_probe(struct device *_dev)
     90{
     91	struct snd_seq_device *dev = to_seq_dev(_dev);
     92	int i;
     93	struct seq_oss_synth *rec;
     94	struct snd_seq_oss_reg *reg = SNDRV_SEQ_DEVICE_ARGPTR(dev);
     95	unsigned long flags;
     96
     97	rec = kzalloc(sizeof(*rec), GFP_KERNEL);
     98	if (!rec)
     99		return -ENOMEM;
    100	rec->seq_device = -1;
    101	rec->synth_type = reg->type;
    102	rec->synth_subtype = reg->subtype;
    103	rec->nr_voices = reg->nvoices;
    104	rec->oper = reg->oper;
    105	rec->private_data = reg->private_data;
    106	rec->opened = 0;
    107	snd_use_lock_init(&rec->use_lock);
    108
    109	/* copy and truncate the name of synth device */
    110	strscpy(rec->name, dev->name, sizeof(rec->name));
    111
    112	/* registration */
    113	spin_lock_irqsave(&register_lock, flags);
    114	for (i = 0; i < max_synth_devs; i++) {
    115		if (synth_devs[i] == NULL)
    116			break;
    117	}
    118	if (i >= max_synth_devs) {
    119		if (max_synth_devs >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS) {
    120			spin_unlock_irqrestore(&register_lock, flags);
    121			pr_err("ALSA: seq_oss: no more synth slot\n");
    122			kfree(rec);
    123			return -ENOMEM;
    124		}
    125		max_synth_devs++;
    126	}
    127	rec->seq_device = i;
    128	synth_devs[i] = rec;
    129	spin_unlock_irqrestore(&register_lock, flags);
    130	dev->driver_data = rec;
    131#ifdef SNDRV_OSS_INFO_DEV_SYNTH
    132	if (i < SNDRV_CARDS)
    133		snd_oss_info_register(SNDRV_OSS_INFO_DEV_SYNTH, i, rec->name);
    134#endif
    135	return 0;
    136}
    137
    138
    139int
    140snd_seq_oss_synth_remove(struct device *_dev)
    141{
    142	struct snd_seq_device *dev = to_seq_dev(_dev);
    143	int index;
    144	struct seq_oss_synth *rec = dev->driver_data;
    145	unsigned long flags;
    146
    147	spin_lock_irqsave(&register_lock, flags);
    148	for (index = 0; index < max_synth_devs; index++) {
    149		if (synth_devs[index] == rec)
    150			break;
    151	}
    152	if (index >= max_synth_devs) {
    153		spin_unlock_irqrestore(&register_lock, flags);
    154		pr_err("ALSA: seq_oss: can't unregister synth\n");
    155		return -EINVAL;
    156	}
    157	synth_devs[index] = NULL;
    158	if (index == max_synth_devs - 1) {
    159		for (index--; index >= 0; index--) {
    160			if (synth_devs[index])
    161				break;
    162		}
    163		max_synth_devs = index + 1;
    164	}
    165	spin_unlock_irqrestore(&register_lock, flags);
    166#ifdef SNDRV_OSS_INFO_DEV_SYNTH
    167	if (rec->seq_device < SNDRV_CARDS)
    168		snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_SYNTH, rec->seq_device);
    169#endif
    170
    171	snd_use_lock_sync(&rec->use_lock);
    172	kfree(rec);
    173
    174	return 0;
    175}
    176
    177
    178/*
    179 */
    180static struct seq_oss_synth *
    181get_sdev(int dev)
    182{
    183	struct seq_oss_synth *rec;
    184	unsigned long flags;
    185
    186	spin_lock_irqsave(&register_lock, flags);
    187	rec = synth_devs[dev];
    188	if (rec)
    189		snd_use_lock_use(&rec->use_lock);
    190	spin_unlock_irqrestore(&register_lock, flags);
    191	return rec;
    192}
    193
    194
    195/*
    196 * set up synth tables
    197 */
    198
    199void
    200snd_seq_oss_synth_setup(struct seq_oss_devinfo *dp)
    201{
    202	int i;
    203	struct seq_oss_synth *rec;
    204	struct seq_oss_synthinfo *info;
    205
    206	dp->max_synthdev = max_synth_devs;
    207	dp->synth_opened = 0;
    208	memset(dp->synths, 0, sizeof(dp->synths));
    209	for (i = 0; i < dp->max_synthdev; i++) {
    210		rec = get_sdev(i);
    211		if (rec == NULL)
    212			continue;
    213		if (rec->oper.open == NULL || rec->oper.close == NULL) {
    214			snd_use_lock_free(&rec->use_lock);
    215			continue;
    216		}
    217		info = &dp->synths[i];
    218		info->arg.app_index = dp->port;
    219		info->arg.file_mode = dp->file_mode;
    220		info->arg.seq_mode = dp->seq_mode;
    221		if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_SYNTH)
    222			info->arg.event_passing = SNDRV_SEQ_OSS_PROCESS_EVENTS;
    223		else
    224			info->arg.event_passing = SNDRV_SEQ_OSS_PASS_EVENTS;
    225		info->opened = 0;
    226		if (!try_module_get(rec->oper.owner)) {
    227			snd_use_lock_free(&rec->use_lock);
    228			continue;
    229		}
    230		if (rec->oper.open(&info->arg, rec->private_data) < 0) {
    231			module_put(rec->oper.owner);
    232			snd_use_lock_free(&rec->use_lock);
    233			continue;
    234		}
    235		info->nr_voices = rec->nr_voices;
    236		if (info->nr_voices > 0) {
    237			info->ch = kcalloc(info->nr_voices, sizeof(struct seq_oss_chinfo), GFP_KERNEL);
    238			if (!info->ch) {
    239				rec->oper.close(&info->arg);
    240				module_put(rec->oper.owner);
    241				snd_use_lock_free(&rec->use_lock);
    242				continue;
    243			}
    244			reset_channels(info);
    245		}
    246		info->opened++;
    247		rec->opened++;
    248		dp->synth_opened++;
    249		snd_use_lock_free(&rec->use_lock);
    250	}
    251}
    252
    253
    254/*
    255 * set up synth tables for MIDI emulation - /dev/music mode only
    256 */
    257
    258void
    259snd_seq_oss_synth_setup_midi(struct seq_oss_devinfo *dp)
    260{
    261	int i;
    262
    263	if (dp->max_synthdev >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS)
    264		return;
    265
    266	for (i = 0; i < dp->max_mididev; i++) {
    267		struct seq_oss_synthinfo *info;
    268		info = &dp->synths[dp->max_synthdev];
    269		if (snd_seq_oss_midi_open(dp, i, dp->file_mode) < 0)
    270			continue;
    271		info->arg.app_index = dp->port;
    272		info->arg.file_mode = dp->file_mode;
    273		info->arg.seq_mode = dp->seq_mode;
    274		info->arg.private_data = info;
    275		info->is_midi = 1;
    276		info->midi_mapped = i;
    277		info->arg.event_passing = SNDRV_SEQ_OSS_PASS_EVENTS;
    278		snd_seq_oss_midi_get_addr(dp, i, &info->arg.addr);
    279		info->opened = 1;
    280		midi_synth_dev.opened++;
    281		dp->max_synthdev++;
    282		if (dp->max_synthdev >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS)
    283			break;
    284	}
    285}
    286
    287
    288/*
    289 * clean up synth tables
    290 */
    291
    292void
    293snd_seq_oss_synth_cleanup(struct seq_oss_devinfo *dp)
    294{
    295	int i;
    296	struct seq_oss_synth *rec;
    297	struct seq_oss_synthinfo *info;
    298
    299	if (snd_BUG_ON(dp->max_synthdev > SNDRV_SEQ_OSS_MAX_SYNTH_DEVS))
    300		return;
    301	for (i = 0; i < dp->max_synthdev; i++) {
    302		info = &dp->synths[i];
    303		if (! info->opened)
    304			continue;
    305		if (info->is_midi) {
    306			if (midi_synth_dev.opened > 0) {
    307				snd_seq_oss_midi_close(dp, info->midi_mapped);
    308				midi_synth_dev.opened--;
    309			}
    310		} else {
    311			rec = get_sdev(i);
    312			if (rec == NULL)
    313				continue;
    314			if (rec->opened > 0) {
    315				rec->oper.close(&info->arg);
    316				module_put(rec->oper.owner);
    317				rec->opened = 0;
    318			}
    319			snd_use_lock_free(&rec->use_lock);
    320		}
    321		kfree(info->sysex);
    322		info->sysex = NULL;
    323		kfree(info->ch);
    324		info->ch = NULL;
    325	}
    326	dp->synth_opened = 0;
    327	dp->max_synthdev = 0;
    328}
    329
    330static struct seq_oss_synthinfo *
    331get_synthinfo_nospec(struct seq_oss_devinfo *dp, int dev)
    332{
    333	if (dev < 0 || dev >= dp->max_synthdev)
    334		return NULL;
    335	dev = array_index_nospec(dev, SNDRV_SEQ_OSS_MAX_SYNTH_DEVS);
    336	return &dp->synths[dev];
    337}
    338
    339/*
    340 * return synth device information pointer
    341 */
    342static struct seq_oss_synth *
    343get_synthdev(struct seq_oss_devinfo *dp, int dev)
    344{
    345	struct seq_oss_synth *rec;
    346	struct seq_oss_synthinfo *info = get_synthinfo_nospec(dp, dev);
    347
    348	if (!info)
    349		return NULL;
    350	if (!info->opened)
    351		return NULL;
    352	if (info->is_midi) {
    353		rec = &midi_synth_dev;
    354		snd_use_lock_use(&rec->use_lock);
    355	} else {
    356		rec = get_sdev(dev);
    357		if (!rec)
    358			return NULL;
    359	}
    360	if (! rec->opened) {
    361		snd_use_lock_free(&rec->use_lock);
    362		return NULL;
    363	}
    364	return rec;
    365}
    366
    367
    368/*
    369 * reset note and velocity on each channel.
    370 */
    371static void
    372reset_channels(struct seq_oss_synthinfo *info)
    373{
    374	int i;
    375	if (info->ch == NULL || ! info->nr_voices)
    376		return;
    377	for (i = 0; i < info->nr_voices; i++) {
    378		info->ch[i].note = -1;
    379		info->ch[i].vel = 0;
    380	}
    381}
    382
    383
    384/*
    385 * reset synth device:
    386 * call reset callback.  if no callback is defined, send a heartbeat
    387 * event to the corresponding port.
    388 */
    389void
    390snd_seq_oss_synth_reset(struct seq_oss_devinfo *dp, int dev)
    391{
    392	struct seq_oss_synth *rec;
    393	struct seq_oss_synthinfo *info;
    394
    395	info = get_synthinfo_nospec(dp, dev);
    396	if (!info || !info->opened)
    397		return;
    398	if (info->sysex)
    399		info->sysex->len = 0; /* reset sysex */
    400	reset_channels(info);
    401	if (info->is_midi) {
    402		if (midi_synth_dev.opened <= 0)
    403			return;
    404		snd_seq_oss_midi_reset(dp, info->midi_mapped);
    405		/* reopen the device */
    406		snd_seq_oss_midi_close(dp, dev);
    407		if (snd_seq_oss_midi_open(dp, info->midi_mapped,
    408					  dp->file_mode) < 0) {
    409			midi_synth_dev.opened--;
    410			info->opened = 0;
    411			kfree(info->sysex);
    412			info->sysex = NULL;
    413			kfree(info->ch);
    414			info->ch = NULL;
    415		}
    416		return;
    417	}
    418
    419	rec = get_sdev(dev);
    420	if (rec == NULL)
    421		return;
    422	if (rec->oper.reset) {
    423		rec->oper.reset(&info->arg);
    424	} else {
    425		struct snd_seq_event ev;
    426		memset(&ev, 0, sizeof(ev));
    427		snd_seq_oss_fill_addr(dp, &ev, info->arg.addr.client,
    428				      info->arg.addr.port);
    429		ev.type = SNDRV_SEQ_EVENT_RESET;
    430		snd_seq_oss_dispatch(dp, &ev, 0, 0);
    431	}
    432	snd_use_lock_free(&rec->use_lock);
    433}
    434
    435
    436/*
    437 * load a patch record:
    438 * call load_patch callback function
    439 */
    440int
    441snd_seq_oss_synth_load_patch(struct seq_oss_devinfo *dp, int dev, int fmt,
    442			    const char __user *buf, int p, int c)
    443{
    444	struct seq_oss_synth *rec;
    445	struct seq_oss_synthinfo *info;
    446	int rc;
    447
    448	info = get_synthinfo_nospec(dp, dev);
    449	if (!info)
    450		return -ENXIO;
    451
    452	if (info->is_midi)
    453		return 0;
    454	rec = get_synthdev(dp, dev);
    455	if (!rec)
    456		return -ENXIO;
    457
    458	if (rec->oper.load_patch == NULL)
    459		rc = -ENXIO;
    460	else
    461		rc = rec->oper.load_patch(&info->arg, fmt, buf, p, c);
    462	snd_use_lock_free(&rec->use_lock);
    463	return rc;
    464}
    465
    466/*
    467 * check if the device is valid synth device and return the synth info
    468 */
    469struct seq_oss_synthinfo *
    470snd_seq_oss_synth_info(struct seq_oss_devinfo *dp, int dev)
    471{
    472	struct seq_oss_synth *rec;
    473
    474	rec = get_synthdev(dp, dev);
    475	if (rec) {
    476		snd_use_lock_free(&rec->use_lock);
    477		return get_synthinfo_nospec(dp, dev);
    478	}
    479	return NULL;
    480}
    481
    482
    483/*
    484 * receive OSS 6 byte sysex packet:
    485 * the full sysex message will be sent if it reaches to the end of data
    486 * (0xff).
    487 */
    488int
    489snd_seq_oss_synth_sysex(struct seq_oss_devinfo *dp, int dev, unsigned char *buf, struct snd_seq_event *ev)
    490{
    491	int i, send;
    492	unsigned char *dest;
    493	struct seq_oss_synth_sysex *sysex;
    494	struct seq_oss_synthinfo *info;
    495
    496	info = snd_seq_oss_synth_info(dp, dev);
    497	if (!info)
    498		return -ENXIO;
    499
    500	sysex = info->sysex;
    501	if (sysex == NULL) {
    502		sysex = kzalloc(sizeof(*sysex), GFP_KERNEL);
    503		if (sysex == NULL)
    504			return -ENOMEM;
    505		info->sysex = sysex;
    506	}
    507
    508	send = 0;
    509	dest = sysex->buf + sysex->len;
    510	/* copy 6 byte packet to the buffer */
    511	for (i = 0; i < 6; i++) {
    512		if (buf[i] == 0xff) {
    513			send = 1;
    514			break;
    515		}
    516		dest[i] = buf[i];
    517		sysex->len++;
    518		if (sysex->len >= MAX_SYSEX_BUFLEN) {
    519			sysex->len = 0;
    520			sysex->skip = 1;
    521			break;
    522		}
    523	}
    524
    525	if (sysex->len && send) {
    526		if (sysex->skip) {
    527			sysex->skip = 0;
    528			sysex->len = 0;
    529			return -EINVAL; /* skip */
    530		}
    531		/* copy the data to event record and send it */
    532		ev->flags = SNDRV_SEQ_EVENT_LENGTH_VARIABLE;
    533		if (snd_seq_oss_synth_addr(dp, dev, ev))
    534			return -EINVAL;
    535		ev->data.ext.len = sysex->len;
    536		ev->data.ext.ptr = sysex->buf;
    537		sysex->len = 0;
    538		return 0;
    539	}
    540
    541	return -EINVAL; /* skip */
    542}
    543
    544/*
    545 * fill the event source/destination addresses
    546 */
    547int
    548snd_seq_oss_synth_addr(struct seq_oss_devinfo *dp, int dev, struct snd_seq_event *ev)
    549{
    550	struct seq_oss_synthinfo *info = snd_seq_oss_synth_info(dp, dev);
    551
    552	if (!info)
    553		return -EINVAL;
    554	snd_seq_oss_fill_addr(dp, ev, info->arg.addr.client,
    555			      info->arg.addr.port);
    556	return 0;
    557}
    558
    559
    560/*
    561 * OSS compatible ioctl
    562 */
    563int
    564snd_seq_oss_synth_ioctl(struct seq_oss_devinfo *dp, int dev, unsigned int cmd, unsigned long addr)
    565{
    566	struct seq_oss_synth *rec;
    567	struct seq_oss_synthinfo *info;
    568	int rc;
    569
    570	info = get_synthinfo_nospec(dp, dev);
    571	if (!info || info->is_midi)
    572		return -ENXIO;
    573	rec = get_synthdev(dp, dev);
    574	if (!rec)
    575		return -ENXIO;
    576	if (rec->oper.ioctl == NULL)
    577		rc = -ENXIO;
    578	else
    579		rc = rec->oper.ioctl(&info->arg, cmd, addr);
    580	snd_use_lock_free(&rec->use_lock);
    581	return rc;
    582}
    583
    584
    585/*
    586 * send OSS raw events - SEQ_PRIVATE and SEQ_VOLUME
    587 */
    588int
    589snd_seq_oss_synth_raw_event(struct seq_oss_devinfo *dp, int dev, unsigned char *data, struct snd_seq_event *ev)
    590{
    591	struct seq_oss_synthinfo *info;
    592
    593	info = snd_seq_oss_synth_info(dp, dev);
    594	if (!info || info->is_midi)
    595		return -ENXIO;
    596	ev->type = SNDRV_SEQ_EVENT_OSS;
    597	memcpy(ev->data.raw8.d, data, 8);
    598	return snd_seq_oss_synth_addr(dp, dev, ev);
    599}
    600
    601
    602/*
    603 * create OSS compatible synth_info record
    604 */
    605int
    606snd_seq_oss_synth_make_info(struct seq_oss_devinfo *dp, int dev, struct synth_info *inf)
    607{
    608	struct seq_oss_synth *rec;
    609	struct seq_oss_synthinfo *info = get_synthinfo_nospec(dp, dev);
    610
    611	if (!info)
    612		return -ENXIO;
    613
    614	if (info->is_midi) {
    615		struct midi_info minf;
    616		if (snd_seq_oss_midi_make_info(dp, info->midi_mapped, &minf))
    617			return -ENXIO;
    618		inf->synth_type = SYNTH_TYPE_MIDI;
    619		inf->synth_subtype = 0;
    620		inf->nr_voices = 16;
    621		inf->device = dev;
    622		strscpy(inf->name, minf.name, sizeof(inf->name));
    623	} else {
    624		rec = get_synthdev(dp, dev);
    625		if (!rec)
    626			return -ENXIO;
    627		inf->synth_type = rec->synth_type;
    628		inf->synth_subtype = rec->synth_subtype;
    629		inf->nr_voices = rec->nr_voices;
    630		inf->device = dev;
    631		strscpy(inf->name, rec->name, sizeof(inf->name));
    632		snd_use_lock_free(&rec->use_lock);
    633	}
    634	return 0;
    635}
    636
    637
    638#ifdef CONFIG_SND_PROC_FS
    639/*
    640 * proc interface
    641 */
    642void
    643snd_seq_oss_synth_info_read(struct snd_info_buffer *buf)
    644{
    645	int i;
    646	struct seq_oss_synth *rec;
    647
    648	snd_iprintf(buf, "\nNumber of synth devices: %d\n", max_synth_devs);
    649	for (i = 0; i < max_synth_devs; i++) {
    650		snd_iprintf(buf, "\nsynth %d: ", i);
    651		rec = get_sdev(i);
    652		if (rec == NULL) {
    653			snd_iprintf(buf, "*empty*\n");
    654			continue;
    655		}
    656		snd_iprintf(buf, "[%s]\n", rec->name);
    657		snd_iprintf(buf, "  type 0x%x : subtype 0x%x : voices %d\n",
    658			    rec->synth_type, rec->synth_subtype,
    659			    rec->nr_voices);
    660		snd_iprintf(buf, "  capabilities : ioctl %s / load_patch %s\n",
    661			    enabled_str((long)rec->oper.ioctl),
    662			    enabled_str((long)rec->oper.load_patch));
    663		snd_use_lock_free(&rec->use_lock);
    664	}
    665}
    666#endif /* CONFIG_SND_PROC_FS */