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


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * OSS compatible sequencer driver
      4 *
      5 * registration of device and proc
      6 *
      7 * Copyright (C) 1998,99 Takashi Iwai <tiwai@suse.de>
      8 */
      9
     10#include <linux/init.h>
     11#include <linux/module.h>
     12#include <linux/mutex.h>
     13#include <linux/compat.h>
     14#include <sound/core.h>
     15#include <sound/minors.h>
     16#include <sound/initval.h>
     17#include "seq_oss_device.h"
     18#include "seq_oss_synth.h"
     19
     20/*
     21 * module option
     22 */
     23MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
     24MODULE_DESCRIPTION("OSS-compatible sequencer module");
     25MODULE_LICENSE("GPL");
     26/* Takashi says this is really only for sound-service-0-, but this is OK. */
     27MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_SEQUENCER);
     28MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_MUSIC);
     29
     30
     31/*
     32 * prototypes
     33 */
     34static int register_device(void);
     35static void unregister_device(void);
     36#ifdef CONFIG_SND_PROC_FS
     37static int register_proc(void);
     38static void unregister_proc(void);
     39#else
     40static inline int register_proc(void) { return 0; }
     41static inline void unregister_proc(void) {}
     42#endif
     43
     44static int odev_open(struct inode *inode, struct file *file);
     45static int odev_release(struct inode *inode, struct file *file);
     46static ssize_t odev_read(struct file *file, char __user *buf, size_t count, loff_t *offset);
     47static ssize_t odev_write(struct file *file, const char __user *buf, size_t count, loff_t *offset);
     48static long odev_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
     49static __poll_t odev_poll(struct file *file, poll_table * wait);
     50
     51
     52/*
     53 * module interface
     54 */
     55
     56static struct snd_seq_driver seq_oss_synth_driver = {
     57	.driver = {
     58		.name = KBUILD_MODNAME,
     59		.probe = snd_seq_oss_synth_probe,
     60		.remove = snd_seq_oss_synth_remove,
     61	},
     62	.id = SNDRV_SEQ_DEV_ID_OSS,
     63	.argsize = sizeof(struct snd_seq_oss_reg),
     64};
     65
     66static int __init alsa_seq_oss_init(void)
     67{
     68	int rc;
     69
     70	rc = register_device();
     71	if (rc < 0)
     72		goto error;
     73	rc = register_proc();
     74	if (rc < 0) {
     75		unregister_device();
     76		goto error;
     77	}
     78	rc = snd_seq_oss_create_client();
     79	if (rc < 0) {
     80		unregister_proc();
     81		unregister_device();
     82		goto error;
     83	}
     84
     85	rc = snd_seq_driver_register(&seq_oss_synth_driver);
     86	if (rc < 0) {
     87		snd_seq_oss_delete_client();
     88		unregister_proc();
     89		unregister_device();
     90		goto error;
     91	}
     92
     93	/* success */
     94	snd_seq_oss_synth_init();
     95
     96 error:
     97	return rc;
     98}
     99
    100static void __exit alsa_seq_oss_exit(void)
    101{
    102	snd_seq_driver_unregister(&seq_oss_synth_driver);
    103	snd_seq_oss_delete_client();
    104	unregister_proc();
    105	unregister_device();
    106}
    107
    108module_init(alsa_seq_oss_init)
    109module_exit(alsa_seq_oss_exit)
    110
    111/*
    112 * ALSA minor device interface
    113 */
    114
    115static DEFINE_MUTEX(register_mutex);
    116
    117static int
    118odev_open(struct inode *inode, struct file *file)
    119{
    120	int level, rc;
    121
    122	if (iminor(inode) == SNDRV_MINOR_OSS_MUSIC)
    123		level = SNDRV_SEQ_OSS_MODE_MUSIC;
    124	else
    125		level = SNDRV_SEQ_OSS_MODE_SYNTH;
    126
    127	mutex_lock(&register_mutex);
    128	rc = snd_seq_oss_open(file, level);
    129	mutex_unlock(&register_mutex);
    130
    131	return rc;
    132}
    133
    134static int
    135odev_release(struct inode *inode, struct file *file)
    136{
    137	struct seq_oss_devinfo *dp;
    138
    139	dp = file->private_data;
    140	if (!dp)
    141		return 0;
    142
    143	mutex_lock(&register_mutex);
    144	snd_seq_oss_release(dp);
    145	mutex_unlock(&register_mutex);
    146
    147	return 0;
    148}
    149
    150static ssize_t
    151odev_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
    152{
    153	struct seq_oss_devinfo *dp;
    154	dp = file->private_data;
    155	if (snd_BUG_ON(!dp))
    156		return -ENXIO;
    157	return snd_seq_oss_read(dp, buf, count);
    158}
    159
    160
    161static ssize_t
    162odev_write(struct file *file, const char __user *buf, size_t count, loff_t *offset)
    163{
    164	struct seq_oss_devinfo *dp;
    165	dp = file->private_data;
    166	if (snd_BUG_ON(!dp))
    167		return -ENXIO;
    168	return snd_seq_oss_write(dp, buf, count, file);
    169}
    170
    171static long
    172odev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
    173{
    174	struct seq_oss_devinfo *dp;
    175	long rc;
    176
    177	dp = file->private_data;
    178	if (snd_BUG_ON(!dp))
    179		return -ENXIO;
    180
    181	if (cmd != SNDCTL_SEQ_SYNC &&
    182	    mutex_lock_interruptible(&register_mutex))
    183		return -ERESTARTSYS;
    184	rc = snd_seq_oss_ioctl(dp, cmd, arg);
    185	if (cmd != SNDCTL_SEQ_SYNC)
    186		mutex_unlock(&register_mutex);
    187	return rc;
    188}
    189
    190#ifdef CONFIG_COMPAT
    191static long odev_ioctl_compat(struct file *file, unsigned int cmd,
    192			      unsigned long arg)
    193{
    194	return odev_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
    195}
    196#else
    197#define odev_ioctl_compat	NULL
    198#endif
    199
    200static __poll_t
    201odev_poll(struct file *file, poll_table * wait)
    202{
    203	struct seq_oss_devinfo *dp;
    204	dp = file->private_data;
    205	if (snd_BUG_ON(!dp))
    206		return EPOLLERR;
    207	return snd_seq_oss_poll(dp, file, wait);
    208}
    209
    210/*
    211 * registration of sequencer minor device
    212 */
    213
    214static const struct file_operations seq_oss_f_ops =
    215{
    216	.owner =	THIS_MODULE,
    217	.read =		odev_read,
    218	.write =	odev_write,
    219	.open =		odev_open,
    220	.release =	odev_release,
    221	.poll =		odev_poll,
    222	.unlocked_ioctl =	odev_ioctl,
    223	.compat_ioctl =	odev_ioctl_compat,
    224	.llseek =	noop_llseek,
    225};
    226
    227static int __init
    228register_device(void)
    229{
    230	int rc;
    231
    232	mutex_lock(&register_mutex);
    233	rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER,
    234				     NULL, 0,
    235				     &seq_oss_f_ops, NULL);
    236	if (rc < 0) {
    237		pr_err("ALSA: seq_oss: can't register device seq\n");
    238		mutex_unlock(&register_mutex);
    239		return rc;
    240	}
    241	rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MUSIC,
    242				     NULL, 0,
    243				     &seq_oss_f_ops, NULL);
    244	if (rc < 0) {
    245		pr_err("ALSA: seq_oss: can't register device music\n");
    246		snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, NULL, 0);
    247		mutex_unlock(&register_mutex);
    248		return rc;
    249	}
    250	mutex_unlock(&register_mutex);
    251	return 0;
    252}
    253
    254static void
    255unregister_device(void)
    256{
    257	mutex_lock(&register_mutex);
    258	if (snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_MUSIC, NULL, 0) < 0)		
    259		pr_err("ALSA: seq_oss: error unregister device music\n");
    260	if (snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, NULL, 0) < 0)
    261		pr_err("ALSA: seq_oss: error unregister device seq\n");
    262	mutex_unlock(&register_mutex);
    263}
    264
    265/*
    266 * /proc interface
    267 */
    268
    269#ifdef CONFIG_SND_PROC_FS
    270
    271static struct snd_info_entry *info_entry;
    272
    273static void
    274info_read(struct snd_info_entry *entry, struct snd_info_buffer *buf)
    275{
    276	mutex_lock(&register_mutex);
    277	snd_iprintf(buf, "OSS sequencer emulation version %s\n", SNDRV_SEQ_OSS_VERSION_STR);
    278	snd_seq_oss_system_info_read(buf);
    279	snd_seq_oss_synth_info_read(buf);
    280	snd_seq_oss_midi_info_read(buf);
    281	mutex_unlock(&register_mutex);
    282}
    283
    284
    285static int __init
    286register_proc(void)
    287{
    288	struct snd_info_entry *entry;
    289
    290	entry = snd_info_create_module_entry(THIS_MODULE, SNDRV_SEQ_OSS_PROCNAME, snd_seq_root);
    291	if (entry == NULL)
    292		return -ENOMEM;
    293
    294	entry->content = SNDRV_INFO_CONTENT_TEXT;
    295	entry->private_data = NULL;
    296	entry->c.text.read = info_read;
    297	if (snd_info_register(entry) < 0) {
    298		snd_info_free_entry(entry);
    299		return -ENOMEM;
    300	}
    301	info_entry = entry;
    302	return 0;
    303}
    304
    305static void
    306unregister_proc(void)
    307{
    308	snd_info_free_entry(info_entry);
    309	info_entry = NULL;
    310}
    311#endif /* CONFIG_SND_PROC_FS */