root/sound/synth/emux/emux_hwdep.c

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

DEFINITIONS

This source file includes following definitions.
  1. snd_emux_hwdep_load_patch
  2. snd_emux_hwdep_misc_mode
  3. snd_emux_hwdep_ioctl
  4. snd_emux_init_hwdep
  5. snd_emux_delete_hwdep

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  *  Interface for hwdep device
   4  *
   5  *  Copyright (C) 2004 Takashi Iwai <tiwai@suse.de>
   6  */
   7 
   8 #include <sound/core.h>
   9 #include <sound/hwdep.h>
  10 #include <linux/uaccess.h>
  11 #include <linux/nospec.h>
  12 #include "emux_voice.h"
  13 
  14 #define TMP_CLIENT_ID   0x1001
  15 
  16 /*
  17  * load patch
  18  */
  19 static int
  20 snd_emux_hwdep_load_patch(struct snd_emux *emu, void __user *arg)
  21 {
  22         int err;
  23         struct soundfont_patch_info patch;
  24 
  25         if (copy_from_user(&patch, arg, sizeof(patch)))
  26                 return -EFAULT;
  27 
  28         if (patch.key == GUS_PATCH)
  29                 return snd_soundfont_load_guspatch(emu->sflist, arg,
  30                                                    patch.len + sizeof(patch),
  31                                                    TMP_CLIENT_ID);
  32 
  33         if (patch.type >= SNDRV_SFNT_LOAD_INFO &&
  34             patch.type <= SNDRV_SFNT_PROBE_DATA) {
  35                 err = snd_soundfont_load(emu->sflist, arg, patch.len + sizeof(patch), TMP_CLIENT_ID);
  36                 if (err < 0)
  37                         return err;
  38         } else {
  39                 if (emu->ops.load_fx)
  40                         return emu->ops.load_fx(emu, patch.type, patch.optarg, arg, patch.len + sizeof(patch));
  41                 else
  42                         return -EINVAL;
  43         }
  44         return 0;
  45 }
  46 
  47 /*
  48  * set misc mode
  49  */
  50 static int
  51 snd_emux_hwdep_misc_mode(struct snd_emux *emu, void __user *arg)
  52 {
  53         struct snd_emux_misc_mode info;
  54         int i;
  55 
  56         if (copy_from_user(&info, arg, sizeof(info)))
  57                 return -EFAULT;
  58         if (info.mode < 0 || info.mode >= EMUX_MD_END)
  59                 return -EINVAL;
  60         info.mode = array_index_nospec(info.mode, EMUX_MD_END);
  61 
  62         if (info.port < 0) {
  63                 for (i = 0; i < emu->num_ports; i++)
  64                         emu->portptrs[i]->ctrls[info.mode] = info.value;
  65         } else {
  66                 if (info.port < emu->num_ports) {
  67                         info.port = array_index_nospec(info.port, emu->num_ports);
  68                         emu->portptrs[info.port]->ctrls[info.mode] = info.value;
  69                 }
  70         }
  71         return 0;
  72 }
  73 
  74 
  75 /*
  76  * ioctl
  77  */
  78 static int
  79 snd_emux_hwdep_ioctl(struct snd_hwdep * hw, struct file *file,
  80                      unsigned int cmd, unsigned long arg)
  81 {
  82         struct snd_emux *emu = hw->private_data;
  83 
  84         switch (cmd) {
  85         case SNDRV_EMUX_IOCTL_VERSION:
  86                 return put_user(SNDRV_EMUX_VERSION, (unsigned int __user *)arg);
  87         case SNDRV_EMUX_IOCTL_LOAD_PATCH:
  88                 return snd_emux_hwdep_load_patch(emu, (void __user *)arg);
  89         case SNDRV_EMUX_IOCTL_RESET_SAMPLES:
  90                 snd_soundfont_remove_samples(emu->sflist);
  91                 break;
  92         case SNDRV_EMUX_IOCTL_REMOVE_LAST_SAMPLES:
  93                 snd_soundfont_remove_unlocked(emu->sflist);
  94                 break;
  95         case SNDRV_EMUX_IOCTL_MEM_AVAIL:
  96                 if (emu->memhdr) {
  97                         int size = snd_util_mem_avail(emu->memhdr);
  98                         return put_user(size, (unsigned int __user *)arg);
  99                 }
 100                 break;
 101         case SNDRV_EMUX_IOCTL_MISC_MODE:
 102                 return snd_emux_hwdep_misc_mode(emu, (void __user *)arg);
 103         }
 104 
 105         return 0;
 106 }
 107 
 108 
 109 /*
 110  * register hwdep device
 111  */
 112 
 113 int
 114 snd_emux_init_hwdep(struct snd_emux *emu)
 115 {
 116         struct snd_hwdep *hw;
 117         int err;
 118 
 119         if ((err = snd_hwdep_new(emu->card, SNDRV_EMUX_HWDEP_NAME, emu->hwdep_idx, &hw)) < 0)
 120                 return err;
 121         emu->hwdep = hw;
 122         strcpy(hw->name, SNDRV_EMUX_HWDEP_NAME);
 123         hw->iface = SNDRV_HWDEP_IFACE_EMUX_WAVETABLE;
 124         hw->ops.ioctl = snd_emux_hwdep_ioctl;
 125         /* The ioctl parameter types are compatible between 32- and
 126          * 64-bit architectures, so use the same function. */
 127         hw->ops.ioctl_compat = snd_emux_hwdep_ioctl;
 128         hw->exclusive = 1;
 129         hw->private_data = emu;
 130         if ((err = snd_card_register(emu->card)) < 0)
 131                 return err;
 132 
 133         return 0;
 134 }
 135 
 136 
 137 /*
 138  * unregister
 139  */
 140 void
 141 snd_emux_delete_hwdep(struct snd_emux *emu)
 142 {
 143         if (emu->hwdep) {
 144                 snd_device_free(emu->card, emu->hwdep);
 145                 emu->hwdep = NULL;
 146         }
 147 }

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