root/arch/um/drivers/hostaudio_kern.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. set_dsp
  2. set_mixer
  3. hostaudio_read
  4. hostaudio_write
  5. hostaudio_poll
  6. hostaudio_ioctl
  7. hostaudio_open
  8. hostaudio_release
  9. hostmixer_ioctl_mixdev
  10. hostmixer_open_mixdev
  11. hostmixer_release
  12. hostaudio_init_module
  13. hostaudio_cleanup_module

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

/* [<][>][^][v][top][bottom][index][help] */