Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 | /*
* Interface for hwdep device
*
* Copyright (C) 2004 Takashi Iwai <tiwai@suse.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <sound/core.h>
#include <sound/hwdep.h>
#include <asm/uaccess.h>
#include "emux_voice.h"
/*
* open the hwdep device
*/
static int
snd_emux_hwdep_open(struct snd_hwdep *hw, struct file *file)
{
return 0;
}
/*
* close the device
*/
static int
snd_emux_hwdep_release(struct snd_hwdep *hw, struct file *file)
{
return 0;
}
#define TMP_CLIENT_ID 0x1001
/*
* load patch
*/
static int
snd_emux_hwdep_load_patch(struct snd_emux *emu, void __user *arg)
{
int err;
struct soundfont_patch_info patch;
if (copy_from_user(&patch, arg, sizeof(patch)))
return -EFAULT;
if (patch.type >= SNDRV_SFNT_LOAD_INFO &&
patch.type <= SNDRV_SFNT_PROBE_DATA) {
err = snd_soundfont_load(emu->sflist, arg, patch.len + sizeof(patch), TMP_CLIENT_ID);
if (err < 0)
return err;
} else {
if (emu->ops.load_fx)
return emu->ops.load_fx(emu, patch.type, patch.optarg, arg, patch.len + sizeof(patch));
else
return -EINVAL;
}
return 0;
}
/*
* set misc mode
*/
static int
snd_emux_hwdep_misc_mode(struct snd_emux *emu, void __user *arg)
{
struct snd_emux_misc_mode info;
int i;
if (copy_from_user(&info, arg, sizeof(info)))
return -EFAULT;
if (info.mode < 0 || info.mode >= EMUX_MD_END)
return -EINVAL;
if (info.port < 0) {
for (i = 0; i < emu->num_ports; i++)
emu->portptrs[i]->ctrls[info.mode] = info.value;
} else {
if (info.port < emu->num_ports)
emu->portptrs[info.port]->ctrls[info.mode] = info.value;
}
return 0;
}
/*
* ioctl
*/
static int
snd_emux_hwdep_ioctl(struct snd_hwdep * hw, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct snd_emux *emu = hw->private_data;
switch (cmd) {
case SNDRV_EMUX_IOCTL_VERSION:
return put_user(SNDRV_EMUX_VERSION, (unsigned int __user *)arg);
case SNDRV_EMUX_IOCTL_LOAD_PATCH:
return snd_emux_hwdep_load_patch(emu, (void __user *)arg);
case SNDRV_EMUX_IOCTL_RESET_SAMPLES:
snd_soundfont_remove_samples(emu->sflist);
break;
case SNDRV_EMUX_IOCTL_REMOVE_LAST_SAMPLES:
snd_soundfont_remove_unlocked(emu->sflist);
break;
case SNDRV_EMUX_IOCTL_MEM_AVAIL:
if (emu->memhdr) {
int size = snd_util_mem_avail(emu->memhdr);
return put_user(size, (unsigned int __user *)arg);
}
break;
case SNDRV_EMUX_IOCTL_MISC_MODE:
return snd_emux_hwdep_misc_mode(emu, (void __user *)arg);
}
return 0;
}
/*
* register hwdep device
*/
int
snd_emux_init_hwdep(struct snd_emux *emu)
{
struct snd_hwdep *hw;
int err;
if ((err = snd_hwdep_new(emu->card, SNDRV_EMUX_HWDEP_NAME, emu->hwdep_idx, &hw)) < 0)
return err;
emu->hwdep = hw;
strcpy(hw->name, SNDRV_EMUX_HWDEP_NAME);
hw->iface = SNDRV_HWDEP_IFACE_EMUX_WAVETABLE;
hw->ops.open = snd_emux_hwdep_open;
hw->ops.release = snd_emux_hwdep_release;
hw->ops.ioctl = snd_emux_hwdep_ioctl;
hw->exclusive = 1;
hw->private_data = emu;
if ((err = snd_card_register(emu->card)) < 0)
return err;
return 0;
}
/*
* unregister
*/
void
snd_emux_delete_hwdep(struct snd_emux *emu)
{
if (emu->hwdep) {
snd_device_free(emu->card, emu->hwdep);
emu->hwdep = NULL;
}
}
|