]> bbs.cooldavid.org Git - net-next-2.6.git/blame - arch/um/drivers/hostaudio_kern.c
sound: push BKL into open functions
[net-next-2.6.git] / arch / um / drivers / hostaudio_kern.c
CommitLineData
cb8fa61c
JD
1/*
2 * Copyright (C) 2002 Steve Schmidtke
1da177e4
LT
3 * Licensed under the GPL
4 */
5
cb8fa61c 6#include "linux/fs.h"
1da177e4 7#include "linux/module.h"
1da177e4 8#include "linux/slab.h"
1da177e4
LT
9#include "linux/sound.h"
10#include "linux/soundcard.h"
90dc763f 11#include "linux/smp_lock.h"
1da177e4 12#include "asm/uaccess.h"
1da177e4
LT
13#include "init.h"
14#include "os.h"
15
16struct hostaudio_state {
d471c0fc 17 int fd;
1da177e4
LT
18};
19
20struct hostmixer_state {
d471c0fc 21 int fd;
1da177e4
LT
22};
23
24#define HOSTAUDIO_DEV_DSP "/dev/sound/dsp"
25#define HOSTAUDIO_DEV_MIXER "/dev/sound/mixer"
26
cb8fa61c
JD
27/*
28 * Changed either at boot time or module load time. At boot, this is
b612e475
JD
29 * single-threaded; at module load, multiple modules would each have
30 * their own copy of these variables.
31 */
32static char *dsp = HOSTAUDIO_DEV_DSP;
33static char *mixer = HOSTAUDIO_DEV_MIXER;
1da177e4
LT
34
35#define DSP_HELP \
36" This is used to specify the host dsp device to the hostaudio driver.\n" \
37" The default is \"" HOSTAUDIO_DEV_DSP "\".\n\n"
38
39#define MIXER_HELP \
40" This is used to specify the host mixer device to the hostaudio driver.\n"\
41" The default is \"" HOSTAUDIO_DEV_MIXER "\".\n\n"
42
43#ifndef MODULE
44static int set_dsp(char *name, int *add)
45{
46 dsp = name;
cb8fa61c 47 return 0;
1da177e4
LT
48}
49
50__uml_setup("dsp=", set_dsp, "dsp=<dsp device>\n" DSP_HELP);
51
52static int set_mixer(char *name, int *add)
53{
54 mixer = name;
cb8fa61c 55 return 0;
1da177e4
LT
56}
57
58__uml_setup("mixer=", set_mixer, "mixer=<mixer device>\n" MIXER_HELP);
59
60#else /*MODULE*/
61
20a64f1d 62module_param(dsp, charp, 0644);
1da177e4
LT
63MODULE_PARM_DESC(dsp, DSP_HELP);
64
20a64f1d 65module_param(mixer, charp, 0644);
1da177e4
LT
66MODULE_PARM_DESC(mixer, MIXER_HELP);
67
68#endif
69
70/* /dev/dsp file operations */
71
4d338e1a
AV
72static ssize_t hostaudio_read(struct file *file, char __user *buffer,
73 size_t count, loff_t *ppos)
1da177e4 74{
d471c0fc 75 struct hostaudio_state *state = file->private_data;
1da177e4
LT
76 void *kbuf;
77 int err;
78
79#ifdef DEBUG
cb8fa61c 80 printk(KERN_DEBUG "hostaudio: read called, count = %d\n", count);
1da177e4
LT
81#endif
82
83 kbuf = kmalloc(count, GFP_KERNEL);
cb8fa61c
JD
84 if (kbuf == NULL)
85 return -ENOMEM;
1da177e4 86
a6ea4cce 87 err = os_read_file(state->fd, kbuf, count);
cb8fa61c 88 if (err < 0)
1da177e4
LT
89 goto out;
90
cb8fa61c 91 if (copy_to_user(buffer, kbuf, err))
1da177e4
LT
92 err = -EFAULT;
93
d471c0fc 94out:
1da177e4 95 kfree(kbuf);
cb8fa61c 96 return err;
1da177e4
LT
97}
98
4d338e1a 99static ssize_t hostaudio_write(struct file *file, const char __user *buffer,
1da177e4
LT
100 size_t count, loff_t *ppos)
101{
d471c0fc 102 struct hostaudio_state *state = file->private_data;
1da177e4
LT
103 void *kbuf;
104 int err;
105
106#ifdef DEBUG
cb8fa61c 107 printk(KERN_DEBUG "hostaudio: write called, count = %d\n", count);
1da177e4
LT
108#endif
109
110 kbuf = kmalloc(count, GFP_KERNEL);
cb8fa61c
JD
111 if (kbuf == NULL)
112 return -ENOMEM;
1da177e4
LT
113
114 err = -EFAULT;
cb8fa61c 115 if (copy_from_user(kbuf, buffer, count))
1da177e4
LT
116 goto out;
117
a6ea4cce 118 err = os_write_file(state->fd, kbuf, count);
cb8fa61c 119 if (err < 0)
1da177e4
LT
120 goto out;
121 *ppos += err;
122
123 out:
124 kfree(kbuf);
cb8fa61c 125 return err;
1da177e4
LT
126}
127
cb8fa61c 128static unsigned int hostaudio_poll(struct file *file,
1da177e4
LT
129 struct poll_table_struct *wait)
130{
d471c0fc 131 unsigned int mask = 0;
1da177e4
LT
132
133#ifdef DEBUG
cb8fa61c 134 printk(KERN_DEBUG "hostaudio: poll called (unimplemented)\n");
1da177e4
LT
135#endif
136
cb8fa61c 137 return mask;
1da177e4
LT
138}
139
d6c89d9a 140static long hostaudio_ioctl(struct file *file,
1da177e4
LT
141 unsigned int cmd, unsigned long arg)
142{
d471c0fc 143 struct hostaudio_state *state = file->private_data;
1da177e4
LT
144 unsigned long data = 0;
145 int err;
146
147#ifdef DEBUG
cb8fa61c 148 printk(KERN_DEBUG "hostaudio: ioctl called, cmd = %u\n", cmd);
1da177e4
LT
149#endif
150 switch(cmd){
151 case SNDCTL_DSP_SPEED:
152 case SNDCTL_DSP_STEREO:
153 case SNDCTL_DSP_GETBLKSIZE:
154 case SNDCTL_DSP_CHANNELS:
155 case SNDCTL_DSP_SUBDIVIDE:
156 case SNDCTL_DSP_SETFRAGMENT:
cb8fa61c 157 if (get_user(data, (int __user *) arg))
484f1e2c 158 return -EFAULT;
1da177e4
LT
159 break;
160 default:
161 break;
162 }
163
164 err = os_ioctl_generic(state->fd, cmd, (unsigned long) &data);
165
166 switch(cmd){
167 case SNDCTL_DSP_SPEED:
168 case SNDCTL_DSP_STEREO:
169 case SNDCTL_DSP_GETBLKSIZE:
170 case SNDCTL_DSP_CHANNELS:
171 case SNDCTL_DSP_SUBDIVIDE:
172 case SNDCTL_DSP_SETFRAGMENT:
cb8fa61c
JD
173 if (put_user(data, (int __user *) arg))
174 return -EFAULT;
1da177e4
LT
175 break;
176 default:
177 break;
178 }
179
cb8fa61c 180 return err;
1da177e4
LT
181}
182
183static int hostaudio_open(struct inode *inode, struct file *file)
184{
d471c0fc
JD
185 struct hostaudio_state *state;
186 int r = 0, w = 0;
187 int ret;
1da177e4
LT
188
189#ifdef DEBUG
cb8fa61c 190 printk(KERN_DEBUG "hostaudio: open called (host: %s)\n", dsp);
1da177e4
LT
191#endif
192
d471c0fc 193 state = kmalloc(sizeof(struct hostaudio_state), GFP_KERNEL);
cb8fa61c
JD
194 if (state == NULL)
195 return -ENOMEM;
1da177e4 196
cb8fa61c
JD
197 if (file->f_mode & FMODE_READ)
198 r = 1;
199 if (file->f_mode & FMODE_WRITE)
200 w = 1;
1da177e4 201
90dc763f 202 lock_kernel();
1da177e4 203 ret = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0);
90dc763f
AB
204 unlock_kernel();
205
cb8fa61c 206 if (ret < 0) {
1da177e4 207 kfree(state);
cb8fa61c 208 return ret;
d471c0fc 209 }
1da177e4 210 state->fd = ret;
d471c0fc 211 file->private_data = state;
cb8fa61c 212 return 0;
1da177e4
LT
213}
214
215static int hostaudio_release(struct inode *inode, struct file *file)
216{
d471c0fc 217 struct hostaudio_state *state = file->private_data;
1da177e4
LT
218
219#ifdef DEBUG
cb8fa61c 220 printk(KERN_DEBUG "hostaudio: release called\n");
1da177e4 221#endif
d471c0fc
JD
222 os_close_file(state->fd);
223 kfree(state);
1da177e4 224
cb8fa61c 225 return 0;
1da177e4
LT
226}
227
228/* /dev/mixer file operations */
229
d6c89d9a 230static long hostmixer_ioctl_mixdev(struct file *file,
1da177e4
LT
231 unsigned int cmd, unsigned long arg)
232{
d471c0fc 233 struct hostmixer_state *state = file->private_data;
1da177e4
LT
234
235#ifdef DEBUG
cb8fa61c 236 printk(KERN_DEBUG "hostmixer: ioctl called\n");
1da177e4
LT
237#endif
238
cb8fa61c 239 return os_ioctl_generic(state->fd, cmd, arg);
1da177e4
LT
240}
241
242static int hostmixer_open_mixdev(struct inode *inode, struct file *file)
243{
d471c0fc
JD
244 struct hostmixer_state *state;
245 int r = 0, w = 0;
246 int ret;
1da177e4
LT
247
248#ifdef DEBUG
cb8fa61c 249 printk(KERN_DEBUG "hostmixer: open called (host: %s)\n", mixer);
1da177e4
LT
250#endif
251
d471c0fc 252 state = kmalloc(sizeof(struct hostmixer_state), GFP_KERNEL);
cb8fa61c
JD
253 if (state == NULL)
254 return -ENOMEM;
1da177e4 255
cb8fa61c
JD
256 if (file->f_mode & FMODE_READ)
257 r = 1;
258 if (file->f_mode & FMODE_WRITE)
259 w = 1;
1da177e4 260
90dc763f 261 lock_kernel();
1da177e4 262 ret = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0);
90dc763f 263 unlock_kernel();
cb8fa61c
JD
264
265 if (ret < 0) {
266 printk(KERN_ERR "hostaudio_open_mixdev failed to open '%s', "
267 "err = %d\n", dsp, -ret);
1da177e4 268 kfree(state);
cb8fa61c 269 return ret;
d471c0fc 270 }
1da177e4 271
d471c0fc 272 file->private_data = state;
cb8fa61c 273 return 0;
1da177e4
LT
274}
275
276static int hostmixer_release(struct inode *inode, struct file *file)
277{
d471c0fc 278 struct hostmixer_state *state = file->private_data;
1da177e4
LT
279
280#ifdef DEBUG
cb8fa61c 281 printk(KERN_DEBUG "hostmixer: release called\n");
1da177e4
LT
282#endif
283
d471c0fc
JD
284 os_close_file(state->fd);
285 kfree(state);
1da177e4 286
cb8fa61c 287 return 0;
1da177e4
LT
288}
289
1da177e4
LT
290/* kernel module operations */
291
5e7672ec 292static const struct file_operations hostaudio_fops = {
d471c0fc
JD
293 .owner = THIS_MODULE,
294 .llseek = no_llseek,
295 .read = hostaudio_read,
296 .write = hostaudio_write,
297 .poll = hostaudio_poll,
d6c89d9a 298 .unlocked_ioctl = hostaudio_ioctl,
d471c0fc
JD
299 .mmap = NULL,
300 .open = hostaudio_open,
301 .release = hostaudio_release,
1da177e4
LT
302};
303
5e7672ec 304static const struct file_operations hostmixer_fops = {
d471c0fc
JD
305 .owner = THIS_MODULE,
306 .llseek = no_llseek,
d6c89d9a 307 .unlocked_ioctl = hostmixer_ioctl_mixdev,
d471c0fc
JD
308 .open = hostmixer_open_mixdev,
309 .release = hostmixer_release,
1da177e4
LT
310};
311
312struct {
313 int dev_audio;
314 int dev_mixer;
315} module_data;
316
317MODULE_AUTHOR("Steve Schmidtke");
318MODULE_DESCRIPTION("UML Audio Relay");
319MODULE_LICENSE("GPL");
320
321static int __init hostaudio_init_module(void)
322{
d471c0fc 323 printk(KERN_INFO "UML Audio Relay (host dsp = %s, host mixer = %s)\n",
1da177e4
LT
324 dsp, mixer);
325
326 module_data.dev_audio = register_sound_dsp(&hostaudio_fops, -1);
cb8fa61c 327 if (module_data.dev_audio < 0) {
d471c0fc
JD
328 printk(KERN_ERR "hostaudio: couldn't register DSP device!\n");
329 return -ENODEV;
330 }
1da177e4
LT
331
332 module_data.dev_mixer = register_sound_mixer(&hostmixer_fops, -1);
cb8fa61c 333 if (module_data.dev_mixer < 0) {
d471c0fc 334 printk(KERN_ERR "hostmixer: couldn't register mixer "
1da177e4 335 "device!\n");
d471c0fc
JD
336 unregister_sound_dsp(module_data.dev_audio);
337 return -ENODEV;
338 }
1da177e4 339
d471c0fc 340 return 0;
1da177e4
LT
341}
342
343static void __exit hostaudio_cleanup_module (void)
344{
d471c0fc
JD
345 unregister_sound_mixer(module_data.dev_mixer);
346 unregister_sound_dsp(module_data.dev_audio);
1da177e4
LT
347}
348
349module_init(hostaudio_init_module);
350module_exit(hostaudio_cleanup_module);