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