2 * Copyright (C) 2002 Steve Schmidtke
3 * Licensed under the GPL
6 #include "linux/module.h"
7 #include "linux/init.h"
8 #include "linux/slab.h"
10 #include "linux/sound.h"
11 #include "linux/soundcard.h"
12 #include "asm/uaccess.h"
13 #include "kern_util.h"
17 struct hostaudio_state
{
21 struct hostmixer_state
{
25 #define HOSTAUDIO_DEV_DSP "/dev/sound/dsp"
26 #define HOSTAUDIO_DEV_MIXER "/dev/sound/mixer"
28 /* Only changed from linux_main at boot time */
29 char *dsp
= HOSTAUDIO_DEV_DSP
;
30 char *mixer
= HOSTAUDIO_DEV_MIXER
;
33 " This is used to specify the host dsp device to the hostaudio driver.\n" \
34 " The default is \"" HOSTAUDIO_DEV_DSP "\".\n\n"
37 " This is used to specify the host mixer device to the hostaudio driver.\n"\
38 " The default is \"" HOSTAUDIO_DEV_MIXER "\".\n\n"
41 static int set_dsp(char *name
, int *add
)
47 __uml_setup("dsp=", set_dsp
, "dsp=<dsp device>\n" DSP_HELP
);
49 static int set_mixer(char *name
, int *add
)
55 __uml_setup("mixer=", set_mixer
, "mixer=<mixer device>\n" MIXER_HELP
);
59 module_param(dsp
, charp
, 0644);
60 MODULE_PARM_DESC(dsp
, DSP_HELP
);
62 module_param(mixer
, charp
, 0644);
63 MODULE_PARM_DESC(mixer
, MIXER_HELP
);
67 /* /dev/dsp file operations */
69 static ssize_t
hostaudio_read(struct file
*file
, char __user
*buffer
,
70 size_t count
, loff_t
*ppos
)
72 struct hostaudio_state
*state
= file
->private_data
;
77 printk("hostaudio: read called, count = %d\n", count
);
80 kbuf
= kmalloc(count
, GFP_KERNEL
);
84 err
= os_read_file(state
->fd
, kbuf
, count
);
88 if(copy_to_user(buffer
, kbuf
, err
))
96 static ssize_t
hostaudio_write(struct file
*file
, const char __user
*buffer
,
97 size_t count
, loff_t
*ppos
)
99 struct hostaudio_state
*state
= file
->private_data
;
104 printk("hostaudio: write called, count = %d\n", count
);
107 kbuf
= kmalloc(count
, GFP_KERNEL
);
112 if(copy_from_user(kbuf
, buffer
, count
))
115 err
= os_write_file(state
->fd
, kbuf
, count
);
125 static unsigned int hostaudio_poll(struct file
*file
,
126 struct poll_table_struct
*wait
)
128 unsigned int mask
= 0;
131 printk("hostaudio: poll called (unimplemented)\n");
137 static int hostaudio_ioctl(struct inode
*inode
, struct file
*file
,
138 unsigned int cmd
, unsigned long arg
)
140 struct hostaudio_state
*state
= file
->private_data
;
141 unsigned long data
= 0;
145 printk("hostaudio: ioctl called, cmd = %u\n", cmd
);
148 case SNDCTL_DSP_SPEED
:
149 case SNDCTL_DSP_STEREO
:
150 case SNDCTL_DSP_GETBLKSIZE
:
151 case SNDCTL_DSP_CHANNELS
:
152 case SNDCTL_DSP_SUBDIVIDE
:
153 case SNDCTL_DSP_SETFRAGMENT
:
154 if(get_user(data
, (int __user
*) arg
))
161 err
= os_ioctl_generic(state
->fd
, cmd
, (unsigned long) &data
);
164 case SNDCTL_DSP_SPEED
:
165 case SNDCTL_DSP_STEREO
:
166 case SNDCTL_DSP_GETBLKSIZE
:
167 case SNDCTL_DSP_CHANNELS
:
168 case SNDCTL_DSP_SUBDIVIDE
:
169 case SNDCTL_DSP_SETFRAGMENT
:
170 if(put_user(data
, (int __user
*) arg
))
180 static int hostaudio_open(struct inode
*inode
, struct file
*file
)
182 struct hostaudio_state
*state
;
187 printk("hostaudio: open called (host: %s)\n", dsp
);
190 state
= kmalloc(sizeof(struct hostaudio_state
), GFP_KERNEL
);
194 if(file
->f_mode
& FMODE_READ
) r
= 1;
195 if(file
->f_mode
& FMODE_WRITE
) w
= 1;
197 ret
= os_open_file(dsp
, of_set_rw(OPENFLAGS(), r
, w
), 0);
204 file
->private_data
= state
;
208 static int hostaudio_release(struct inode
*inode
, struct file
*file
)
210 struct hostaudio_state
*state
= file
->private_data
;
213 printk("hostaudio: release called\n");
216 os_close_file(state
->fd
);
222 /* /dev/mixer file operations */
224 static int hostmixer_ioctl_mixdev(struct inode
*inode
, struct file
*file
,
225 unsigned int cmd
, unsigned long arg
)
227 struct hostmixer_state
*state
= file
->private_data
;
230 printk("hostmixer: ioctl called\n");
233 return(os_ioctl_generic(state
->fd
, cmd
, arg
));
236 static int hostmixer_open_mixdev(struct inode
*inode
, struct file
*file
)
238 struct hostmixer_state
*state
;
243 printk("hostmixer: open called (host: %s)\n", mixer
);
246 state
= kmalloc(sizeof(struct hostmixer_state
), GFP_KERNEL
);
247 if(state
== NULL
) return(-ENOMEM
);
249 if(file
->f_mode
& FMODE_READ
) r
= 1;
250 if(file
->f_mode
& FMODE_WRITE
) w
= 1;
252 ret
= os_open_file(mixer
, of_set_rw(OPENFLAGS(), r
, w
), 0);
255 printk("hostaudio_open_mixdev failed to open '%s', err = %d\n",
261 file
->private_data
= state
;
265 static int hostmixer_release(struct inode
*inode
, struct file
*file
)
267 struct hostmixer_state
*state
= file
->private_data
;
270 printk("hostmixer: release called\n");
273 os_close_file(state
->fd
);
280 /* kernel module operations */
282 static const struct file_operations hostaudio_fops
= {
283 .owner
= THIS_MODULE
,
285 .read
= hostaudio_read
,
286 .write
= hostaudio_write
,
287 .poll
= hostaudio_poll
,
288 .ioctl
= hostaudio_ioctl
,
290 .open
= hostaudio_open
,
291 .release
= hostaudio_release
,
294 static const struct file_operations hostmixer_fops
= {
295 .owner
= THIS_MODULE
,
297 .ioctl
= hostmixer_ioctl_mixdev
,
298 .open
= hostmixer_open_mixdev
,
299 .release
= hostmixer_release
,
307 MODULE_AUTHOR("Steve Schmidtke");
308 MODULE_DESCRIPTION("UML Audio Relay");
309 MODULE_LICENSE("GPL");
311 static int __init
hostaudio_init_module(void)
313 printk(KERN_INFO
"UML Audio Relay (host dsp = %s, host mixer = %s)\n",
316 module_data
.dev_audio
= register_sound_dsp(&hostaudio_fops
, -1);
317 if(module_data
.dev_audio
< 0){
318 printk(KERN_ERR
"hostaudio: couldn't register DSP device!\n");
322 module_data
.dev_mixer
= register_sound_mixer(&hostmixer_fops
, -1);
323 if(module_data
.dev_mixer
< 0){
324 printk(KERN_ERR
"hostmixer: couldn't register mixer "
326 unregister_sound_dsp(module_data
.dev_audio
);
333 static void __exit
hostaudio_cleanup_module (void)
335 unregister_sound_mixer(module_data
.dev_mixer
);
336 unregister_sound_dsp(module_data
.dev_audio
);
339 module_init(hostaudio_init_module
);
340 module_exit(hostaudio_cleanup_module
);
343 * Overrides for Emacs so that we follow Linus's tabbing style.
344 * Emacs will notice this stuff at the end of the file and automatically
345 * adjust the settings for this buffer only. This must remain at the end
347 * ---------------------------------------------------------------------------
349 * c-file-style: "linux"