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

sound_oss.c (6583B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *  Advanced Linux Sound Architecture
      4 *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
      5 */
      6
      7#include <linux/init.h>
      8#include <linux/export.h>
      9#include <linux/slab.h>
     10#include <linux/time.h>
     11#include <sound/core.h>
     12#include <sound/minors.h>
     13#include <sound/info.h>
     14#include <linux/sound.h>
     15#include <linux/mutex.h>
     16
     17#define SNDRV_OSS_MINORS 256
     18
     19static struct snd_minor *snd_oss_minors[SNDRV_OSS_MINORS];
     20static DEFINE_MUTEX(sound_oss_mutex);
     21
     22/* NOTE: This function increments the refcount of the associated card like
     23 * snd_lookup_minor_data(); the caller must call snd_card_unref() appropriately
     24 */
     25void *snd_lookup_oss_minor_data(unsigned int minor, int type)
     26{
     27	struct snd_minor *mreg;
     28	void *private_data;
     29
     30	if (minor >= ARRAY_SIZE(snd_oss_minors))
     31		return NULL;
     32	mutex_lock(&sound_oss_mutex);
     33	mreg = snd_oss_minors[minor];
     34	if (mreg && mreg->type == type) {
     35		private_data = mreg->private_data;
     36		if (private_data && mreg->card_ptr)
     37			get_device(&mreg->card_ptr->card_dev);
     38	} else
     39		private_data = NULL;
     40	mutex_unlock(&sound_oss_mutex);
     41	return private_data;
     42}
     43EXPORT_SYMBOL(snd_lookup_oss_minor_data);
     44
     45static int snd_oss_kernel_minor(int type, struct snd_card *card, int dev)
     46{
     47	int minor;
     48
     49	switch (type) {
     50	case SNDRV_OSS_DEVICE_TYPE_MIXER:
     51		if (snd_BUG_ON(!card || dev < 0 || dev > 1))
     52			return -EINVAL;
     53		minor = SNDRV_MINOR_OSS(card->number, (dev ? SNDRV_MINOR_OSS_MIXER1 : SNDRV_MINOR_OSS_MIXER));
     54		break;
     55	case SNDRV_OSS_DEVICE_TYPE_SEQUENCER:
     56		minor = SNDRV_MINOR_OSS_SEQUENCER;
     57		break;
     58	case SNDRV_OSS_DEVICE_TYPE_MUSIC:
     59		minor = SNDRV_MINOR_OSS_MUSIC;
     60		break;
     61	case SNDRV_OSS_DEVICE_TYPE_PCM:
     62		if (snd_BUG_ON(!card || dev < 0 || dev > 1))
     63			return -EINVAL;
     64		minor = SNDRV_MINOR_OSS(card->number, (dev ? SNDRV_MINOR_OSS_PCM1 : SNDRV_MINOR_OSS_PCM));
     65		break;
     66	case SNDRV_OSS_DEVICE_TYPE_MIDI:
     67		if (snd_BUG_ON(!card || dev < 0 || dev > 1))
     68			return -EINVAL;
     69		minor = SNDRV_MINOR_OSS(card->number, (dev ? SNDRV_MINOR_OSS_MIDI1 : SNDRV_MINOR_OSS_MIDI));
     70		break;
     71	case SNDRV_OSS_DEVICE_TYPE_DMFM:
     72		minor = SNDRV_MINOR_OSS(card->number, SNDRV_MINOR_OSS_DMFM);
     73		break;
     74	case SNDRV_OSS_DEVICE_TYPE_SNDSTAT:
     75		minor = SNDRV_MINOR_OSS_SNDSTAT;
     76		break;
     77	default:
     78		return -EINVAL;
     79	}
     80	if (minor < 0 || minor >= SNDRV_OSS_MINORS)
     81		return -EINVAL;
     82	return minor;
     83}
     84
     85int snd_register_oss_device(int type, struct snd_card *card, int dev,
     86			    const struct file_operations *f_ops, void *private_data)
     87{
     88	int minor = snd_oss_kernel_minor(type, card, dev);
     89	int minor_unit;
     90	struct snd_minor *preg;
     91	int cidx = SNDRV_MINOR_OSS_CARD(minor);
     92	int track2 = -1;
     93	int register1 = -1, register2 = -1;
     94	struct device *carddev = snd_card_get_device_link(card);
     95
     96	if (card && card->number >= SNDRV_MINOR_OSS_DEVICES)
     97		return 0; /* ignore silently */
     98	if (minor < 0)
     99		return minor;
    100	preg = kmalloc(sizeof(struct snd_minor), GFP_KERNEL);
    101	if (preg == NULL)
    102		return -ENOMEM;
    103	preg->type = type;
    104	preg->card = card ? card->number : -1;
    105	preg->device = dev;
    106	preg->f_ops = f_ops;
    107	preg->private_data = private_data;
    108	preg->card_ptr = card;
    109	mutex_lock(&sound_oss_mutex);
    110	snd_oss_minors[minor] = preg;
    111	minor_unit = SNDRV_MINOR_OSS_DEVICE(minor);
    112	switch (minor_unit) {
    113	case SNDRV_MINOR_OSS_PCM:
    114		track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_AUDIO);
    115		break;
    116	case SNDRV_MINOR_OSS_MIDI:
    117		track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_DMMIDI);
    118		break;
    119	case SNDRV_MINOR_OSS_MIDI1:
    120		track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_DMMIDI1);
    121		break;
    122	}
    123	register1 = register_sound_special_device(f_ops, minor, carddev);
    124	if (register1 != minor)
    125		goto __end;
    126	if (track2 >= 0) {
    127		register2 = register_sound_special_device(f_ops, track2,
    128							  carddev);
    129		if (register2 != track2)
    130			goto __end;
    131		snd_oss_minors[track2] = preg;
    132	}
    133	mutex_unlock(&sound_oss_mutex);
    134	return 0;
    135
    136      __end:
    137      	if (register2 >= 0)
    138      		unregister_sound_special(register2);
    139      	if (register1 >= 0)
    140      		unregister_sound_special(register1);
    141	snd_oss_minors[minor] = NULL;
    142	mutex_unlock(&sound_oss_mutex);
    143	kfree(preg);
    144      	return -EBUSY;
    145}
    146EXPORT_SYMBOL(snd_register_oss_device);
    147
    148int snd_unregister_oss_device(int type, struct snd_card *card, int dev)
    149{
    150	int minor = snd_oss_kernel_minor(type, card, dev);
    151	int cidx = SNDRV_MINOR_OSS_CARD(minor);
    152	int track2 = -1;
    153	struct snd_minor *mptr;
    154
    155	if (card && card->number >= SNDRV_MINOR_OSS_DEVICES)
    156		return 0;
    157	if (minor < 0)
    158		return minor;
    159	mutex_lock(&sound_oss_mutex);
    160	mptr = snd_oss_minors[minor];
    161	if (mptr == NULL) {
    162		mutex_unlock(&sound_oss_mutex);
    163		return -ENOENT;
    164	}
    165	unregister_sound_special(minor);
    166	switch (SNDRV_MINOR_OSS_DEVICE(minor)) {
    167	case SNDRV_MINOR_OSS_PCM:
    168		track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_AUDIO);
    169		break;
    170	case SNDRV_MINOR_OSS_MIDI:
    171		track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_DMMIDI);
    172		break;
    173	case SNDRV_MINOR_OSS_MIDI1:
    174		track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_DMMIDI1);
    175		break;
    176	}
    177	if (track2 >= 0) {
    178		unregister_sound_special(track2);
    179		snd_oss_minors[track2] = NULL;
    180	}
    181	snd_oss_minors[minor] = NULL;
    182	mutex_unlock(&sound_oss_mutex);
    183	kfree(mptr);
    184	return 0;
    185}
    186EXPORT_SYMBOL(snd_unregister_oss_device);
    187
    188/*
    189 *  INFO PART
    190 */
    191
    192#ifdef CONFIG_SND_PROC_FS
    193static const char *snd_oss_device_type_name(int type)
    194{
    195	switch (type) {
    196	case SNDRV_OSS_DEVICE_TYPE_MIXER:
    197		return "mixer";
    198	case SNDRV_OSS_DEVICE_TYPE_SEQUENCER:
    199	case SNDRV_OSS_DEVICE_TYPE_MUSIC:
    200		return "sequencer";
    201	case SNDRV_OSS_DEVICE_TYPE_PCM:
    202		return "digital audio";
    203	case SNDRV_OSS_DEVICE_TYPE_MIDI:
    204		return "raw midi";
    205	case SNDRV_OSS_DEVICE_TYPE_DMFM:
    206		return "hardware dependent";
    207	default:
    208		return "?";
    209	}
    210}
    211
    212static void snd_minor_info_oss_read(struct snd_info_entry *entry,
    213				    struct snd_info_buffer *buffer)
    214{
    215	int minor;
    216	struct snd_minor *mptr;
    217
    218	mutex_lock(&sound_oss_mutex);
    219	for (minor = 0; minor < SNDRV_OSS_MINORS; ++minor) {
    220		mptr = snd_oss_minors[minor];
    221		if (!mptr)
    222			continue;
    223		if (mptr->card >= 0)
    224			snd_iprintf(buffer, "%3i: [%i-%2i]: %s\n", minor,
    225				    mptr->card, mptr->device,
    226				    snd_oss_device_type_name(mptr->type));
    227		else
    228			snd_iprintf(buffer, "%3i:       : %s\n", minor,
    229				    snd_oss_device_type_name(mptr->type));
    230	}
    231	mutex_unlock(&sound_oss_mutex);
    232}
    233
    234
    235int __init snd_minor_info_oss_init(void)
    236{
    237	struct snd_info_entry *entry;
    238
    239	entry = snd_info_create_module_entry(THIS_MODULE, "devices", snd_oss_root);
    240	if (!entry)
    241		return -ENOMEM;
    242	entry->c.text.read = snd_minor_info_oss_read;
    243	return snd_info_register(entry); /* freed in error path */
    244}
    245#endif /* CONFIG_SND_PROC_FS */