0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/init.h>
0011 #include <linux/module.h>
0012 #include <linux/mutex.h>
0013 #include <linux/compat.h>
0014 #include <sound/core.h>
0015 #include <sound/minors.h>
0016 #include <sound/initval.h>
0017 #include "seq_oss_device.h"
0018 #include "seq_oss_synth.h"
0019
0020
0021
0022
0023 MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
0024 MODULE_DESCRIPTION("OSS-compatible sequencer module");
0025 MODULE_LICENSE("GPL");
0026
0027 MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_SEQUENCER);
0028 MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_MUSIC);
0029
0030
0031
0032
0033
0034 static int register_device(void);
0035 static void unregister_device(void);
0036 #ifdef CONFIG_SND_PROC_FS
0037 static int register_proc(void);
0038 static void unregister_proc(void);
0039 #else
0040 static inline int register_proc(void) { return 0; }
0041 static inline void unregister_proc(void) {}
0042 #endif
0043
0044 static int odev_open(struct inode *inode, struct file *file);
0045 static int odev_release(struct inode *inode, struct file *file);
0046 static ssize_t odev_read(struct file *file, char __user *buf, size_t count, loff_t *offset);
0047 static ssize_t odev_write(struct file *file, const char __user *buf, size_t count, loff_t *offset);
0048 static long odev_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
0049 static __poll_t odev_poll(struct file *file, poll_table * wait);
0050
0051
0052
0053
0054
0055
0056 static struct snd_seq_driver seq_oss_synth_driver = {
0057 .driver = {
0058 .name = KBUILD_MODNAME,
0059 .probe = snd_seq_oss_synth_probe,
0060 .remove = snd_seq_oss_synth_remove,
0061 },
0062 .id = SNDRV_SEQ_DEV_ID_OSS,
0063 .argsize = sizeof(struct snd_seq_oss_reg),
0064 };
0065
0066 static int __init alsa_seq_oss_init(void)
0067 {
0068 int rc;
0069
0070 rc = register_device();
0071 if (rc < 0)
0072 goto error;
0073 rc = register_proc();
0074 if (rc < 0) {
0075 unregister_device();
0076 goto error;
0077 }
0078 rc = snd_seq_oss_create_client();
0079 if (rc < 0) {
0080 unregister_proc();
0081 unregister_device();
0082 goto error;
0083 }
0084
0085 rc = snd_seq_driver_register(&seq_oss_synth_driver);
0086 if (rc < 0) {
0087 snd_seq_oss_delete_client();
0088 unregister_proc();
0089 unregister_device();
0090 goto error;
0091 }
0092
0093
0094 snd_seq_oss_synth_init();
0095
0096 error:
0097 return rc;
0098 }
0099
0100 static void __exit alsa_seq_oss_exit(void)
0101 {
0102 snd_seq_driver_unregister(&seq_oss_synth_driver);
0103 snd_seq_oss_delete_client();
0104 unregister_proc();
0105 unregister_device();
0106 }
0107
0108 module_init(alsa_seq_oss_init)
0109 module_exit(alsa_seq_oss_exit)
0110
0111
0112
0113
0114
0115 static DEFINE_MUTEX(register_mutex);
0116
0117 static int
0118 odev_open(struct inode *inode, struct file *file)
0119 {
0120 int level, rc;
0121
0122 if (iminor(inode) == SNDRV_MINOR_OSS_MUSIC)
0123 level = SNDRV_SEQ_OSS_MODE_MUSIC;
0124 else
0125 level = SNDRV_SEQ_OSS_MODE_SYNTH;
0126
0127 mutex_lock(®ister_mutex);
0128 rc = snd_seq_oss_open(file, level);
0129 mutex_unlock(®ister_mutex);
0130
0131 return rc;
0132 }
0133
0134 static int
0135 odev_release(struct inode *inode, struct file *file)
0136 {
0137 struct seq_oss_devinfo *dp;
0138
0139 dp = file->private_data;
0140 if (!dp)
0141 return 0;
0142
0143 mutex_lock(®ister_mutex);
0144 snd_seq_oss_release(dp);
0145 mutex_unlock(®ister_mutex);
0146
0147 return 0;
0148 }
0149
0150 static ssize_t
0151 odev_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
0152 {
0153 struct seq_oss_devinfo *dp;
0154 dp = file->private_data;
0155 if (snd_BUG_ON(!dp))
0156 return -ENXIO;
0157 return snd_seq_oss_read(dp, buf, count);
0158 }
0159
0160
0161 static ssize_t
0162 odev_write(struct file *file, const char __user *buf, size_t count, loff_t *offset)
0163 {
0164 struct seq_oss_devinfo *dp;
0165 dp = file->private_data;
0166 if (snd_BUG_ON(!dp))
0167 return -ENXIO;
0168 return snd_seq_oss_write(dp, buf, count, file);
0169 }
0170
0171 static long
0172 odev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
0173 {
0174 struct seq_oss_devinfo *dp;
0175 long rc;
0176
0177 dp = file->private_data;
0178 if (snd_BUG_ON(!dp))
0179 return -ENXIO;
0180
0181 if (cmd != SNDCTL_SEQ_SYNC &&
0182 mutex_lock_interruptible(®ister_mutex))
0183 return -ERESTARTSYS;
0184 rc = snd_seq_oss_ioctl(dp, cmd, arg);
0185 if (cmd != SNDCTL_SEQ_SYNC)
0186 mutex_unlock(®ister_mutex);
0187 return rc;
0188 }
0189
0190 #ifdef CONFIG_COMPAT
0191 static long odev_ioctl_compat(struct file *file, unsigned int cmd,
0192 unsigned long arg)
0193 {
0194 return odev_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
0195 }
0196 #else
0197 #define odev_ioctl_compat NULL
0198 #endif
0199
0200 static __poll_t
0201 odev_poll(struct file *file, poll_table * wait)
0202 {
0203 struct seq_oss_devinfo *dp;
0204 dp = file->private_data;
0205 if (snd_BUG_ON(!dp))
0206 return EPOLLERR;
0207 return snd_seq_oss_poll(dp, file, wait);
0208 }
0209
0210
0211
0212
0213
0214 static const struct file_operations seq_oss_f_ops =
0215 {
0216 .owner = THIS_MODULE,
0217 .read = odev_read,
0218 .write = odev_write,
0219 .open = odev_open,
0220 .release = odev_release,
0221 .poll = odev_poll,
0222 .unlocked_ioctl = odev_ioctl,
0223 .compat_ioctl = odev_ioctl_compat,
0224 .llseek = noop_llseek,
0225 };
0226
0227 static int __init
0228 register_device(void)
0229 {
0230 int rc;
0231
0232 mutex_lock(®ister_mutex);
0233 rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER,
0234 NULL, 0,
0235 &seq_oss_f_ops, NULL);
0236 if (rc < 0) {
0237 pr_err("ALSA: seq_oss: can't register device seq\n");
0238 mutex_unlock(®ister_mutex);
0239 return rc;
0240 }
0241 rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MUSIC,
0242 NULL, 0,
0243 &seq_oss_f_ops, NULL);
0244 if (rc < 0) {
0245 pr_err("ALSA: seq_oss: can't register device music\n");
0246 snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, NULL, 0);
0247 mutex_unlock(®ister_mutex);
0248 return rc;
0249 }
0250 mutex_unlock(®ister_mutex);
0251 return 0;
0252 }
0253
0254 static void
0255 unregister_device(void)
0256 {
0257 mutex_lock(®ister_mutex);
0258 if (snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_MUSIC, NULL, 0) < 0)
0259 pr_err("ALSA: seq_oss: error unregister device music\n");
0260 if (snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, NULL, 0) < 0)
0261 pr_err("ALSA: seq_oss: error unregister device seq\n");
0262 mutex_unlock(®ister_mutex);
0263 }
0264
0265
0266
0267
0268
0269 #ifdef CONFIG_SND_PROC_FS
0270
0271 static struct snd_info_entry *info_entry;
0272
0273 static void
0274 info_read(struct snd_info_entry *entry, struct snd_info_buffer *buf)
0275 {
0276 mutex_lock(®ister_mutex);
0277 snd_iprintf(buf, "OSS sequencer emulation version %s\n", SNDRV_SEQ_OSS_VERSION_STR);
0278 snd_seq_oss_system_info_read(buf);
0279 snd_seq_oss_synth_info_read(buf);
0280 snd_seq_oss_midi_info_read(buf);
0281 mutex_unlock(®ister_mutex);
0282 }
0283
0284
0285 static int __init
0286 register_proc(void)
0287 {
0288 struct snd_info_entry *entry;
0289
0290 entry = snd_info_create_module_entry(THIS_MODULE, SNDRV_SEQ_OSS_PROCNAME, snd_seq_root);
0291 if (entry == NULL)
0292 return -ENOMEM;
0293
0294 entry->content = SNDRV_INFO_CONTENT_TEXT;
0295 entry->private_data = NULL;
0296 entry->c.text.read = info_read;
0297 if (snd_info_register(entry) < 0) {
0298 snd_info_free_entry(entry);
0299 return -ENOMEM;
0300 }
0301 info_entry = entry;
0302 return 0;
0303 }
0304
0305 static void
0306 unregister_proc(void)
0307 {
0308 snd_info_free_entry(info_entry);
0309 info_entry = NULL;
0310 }
0311 #endif