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