Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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