2 * Copyright (C) 2002 Steve Schmidtke
3 * Licensed under the GPL
7 #include "linux/module.h"
8 #include "linux/slab.h"
9 #include "linux/sound.h"
10 #include "linux/soundcard.h"
11 #include "asm/uaccess.h"
15 struct hostaudio_state {
19 struct hostmixer_state {
23 #define HOSTAUDIO_DEV_DSP "/dev/sound/dsp"
24 #define HOSTAUDIO_DEV_MIXER "/dev/sound/mixer"
27 * Changed either at boot time or module load time. At boot, this is
28 * single-threaded; at module load, multiple modules would each have
29 * their own copy of these variables.
31 static char *dsp = HOSTAUDIO_DEV_DSP;
32 static char *mixer = HOSTAUDIO_DEV_MIXER;
35 " This is used to specify the host dsp device to the hostaudio driver.\n" \
36 " The default is \"" HOSTAUDIO_DEV_DSP "\".\n\n"
39 " This is used to specify the host mixer device to the hostaudio driver.\n"\
40 " The default is \"" HOSTAUDIO_DEV_MIXER "\".\n\n"
43 static int set_dsp(char *name, int *add)
49 __uml_setup("dsp=", set_dsp, "dsp=<dsp device>\n" DSP_HELP);
51 static int set_mixer(char *name, int *add)
57 __uml_setup("mixer=", set_mixer, "mixer=<mixer device>\n" MIXER_HELP);
61 module_param(dsp, charp, 0644);
62 MODULE_PARM_DESC(dsp, DSP_HELP);
64 module_param(mixer, charp, 0644);
65 MODULE_PARM_DESC(mixer, MIXER_HELP);
69 /* /dev/dsp file operations */
71 static ssize_t hostaudio_read(struct file *file, char __user *buffer,
72 size_t count, loff_t *ppos)
74 struct hostaudio_state *state = file->private_data;
79 printk(KERN_DEBUG "hostaudio: read called, count = %d\n", count);
82 kbuf = kmalloc(count, GFP_KERNEL);
86 err = os_read_file(state->fd, kbuf, count);
90 if (copy_to_user(buffer, kbuf, err))
98 static ssize_t hostaudio_write(struct file *file, const char __user *buffer,
99 size_t count, loff_t *ppos)
101 struct hostaudio_state *state = file->private_data;
106 printk(KERN_DEBUG "hostaudio: write called, count = %d\n", count);
109 kbuf = kmalloc(count, GFP_KERNEL);
114 if (copy_from_user(kbuf, buffer, count))
117 err = os_write_file(state->fd, kbuf, count);
127 static unsigned int hostaudio_poll(struct file *file,
128 struct poll_table_struct *wait)
130 unsigned int mask = 0;
133 printk(KERN_DEBUG "hostaudio: poll called (unimplemented)\n");
139 static int hostaudio_ioctl(struct inode *inode, struct file *file,
140 unsigned int cmd, unsigned long arg)
142 struct hostaudio_state *state = file->private_data;
143 unsigned long data = 0;
147 printk(KERN_DEBUG "hostaudio: ioctl called, cmd = %u\n", cmd);
150 case SNDCTL_DSP_SPEED:
151 case SNDCTL_DSP_STEREO:
152 case SNDCTL_DSP_GETBLKSIZE:
153 case SNDCTL_DSP_CHANNELS:
154 case SNDCTL_DSP_SUBDIVIDE:
155 case SNDCTL_DSP_SETFRAGMENT:
156 if (get_user(data, (int __user *) arg))
163 err = os_ioctl_generic(state->fd, cmd, (unsigned long) &data);
166 case SNDCTL_DSP_SPEED:
167 case SNDCTL_DSP_STEREO:
168 case SNDCTL_DSP_GETBLKSIZE:
169 case SNDCTL_DSP_CHANNELS:
170 case SNDCTL_DSP_SUBDIVIDE:
171 case SNDCTL_DSP_SETFRAGMENT:
172 if (put_user(data, (int __user *) arg))
182 static int hostaudio_open(struct inode *inode, struct file *file)
184 struct hostaudio_state *state;
189 printk(KERN_DEBUG "hostaudio: open called (host: %s)\n", dsp);
192 state = kmalloc(sizeof(struct hostaudio_state), GFP_KERNEL);
196 if (file->f_mode & FMODE_READ)
198 if (file->f_mode & FMODE_WRITE)
201 ret = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0);
207 file->private_data = state;
211 static int hostaudio_release(struct inode *inode, struct file *file)
213 struct hostaudio_state *state = file->private_data;
216 printk(KERN_DEBUG "hostaudio: release called\n");
218 os_close_file(state->fd);
224 /* /dev/mixer file operations */
226 static int hostmixer_ioctl_mixdev(struct inode *inode, struct file *file,
227 unsigned int cmd, unsigned long arg)
229 struct hostmixer_state *state = file->private_data;
232 printk(KERN_DEBUG "hostmixer: ioctl called\n");
235 return os_ioctl_generic(state->fd, cmd, arg);
238 static int hostmixer_open_mixdev(struct inode *inode, struct file *file)
240 struct hostmixer_state *state;
245 printk(KERN_DEBUG "hostmixer: open called (host: %s)\n", mixer);
248 state = kmalloc(sizeof(struct hostmixer_state), GFP_KERNEL);
252 if (file->f_mode & FMODE_READ)
254 if (file->f_mode & FMODE_WRITE)
257 ret = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0);
260 printk(KERN_ERR "hostaudio_open_mixdev failed to open '%s', "
261 "err = %d\n", dsp, -ret);
266 file->private_data = state;
270 static int hostmixer_release(struct inode *inode, struct file *file)
272 struct hostmixer_state *state = file->private_data;
275 printk(KERN_DEBUG "hostmixer: release called\n");
278 os_close_file(state->fd);
284 /* kernel module operations */
286 static const struct file_operations hostaudio_fops = {
287 .owner = THIS_MODULE,
289 .read = hostaudio_read,
290 .write = hostaudio_write,
291 .poll = hostaudio_poll,
292 .ioctl = hostaudio_ioctl,
294 .open = hostaudio_open,
295 .release = hostaudio_release,
298 static const struct file_operations hostmixer_fops = {
299 .owner = THIS_MODULE,
301 .ioctl = hostmixer_ioctl_mixdev,
302 .open = hostmixer_open_mixdev,
303 .release = hostmixer_release,
311 MODULE_AUTHOR("Steve Schmidtke");
312 MODULE_DESCRIPTION("UML Audio Relay");
313 MODULE_LICENSE("GPL");
315 static int __init hostaudio_init_module(void)
317 printk(KERN_INFO "UML Audio Relay (host dsp = %s, host mixer = %s)\n",
320 module_data.dev_audio = register_sound_dsp(&hostaudio_fops, -1);
321 if (module_data.dev_audio < 0) {
322 printk(KERN_ERR "hostaudio: couldn't register DSP device!\n");
326 module_data.dev_mixer = register_sound_mixer(&hostmixer_fops, -1);
327 if (module_data.dev_mixer < 0) {
328 printk(KERN_ERR "hostmixer: couldn't register mixer "
330 unregister_sound_dsp(module_data.dev_audio);
337 static void __exit hostaudio_cleanup_module (void)
339 unregister_sound_mixer(module_data.dev_mixer);
340 unregister_sound_dsp(module_data.dev_audio);
343 module_init(hostaudio_init_module);
344 module_exit(hostaudio_cleanup_module);