aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/drivers/hostaudio_kern.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/drivers/hostaudio_kern.c')
-rw-r--r--arch/um/drivers/hostaudio_kern.c169
1 files changed, 79 insertions, 90 deletions
diff --git a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c
index a0d148ea63d6..10e08a8c17c3 100644
--- a/arch/um/drivers/hostaudio_kern.c
+++ b/arch/um/drivers/hostaudio_kern.c
@@ -15,19 +15,22 @@
15#include "os.h" 15#include "os.h"
16 16
17struct hostaudio_state { 17struct hostaudio_state {
18 int fd; 18 int fd;
19}; 19};
20 20
21struct hostmixer_state { 21struct hostmixer_state {
22 int fd; 22 int fd;
23}; 23};
24 24
25#define HOSTAUDIO_DEV_DSP "/dev/sound/dsp" 25#define HOSTAUDIO_DEV_DSP "/dev/sound/dsp"
26#define HOSTAUDIO_DEV_MIXER "/dev/sound/mixer" 26#define HOSTAUDIO_DEV_MIXER "/dev/sound/mixer"
27 27
28/* Only changed from linux_main at boot time */ 28/* Changed either at boot time or module load time. At boot, this is
29char *dsp = HOSTAUDIO_DEV_DSP; 29 * single-threaded; at module load, multiple modules would each have
30char *mixer = HOSTAUDIO_DEV_MIXER; 30 * their own copy of these variables.
31 */
32static char *dsp = HOSTAUDIO_DEV_DSP;
33static char *mixer = HOSTAUDIO_DEV_MIXER;
31 34
32#define DSP_HELP \ 35#define DSP_HELP \
33" This is used to specify the host dsp device to the hostaudio driver.\n" \ 36" This is used to specify the host dsp device to the hostaudio driver.\n" \
@@ -69,12 +72,12 @@ MODULE_PARM_DESC(mixer, MIXER_HELP);
69static ssize_t hostaudio_read(struct file *file, char __user *buffer, 72static ssize_t hostaudio_read(struct file *file, char __user *buffer,
70 size_t count, loff_t *ppos) 73 size_t count, loff_t *ppos)
71{ 74{
72 struct hostaudio_state *state = file->private_data; 75 struct hostaudio_state *state = file->private_data;
73 void *kbuf; 76 void *kbuf;
74 int err; 77 int err;
75 78
76#ifdef DEBUG 79#ifdef DEBUG
77 printk("hostaudio: read called, count = %d\n", count); 80 printk("hostaudio: read called, count = %d\n", count);
78#endif 81#endif
79 82
80 kbuf = kmalloc(count, GFP_KERNEL); 83 kbuf = kmalloc(count, GFP_KERNEL);
@@ -88,7 +91,7 @@ static ssize_t hostaudio_read(struct file *file, char __user *buffer,
88 if(copy_to_user(buffer, kbuf, err)) 91 if(copy_to_user(buffer, kbuf, err))
89 err = -EFAULT; 92 err = -EFAULT;
90 93
91 out: 94out:
92 kfree(kbuf); 95 kfree(kbuf);
93 return(err); 96 return(err);
94} 97}
@@ -96,12 +99,12 @@ static ssize_t hostaudio_read(struct file *file, char __user *buffer,
96static ssize_t hostaudio_write(struct file *file, const char __user *buffer, 99static ssize_t hostaudio_write(struct file *file, const char __user *buffer,
97 size_t count, loff_t *ppos) 100 size_t count, loff_t *ppos)
98{ 101{
99 struct hostaudio_state *state = file->private_data; 102 struct hostaudio_state *state = file->private_data;
100 void *kbuf; 103 void *kbuf;
101 int err; 104 int err;
102 105
103#ifdef DEBUG 106#ifdef DEBUG
104 printk("hostaudio: write called, count = %d\n", count); 107 printk("hostaudio: write called, count = %d\n", count);
105#endif 108#endif
106 109
107 kbuf = kmalloc(count, GFP_KERNEL); 110 kbuf = kmalloc(count, GFP_KERNEL);
@@ -125,24 +128,24 @@ static ssize_t hostaudio_write(struct file *file, const char __user *buffer,
125static unsigned int hostaudio_poll(struct file *file, 128static unsigned int hostaudio_poll(struct file *file,
126 struct poll_table_struct *wait) 129 struct poll_table_struct *wait)
127{ 130{
128 unsigned int mask = 0; 131 unsigned int mask = 0;
129 132
130#ifdef DEBUG 133#ifdef DEBUG
131 printk("hostaudio: poll called (unimplemented)\n"); 134 printk("hostaudio: poll called (unimplemented)\n");
132#endif 135#endif
133 136
134 return(mask); 137 return(mask);
135} 138}
136 139
137static int hostaudio_ioctl(struct inode *inode, struct file *file, 140static int hostaudio_ioctl(struct inode *inode, struct file *file,
138 unsigned int cmd, unsigned long arg) 141 unsigned int cmd, unsigned long arg)
139{ 142{
140 struct hostaudio_state *state = file->private_data; 143 struct hostaudio_state *state = file->private_data;
141 unsigned long data = 0; 144 unsigned long data = 0;
142 int err; 145 int err;
143 146
144#ifdef DEBUG 147#ifdef DEBUG
145 printk("hostaudio: ioctl called, cmd = %u\n", cmd); 148 printk("hostaudio: ioctl called, cmd = %u\n", cmd);
146#endif 149#endif
147 switch(cmd){ 150 switch(cmd){
148 case SNDCTL_DSP_SPEED: 151 case SNDCTL_DSP_SPEED:
@@ -179,42 +182,40 @@ static int hostaudio_ioctl(struct inode *inode, struct file *file,
179 182
180static int hostaudio_open(struct inode *inode, struct file *file) 183static int hostaudio_open(struct inode *inode, struct file *file)
181{ 184{
182 struct hostaudio_state *state; 185 struct hostaudio_state *state;
183 int r = 0, w = 0; 186 int r = 0, w = 0;
184 int ret; 187 int ret;
185 188
186#ifdef DEBUG 189#ifdef DEBUG
187 printk("hostaudio: open called (host: %s)\n", dsp); 190 printk("hostaudio: open called (host: %s)\n", dsp);
188#endif 191#endif
189 192
190 state = kmalloc(sizeof(struct hostaudio_state), GFP_KERNEL); 193 state = kmalloc(sizeof(struct hostaudio_state), GFP_KERNEL);
191 if(state == NULL) 194 if(state == NULL)
192 return(-ENOMEM); 195 return(-ENOMEM);
193 196
194 if(file->f_mode & FMODE_READ) r = 1; 197 if(file->f_mode & FMODE_READ) r = 1;
195 if(file->f_mode & FMODE_WRITE) w = 1; 198 if(file->f_mode & FMODE_WRITE) w = 1;
196 199
197 ret = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0); 200 ret = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0);
198 if(ret < 0){ 201 if(ret < 0){
199 kfree(state); 202 kfree(state);
200 return(ret); 203 return(ret);
201 } 204 }
202
203 state->fd = ret; 205 state->fd = ret;
204 file->private_data = state; 206 file->private_data = state;
205 return(0); 207 return(0);
206} 208}
207 209
208static int hostaudio_release(struct inode *inode, struct file *file) 210static int hostaudio_release(struct inode *inode, struct file *file)
209{ 211{
210 struct hostaudio_state *state = file->private_data; 212 struct hostaudio_state *state = file->private_data;
211 213
212#ifdef DEBUG 214#ifdef DEBUG
213 printk("hostaudio: release called\n"); 215 printk("hostaudio: release called\n");
214#endif 216#endif
215 217 os_close_file(state->fd);
216 os_close_file(state->fd); 218 kfree(state);
217 kfree(state);
218 219
219 return(0); 220 return(0);
220} 221}
@@ -224,10 +225,10 @@ static int hostaudio_release(struct inode *inode, struct file *file)
224static int hostmixer_ioctl_mixdev(struct inode *inode, struct file *file, 225static int hostmixer_ioctl_mixdev(struct inode *inode, struct file *file,
225 unsigned int cmd, unsigned long arg) 226 unsigned int cmd, unsigned long arg)
226{ 227{
227 struct hostmixer_state *state = file->private_data; 228 struct hostmixer_state *state = file->private_data;
228 229
229#ifdef DEBUG 230#ifdef DEBUG
230 printk("hostmixer: ioctl called\n"); 231 printk("hostmixer: ioctl called\n");
231#endif 232#endif
232 233
233 return(os_ioctl_generic(state->fd, cmd, arg)); 234 return(os_ioctl_generic(state->fd, cmd, arg));
@@ -235,68 +236,67 @@ static int hostmixer_ioctl_mixdev(struct inode *inode, struct file *file,
235 236
236static int hostmixer_open_mixdev(struct inode *inode, struct file *file) 237static int hostmixer_open_mixdev(struct inode *inode, struct file *file)
237{ 238{
238 struct hostmixer_state *state; 239 struct hostmixer_state *state;
239 int r = 0, w = 0; 240 int r = 0, w = 0;
240 int ret; 241 int ret;
241 242
242#ifdef DEBUG 243#ifdef DEBUG
243 printk("hostmixer: open called (host: %s)\n", mixer); 244 printk("hostmixer: open called (host: %s)\n", mixer);
244#endif 245#endif
245 246
246 state = kmalloc(sizeof(struct hostmixer_state), GFP_KERNEL); 247 state = kmalloc(sizeof(struct hostmixer_state), GFP_KERNEL);
247 if(state == NULL) return(-ENOMEM); 248 if(state == NULL) return(-ENOMEM);
248 249
249 if(file->f_mode & FMODE_READ) r = 1; 250 if(file->f_mode & FMODE_READ) r = 1;
250 if(file->f_mode & FMODE_WRITE) w = 1; 251 if(file->f_mode & FMODE_WRITE) w = 1;
251 252
252 ret = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0); 253 ret = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0);
253 254
254 if(ret < 0){ 255 if(ret < 0){
255 printk("hostaudio_open_mixdev failed to open '%s', err = %d\n", 256 printk("hostaudio_open_mixdev failed to open '%s', err = %d\n",
256 dsp, -ret); 257 dsp, -ret);
257 kfree(state); 258 kfree(state);
258 return(ret); 259 return(ret);
259 } 260 }
260 261
261 file->private_data = state; 262 file->private_data = state;
262 return(0); 263 return(0);
263} 264}
264 265
265static int hostmixer_release(struct inode *inode, struct file *file) 266static int hostmixer_release(struct inode *inode, struct file *file)
266{ 267{
267 struct hostmixer_state *state = file->private_data; 268 struct hostmixer_state *state = file->private_data;
268 269
269#ifdef DEBUG 270#ifdef DEBUG
270 printk("hostmixer: release called\n"); 271 printk("hostmixer: release called\n");
271#endif 272#endif
272 273
273 os_close_file(state->fd); 274 os_close_file(state->fd);
274 kfree(state); 275 kfree(state);
275 276
276 return(0); 277 return(0);
277} 278}
278 279
279
280/* kernel module operations */ 280/* kernel module operations */
281 281
282static const struct file_operations hostaudio_fops = { 282static const struct file_operations hostaudio_fops = {
283 .owner = THIS_MODULE, 283 .owner = THIS_MODULE,
284 .llseek = no_llseek, 284 .llseek = no_llseek,
285 .read = hostaudio_read, 285 .read = hostaudio_read,
286 .write = hostaudio_write, 286 .write = hostaudio_write,
287 .poll = hostaudio_poll, 287 .poll = hostaudio_poll,
288 .ioctl = hostaudio_ioctl, 288 .ioctl = hostaudio_ioctl,
289 .mmap = NULL, 289 .mmap = NULL,
290 .open = hostaudio_open, 290 .open = hostaudio_open,
291 .release = hostaudio_release, 291 .release = hostaudio_release,
292}; 292};
293 293
294static const struct file_operations hostmixer_fops = { 294static const struct file_operations hostmixer_fops = {
295 .owner = THIS_MODULE, 295 .owner = THIS_MODULE,
296 .llseek = no_llseek, 296 .llseek = no_llseek,
297 .ioctl = hostmixer_ioctl_mixdev, 297 .ioctl = hostmixer_ioctl_mixdev,
298 .open = hostmixer_open_mixdev, 298 .open = hostmixer_open_mixdev,
299 .release = hostmixer_release, 299 .release = hostmixer_release,
300}; 300};
301 301
302struct { 302struct {
@@ -310,42 +310,31 @@ MODULE_LICENSE("GPL");
310 310
311static int __init hostaudio_init_module(void) 311static int __init hostaudio_init_module(void)
312{ 312{
313 printk(KERN_INFO "UML Audio Relay (host dsp = %s, host mixer = %s)\n", 313 printk(KERN_INFO "UML Audio Relay (host dsp = %s, host mixer = %s)\n",
314 dsp, mixer); 314 dsp, mixer);
315 315
316 module_data.dev_audio = register_sound_dsp(&hostaudio_fops, -1); 316 module_data.dev_audio = register_sound_dsp(&hostaudio_fops, -1);
317 if(module_data.dev_audio < 0){ 317 if(module_data.dev_audio < 0){
318 printk(KERN_ERR "hostaudio: couldn't register DSP device!\n"); 318 printk(KERN_ERR "hostaudio: couldn't register DSP device!\n");
319 return -ENODEV; 319 return -ENODEV;
320 } 320 }
321 321
322 module_data.dev_mixer = register_sound_mixer(&hostmixer_fops, -1); 322 module_data.dev_mixer = register_sound_mixer(&hostmixer_fops, -1);
323 if(module_data.dev_mixer < 0){ 323 if(module_data.dev_mixer < 0){
324 printk(KERN_ERR "hostmixer: couldn't register mixer " 324 printk(KERN_ERR "hostmixer: couldn't register mixer "
325 "device!\n"); 325 "device!\n");
326 unregister_sound_dsp(module_data.dev_audio); 326 unregister_sound_dsp(module_data.dev_audio);
327 return -ENODEV; 327 return -ENODEV;
328 } 328 }
329 329
330 return 0; 330 return 0;
331} 331}
332 332
333static void __exit hostaudio_cleanup_module (void) 333static void __exit hostaudio_cleanup_module (void)
334{ 334{
335 unregister_sound_mixer(module_data.dev_mixer); 335 unregister_sound_mixer(module_data.dev_mixer);
336 unregister_sound_dsp(module_data.dev_audio); 336 unregister_sound_dsp(module_data.dev_audio);
337} 337}
338 338
339module_init(hostaudio_init_module); 339module_init(hostaudio_init_module);
340module_exit(hostaudio_cleanup_module); 340module_exit(hostaudio_cleanup_module);
341
342/*
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
346 * of the file.
347 * ---------------------------------------------------------------------------
348 * Local variables:
349 * c-file-style: "linux"
350 * End:
351 */