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 <linux/mutex.h>
12 #include <linux/uaccess.h>
16 struct hostaudio_state
{
20 struct hostmixer_state
{
24 #define HOSTAUDIO_DEV_DSP "/dev/sound/dsp"
25 #define HOSTAUDIO_DEV_MIXER "/dev/sound/mixer"
28 * Changed either at boot time or module load time. At boot, this is
29 * single-threaded; at module load, multiple modules would each have
30 * their own copy of these variables.
32 static char *dsp
= HOSTAUDIO_DEV_DSP
;
33 static char *mixer
= HOSTAUDIO_DEV_MIXER
;
36 " This is used to specify the host dsp device to the hostaudio driver.\n" \
37 " The default is \"" HOSTAUDIO_DEV_DSP "\".\n\n"
40 " This is used to specify the host mixer device to the hostaudio driver.\n"\
41 " The default is \"" HOSTAUDIO_DEV_MIXER "\".\n\n"
43 module_param(dsp
, charp
, 0644);
44 MODULE_PARM_DESC(dsp
, DSP_HELP
);
45 module_param(mixer
, charp
, 0644);
46 MODULE_PARM_DESC(mixer
, MIXER_HELP
);
49 static int set_dsp(char *name
, int *add
)
55 __uml_setup("dsp=", set_dsp
, "dsp=<dsp device>\n" DSP_HELP
);
57 static int set_mixer(char *name
, int *add
)
63 __uml_setup("mixer=", set_mixer
, "mixer=<mixer device>\n" MIXER_HELP
);
66 static DEFINE_MUTEX(hostaudio_mutex
);
68 /* /dev/dsp file operations */
70 static ssize_t
hostaudio_read(struct file
*file
, char __user
*buffer
,
71 size_t count
, loff_t
*ppos
)
73 struct hostaudio_state
*state
= file
->private_data
;
78 printk(KERN_DEBUG
"hostaudio: read called, count = %d\n", count
);
81 kbuf
= kmalloc(count
, GFP_KERNEL
);
85 err
= os_read_file(state
->fd
, kbuf
, count
);
89 if (copy_to_user(buffer
, kbuf
, err
))
97 static ssize_t
hostaudio_write(struct file
*file
, const char __user
*buffer
,
98 size_t count
, loff_t
*ppos
)
100 struct hostaudio_state
*state
= file
->private_data
;
105 printk(KERN_DEBUG
"hostaudio: write called, count = %d\n", count
);
108 kbuf
= memdup_user(buffer
, count
);
110 return PTR_ERR(kbuf
);
112 err
= os_write_file(state
->fd
, kbuf
, count
);
122 static __poll_t
hostaudio_poll(struct file
*file
,
123 struct poll_table_struct
*wait
)
128 printk(KERN_DEBUG
"hostaudio: poll called (unimplemented)\n");
134 static long hostaudio_ioctl(struct file
*file
,
135 unsigned int cmd
, unsigned long arg
)
137 struct hostaudio_state
*state
= file
->private_data
;
138 unsigned long data
= 0;
142 printk(KERN_DEBUG
"hostaudio: ioctl called, cmd = %u\n", cmd
);
145 case SNDCTL_DSP_SPEED
:
146 case SNDCTL_DSP_STEREO
:
147 case SNDCTL_DSP_GETBLKSIZE
:
148 case SNDCTL_DSP_CHANNELS
:
149 case SNDCTL_DSP_SUBDIVIDE
:
150 case SNDCTL_DSP_SETFRAGMENT
:
151 if (get_user(data
, (int __user
*) arg
))
158 err
= os_ioctl_generic(state
->fd
, cmd
, (unsigned long) &data
);
161 case SNDCTL_DSP_SPEED
:
162 case SNDCTL_DSP_STEREO
:
163 case SNDCTL_DSP_GETBLKSIZE
:
164 case SNDCTL_DSP_CHANNELS
:
165 case SNDCTL_DSP_SUBDIVIDE
:
166 case SNDCTL_DSP_SETFRAGMENT
:
167 if (put_user(data
, (int __user
*) arg
))
177 static int hostaudio_open(struct inode
*inode
, struct file
*file
)
179 struct hostaudio_state
*state
;
184 kernel_param_lock(THIS_MODULE
);
185 printk(KERN_DEBUG
"hostaudio: open called (host: %s)\n", dsp
);
186 kernel_param_unlock(THIS_MODULE
);
189 state
= kmalloc(sizeof(struct hostaudio_state
), GFP_KERNEL
);
193 if (file
->f_mode
& FMODE_READ
)
195 if (file
->f_mode
& FMODE_WRITE
)
198 kernel_param_lock(THIS_MODULE
);
199 mutex_lock(&hostaudio_mutex
);
200 ret
= os_open_file(dsp
, of_set_rw(OPENFLAGS(), r
, w
), 0);
201 mutex_unlock(&hostaudio_mutex
);
202 kernel_param_unlock(THIS_MODULE
);
209 file
->private_data
= state
;
213 static int hostaudio_release(struct inode
*inode
, struct file
*file
)
215 struct hostaudio_state
*state
= file
->private_data
;
218 printk(KERN_DEBUG
"hostaudio: release called\n");
220 os_close_file(state
->fd
);
226 /* /dev/mixer file operations */
228 static long hostmixer_ioctl_mixdev(struct file
*file
,
229 unsigned int cmd
, unsigned long arg
)
231 struct hostmixer_state
*state
= file
->private_data
;
234 printk(KERN_DEBUG
"hostmixer: ioctl called\n");
237 return os_ioctl_generic(state
->fd
, cmd
, arg
);
240 static int hostmixer_open_mixdev(struct inode
*inode
, struct file
*file
)
242 struct hostmixer_state
*state
;
247 printk(KERN_DEBUG
"hostmixer: open called (host: %s)\n", mixer
);
250 state
= kmalloc(sizeof(struct hostmixer_state
), GFP_KERNEL
);
254 if (file
->f_mode
& FMODE_READ
)
256 if (file
->f_mode
& FMODE_WRITE
)
259 kernel_param_lock(THIS_MODULE
);
260 mutex_lock(&hostaudio_mutex
);
261 ret
= os_open_file(mixer
, of_set_rw(OPENFLAGS(), r
, w
), 0);
262 mutex_unlock(&hostaudio_mutex
);
263 kernel_param_unlock(THIS_MODULE
);
266 kernel_param_lock(THIS_MODULE
);
267 printk(KERN_ERR
"hostaudio_open_mixdev failed to open '%s', "
268 "err = %d\n", dsp
, -ret
);
269 kernel_param_unlock(THIS_MODULE
);
274 file
->private_data
= state
;
278 static int hostmixer_release(struct inode
*inode
, struct file
*file
)
280 struct hostmixer_state
*state
= file
->private_data
;
283 printk(KERN_DEBUG
"hostmixer: release called\n");
286 os_close_file(state
->fd
);
292 /* kernel module operations */
294 static const struct file_operations hostaudio_fops
= {
295 .owner
= THIS_MODULE
,
297 .read
= hostaudio_read
,
298 .write
= hostaudio_write
,
299 .poll
= hostaudio_poll
,
300 .unlocked_ioctl
= hostaudio_ioctl
,
302 .open
= hostaudio_open
,
303 .release
= hostaudio_release
,
306 static const struct file_operations hostmixer_fops
= {
307 .owner
= THIS_MODULE
,
309 .unlocked_ioctl
= hostmixer_ioctl_mixdev
,
310 .open
= hostmixer_open_mixdev
,
311 .release
= hostmixer_release
,
319 MODULE_AUTHOR("Steve Schmidtke");
320 MODULE_DESCRIPTION("UML Audio Relay");
321 MODULE_LICENSE("GPL");
323 static int __init
hostaudio_init_module(void)
325 kernel_param_lock(THIS_MODULE
);
326 printk(KERN_INFO
"UML Audio Relay (host dsp = %s, host mixer = %s)\n",
328 kernel_param_unlock(THIS_MODULE
);
330 module_data
.dev_audio
= register_sound_dsp(&hostaudio_fops
, -1);
331 if (module_data
.dev_audio
< 0) {
332 printk(KERN_ERR
"hostaudio: couldn't register DSP device!\n");
336 module_data
.dev_mixer
= register_sound_mixer(&hostmixer_fops
, -1);
337 if (module_data
.dev_mixer
< 0) {
338 printk(KERN_ERR
"hostmixer: couldn't register mixer "
340 unregister_sound_dsp(module_data
.dev_audio
);
347 static void __exit
hostaudio_cleanup_module (void)
349 unregister_sound_mixer(module_data
.dev_mixer
);
350 unregister_sound_dsp(module_data
.dev_audio
);
353 module_init(hostaudio_init_module
);
354 module_exit(hostaudio_cleanup_module
);