aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core
diff options
context:
space:
mode:
Diffstat (limited to 'sound/core')
-rw-r--r--sound/core/seq/Makefile8
-rw-r--r--sound/core/seq/instr/Makefile23
-rw-r--r--sound/core/seq/instr/ainstr_fm.c155
-rw-r--r--sound/core/seq/instr/ainstr_gf1.c359
-rw-r--r--sound/core/seq/instr/ainstr_iw.c623
-rw-r--r--sound/core/seq/instr/ainstr_simple.c215
-rw-r--r--sound/core/seq/seq_clientmgr.c3
-rw-r--r--sound/core/seq/seq_instr.c655
-rw-r--r--sound/core/seq/seq_midi_emul.c7
9 files changed, 3 insertions, 2045 deletions
diff --git a/sound/core/seq/Makefile b/sound/core/seq/Makefile
index ceef14afee30..069593717fba 100644
--- a/sound/core/seq/Makefile
+++ b/sound/core/seq/Makefile
@@ -3,7 +3,6 @@
3# Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz> 3# Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
4# 4#
5 5
6obj-$(CONFIG_SND) += instr/
7ifeq ($(CONFIG_SND_SEQUENCER_OSS),y) 6ifeq ($(CONFIG_SND_SEQUENCER_OSS),y)
8 obj-$(CONFIG_SND_SEQUENCER) += oss/ 7 obj-$(CONFIG_SND_SEQUENCER) += oss/
9endif 8endif
@@ -15,7 +14,6 @@ snd-seq-objs := seq.o seq_lock.o seq_clientmgr.o seq_memory.o seq_queue.o \
15snd-seq-midi-objs := seq_midi.o 14snd-seq-midi-objs := seq_midi.o
16snd-seq-midi-emul-objs := seq_midi_emul.o 15snd-seq-midi-emul-objs := seq_midi_emul.o
17snd-seq-midi-event-objs := seq_midi_event.o 16snd-seq-midi-event-objs := seq_midi_event.o
18snd-seq-instr-objs := seq_instr.o
19snd-seq-dummy-objs := seq_dummy.o 17snd-seq-dummy-objs := seq_dummy.o
20snd-seq-virmidi-objs := seq_virmidi.o 18snd-seq-virmidi-objs := seq_virmidi.o
21 19
@@ -36,9 +34,7 @@ obj-$(CONFIG_SND_SEQ_DUMMY) += snd-seq-dummy.o
36# Toplevel Module Dependency 34# Toplevel Module Dependency
37obj-$(CONFIG_SND_VIRMIDI) += snd-seq-virmidi.o snd-seq-midi-event.o 35obj-$(CONFIG_SND_VIRMIDI) += snd-seq-virmidi.o snd-seq-midi-event.o
38obj-$(call sequencer,$(CONFIG_SND_RAWMIDI)) += snd-seq-midi.o snd-seq-midi-event.o 36obj-$(call sequencer,$(CONFIG_SND_RAWMIDI)) += snd-seq-midi.o snd-seq-midi-event.o
39obj-$(call sequencer,$(CONFIG_SND_OPL3_LIB)) += snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o 37obj-$(call sequencer,$(CONFIG_SND_OPL3_LIB)) += snd-seq-midi-event.o snd-seq-midi-emul.o
40obj-$(call sequencer,$(CONFIG_SND_OPL4_LIB)) += snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o 38obj-$(call sequencer,$(CONFIG_SND_OPL4_LIB)) += snd-seq-midi-event.o snd-seq-midi-emul.o
41obj-$(call sequencer,$(CONFIG_SND_GUS_SYNTH)) += snd-seq-midi-emul.o snd-seq-instr.o
42obj-$(call sequencer,$(CONFIG_SND_SBAWE)) += snd-seq-midi-emul.o snd-seq-virmidi.o 39obj-$(call sequencer,$(CONFIG_SND_SBAWE)) += snd-seq-midi-emul.o snd-seq-virmidi.o
43obj-$(call sequencer,$(CONFIG_SND_EMU10K1)) += snd-seq-midi-emul.o snd-seq-virmidi.o 40obj-$(call sequencer,$(CONFIG_SND_EMU10K1)) += snd-seq-midi-emul.o snd-seq-virmidi.o
44obj-$(call sequencer,$(CONFIG_SND_TRIDENT)) += snd-seq-midi-emul.o snd-seq-instr.o
diff --git a/sound/core/seq/instr/Makefile b/sound/core/seq/instr/Makefile
deleted file mode 100644
index 608960364813..000000000000
--- a/sound/core/seq/instr/Makefile
+++ /dev/null
@@ -1,23 +0,0 @@
1#
2# Makefile for ALSA
3# Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
4#
5
6snd-ainstr-fm-objs := ainstr_fm.o
7snd-ainstr-simple-objs := ainstr_simple.o
8snd-ainstr-gf1-objs := ainstr_gf1.o
9snd-ainstr-iw-objs := ainstr_iw.o
10
11#
12# this function returns:
13# "m" - CONFIG_SND_SEQUENCER is m
14# <empty string> - CONFIG_SND_SEQUENCER is undefined
15# otherwise parameter #1 value
16#
17sequencer = $(if $(subst y,,$(CONFIG_SND_SEQUENCER)),$(if $(1),m),$(if $(CONFIG_SND_SEQUENCER),$(1)))
18
19# Toplevel Module Dependency
20obj-$(call sequencer,$(CONFIG_SND_OPL3_LIB)) += snd-ainstr-fm.o
21obj-$(call sequencer,$(CONFIG_SND_OPL4_LIB)) += snd-ainstr-fm.o
22obj-$(call sequencer,$(CONFIG_SND_GUS_SYNTH)) += snd-ainstr-gf1.o snd-ainstr-simple.o snd-ainstr-iw.o
23obj-$(call sequencer,$(CONFIG_SND_TRIDENT)) += snd-ainstr-simple.o
diff --git a/sound/core/seq/instr/ainstr_fm.c b/sound/core/seq/instr/ainstr_fm.c
deleted file mode 100644
index f80fab8f2ed1..000000000000
--- a/sound/core/seq/instr/ainstr_fm.c
+++ /dev/null
@@ -1,155 +0,0 @@
1/*
2 * FM (OPL2/3) Instrument routines
3 * Copyright (c) 2000 Uros Bizjak <uros@kss-loka.si>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 */
20
21#include <sound/driver.h>
22#include <linux/init.h>
23#include <sound/core.h>
24#include <sound/ainstr_fm.h>
25#include <sound/initval.h>
26#include <asm/uaccess.h>
27
28MODULE_AUTHOR("Uros Bizjak <uros@kss-loka.si>");
29MODULE_DESCRIPTION("Advanced Linux Sound Architecture FM Instrument support.");
30MODULE_LICENSE("GPL");
31
32static int snd_seq_fm_put(void *private_data, struct snd_seq_kinstr *instr,
33 char __user *instr_data, long len, int atomic, int cmd)
34{
35 struct fm_instrument *ip;
36 struct fm_xinstrument ix;
37 int idx;
38
39 if (cmd != SNDRV_SEQ_INSTR_PUT_CMD_CREATE)
40 return -EINVAL;
41 /* copy instrument data */
42 if (len < (long)sizeof(ix))
43 return -EINVAL;
44 if (copy_from_user(&ix, instr_data, sizeof(ix)))
45 return -EFAULT;
46 if (ix.stype != FM_STRU_INSTR)
47 return -EINVAL;
48 ip = (struct fm_instrument *)KINSTR_DATA(instr);
49 ip->share_id[0] = le32_to_cpu(ix.share_id[0]);
50 ip->share_id[1] = le32_to_cpu(ix.share_id[1]);
51 ip->share_id[2] = le32_to_cpu(ix.share_id[2]);
52 ip->share_id[3] = le32_to_cpu(ix.share_id[3]);
53 ip->type = ix.type;
54 for (idx = 0; idx < 4; idx++) {
55 ip->op[idx].am_vib = ix.op[idx].am_vib;
56 ip->op[idx].ksl_level = ix.op[idx].ksl_level;
57 ip->op[idx].attack_decay = ix.op[idx].attack_decay;
58 ip->op[idx].sustain_release = ix.op[idx].sustain_release;
59 ip->op[idx].wave_select = ix.op[idx].wave_select;
60 }
61 for (idx = 0; idx < 2; idx++) {
62 ip->feedback_connection[idx] = ix.feedback_connection[idx];
63 }
64 ip->echo_delay = ix.echo_delay;
65 ip->echo_atten = ix.echo_atten;
66 ip->chorus_spread = ix.chorus_spread;
67 ip->trnsps = ix.trnsps;
68 ip->fix_dur = ix.fix_dur;
69 ip->modes = ix.modes;
70 ip->fix_key = ix.fix_key;
71 return 0;
72}
73
74static int snd_seq_fm_get(void *private_data, struct snd_seq_kinstr *instr,
75 char __user *instr_data, long len, int atomic,
76 int cmd)
77{
78 struct fm_instrument *ip;
79 struct fm_xinstrument ix;
80 int idx;
81
82 if (cmd != SNDRV_SEQ_INSTR_GET_CMD_FULL)
83 return -EINVAL;
84 if (len < (long)sizeof(ix))
85 return -ENOMEM;
86 memset(&ix, 0, sizeof(ix));
87 ip = (struct fm_instrument *)KINSTR_DATA(instr);
88 ix.stype = FM_STRU_INSTR;
89 ix.share_id[0] = cpu_to_le32(ip->share_id[0]);
90 ix.share_id[1] = cpu_to_le32(ip->share_id[1]);
91 ix.share_id[2] = cpu_to_le32(ip->share_id[2]);
92 ix.share_id[3] = cpu_to_le32(ip->share_id[3]);
93 ix.type = ip->type;
94 for (idx = 0; idx < 4; idx++) {
95 ix.op[idx].am_vib = ip->op[idx].am_vib;
96 ix.op[idx].ksl_level = ip->op[idx].ksl_level;
97 ix.op[idx].attack_decay = ip->op[idx].attack_decay;
98 ix.op[idx].sustain_release = ip->op[idx].sustain_release;
99 ix.op[idx].wave_select = ip->op[idx].wave_select;
100 }
101 for (idx = 0; idx < 2; idx++) {
102 ix.feedback_connection[idx] = ip->feedback_connection[idx];
103 }
104 if (copy_to_user(instr_data, &ix, sizeof(ix)))
105 return -EFAULT;
106 ix.echo_delay = ip->echo_delay;
107 ix.echo_atten = ip->echo_atten;
108 ix.chorus_spread = ip->chorus_spread;
109 ix.trnsps = ip->trnsps;
110 ix.fix_dur = ip->fix_dur;
111 ix.modes = ip->modes;
112 ix.fix_key = ip->fix_key;
113 return 0;
114}
115
116static int snd_seq_fm_get_size(void *private_data, struct snd_seq_kinstr *instr,
117 long *size)
118{
119 *size = sizeof(struct fm_xinstrument);
120 return 0;
121}
122
123int snd_seq_fm_init(struct snd_seq_kinstr_ops *ops,
124 struct snd_seq_kinstr_ops *next)
125{
126 memset(ops, 0, sizeof(*ops));
127 // ops->private_data = private_data;
128 ops->add_len = sizeof(struct fm_instrument);
129 ops->instr_type = SNDRV_SEQ_INSTR_ID_OPL2_3;
130 ops->put = snd_seq_fm_put;
131 ops->get = snd_seq_fm_get;
132 ops->get_size = snd_seq_fm_get_size;
133 // ops->remove = snd_seq_fm_remove;
134 // ops->notify = snd_seq_fm_notify;
135 ops->next = next;
136 return 0;
137}
138
139/*
140 * Init part
141 */
142
143static int __init alsa_ainstr_fm_init(void)
144{
145 return 0;
146}
147
148static void __exit alsa_ainstr_fm_exit(void)
149{
150}
151
152module_init(alsa_ainstr_fm_init)
153module_exit(alsa_ainstr_fm_exit)
154
155EXPORT_SYMBOL(snd_seq_fm_init);
diff --git a/sound/core/seq/instr/ainstr_gf1.c b/sound/core/seq/instr/ainstr_gf1.c
deleted file mode 100644
index 49400262b1eb..000000000000
--- a/sound/core/seq/instr/ainstr_gf1.c
+++ /dev/null
@@ -1,359 +0,0 @@
1/*
2 * GF1 (GUS) Patch - Instrument routines
3 * Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 */
20
21#include <sound/driver.h>
22#include <linux/init.h>
23#include <linux/slab.h>
24#include <sound/core.h>
25#include <sound/ainstr_gf1.h>
26#include <sound/initval.h>
27#include <asm/uaccess.h>
28
29MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
30MODULE_DESCRIPTION("Advanced Linux Sound Architecture GF1 (GUS) Patch support.");
31MODULE_LICENSE("GPL");
32
33static unsigned int snd_seq_gf1_size(unsigned int size, unsigned int format)
34{
35 unsigned int result = size;
36
37 if (format & GF1_WAVE_16BIT)
38 result <<= 1;
39 if (format & GF1_WAVE_STEREO)
40 result <<= 1;
41 return format;
42}
43
44static int snd_seq_gf1_copy_wave_from_stream(struct snd_gf1_ops *ops,
45 struct gf1_instrument *ip,
46 char __user **data,
47 long *len,
48 int atomic)
49{
50 struct gf1_wave *wp, *prev;
51 struct gf1_xwave xp;
52 int err;
53 gfp_t gfp_mask;
54 unsigned int real_size;
55
56 gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL;
57 if (*len < (long)sizeof(xp))
58 return -EINVAL;
59 if (copy_from_user(&xp, *data, sizeof(xp)))
60 return -EFAULT;
61 *data += sizeof(xp);
62 *len -= sizeof(xp);
63 wp = kzalloc(sizeof(*wp), gfp_mask);
64 if (wp == NULL)
65 return -ENOMEM;
66 wp->share_id[0] = le32_to_cpu(xp.share_id[0]);
67 wp->share_id[1] = le32_to_cpu(xp.share_id[1]);
68 wp->share_id[2] = le32_to_cpu(xp.share_id[2]);
69 wp->share_id[3] = le32_to_cpu(xp.share_id[3]);
70 wp->format = le32_to_cpu(xp.format);
71 wp->size = le32_to_cpu(xp.size);
72 wp->start = le32_to_cpu(xp.start);
73 wp->loop_start = le32_to_cpu(xp.loop_start);
74 wp->loop_end = le32_to_cpu(xp.loop_end);
75 wp->loop_repeat = le16_to_cpu(xp.loop_repeat);
76 wp->flags = xp.flags;
77 wp->sample_rate = le32_to_cpu(xp.sample_rate);
78 wp->low_frequency = le32_to_cpu(xp.low_frequency);
79 wp->high_frequency = le32_to_cpu(xp.high_frequency);
80 wp->root_frequency = le32_to_cpu(xp.root_frequency);
81 wp->tune = le16_to_cpu(xp.tune);
82 wp->balance = xp.balance;
83 memcpy(wp->envelope_rate, xp.envelope_rate, 6);
84 memcpy(wp->envelope_offset, xp.envelope_offset, 6);
85 wp->tremolo_sweep = xp.tremolo_sweep;
86 wp->tremolo_rate = xp.tremolo_rate;
87 wp->tremolo_depth = xp.tremolo_depth;
88 wp->vibrato_sweep = xp.vibrato_sweep;
89 wp->vibrato_rate = xp.vibrato_rate;
90 wp->vibrato_depth = xp.vibrato_depth;
91 wp->scale_frequency = le16_to_cpu(xp.scale_frequency);
92 wp->scale_factor = le16_to_cpu(xp.scale_factor);
93 real_size = snd_seq_gf1_size(wp->size, wp->format);
94 if ((long)real_size > *len) {
95 kfree(wp);
96 return -ENOMEM;
97 }
98 if (ops->put_sample) {
99 err = ops->put_sample(ops->private_data, wp,
100 *data, real_size, atomic);
101 if (err < 0) {
102 kfree(wp);
103 return err;
104 }
105 }
106 *data += real_size;
107 *len -= real_size;
108 prev = ip->wave;
109 if (prev) {
110 while (prev->next) prev = prev->next;
111 prev->next = wp;
112 } else {
113 ip->wave = wp;
114 }
115 return 0;
116}
117
118static void snd_seq_gf1_wave_free(struct snd_gf1_ops *ops,
119 struct gf1_wave *wave,
120 int atomic)
121{
122 if (ops->remove_sample)
123 ops->remove_sample(ops->private_data, wave, atomic);
124 kfree(wave);
125}
126
127static void snd_seq_gf1_instr_free(struct snd_gf1_ops *ops,
128 struct gf1_instrument *ip,
129 int atomic)
130{
131 struct gf1_wave *wave;
132
133 while ((wave = ip->wave) != NULL) {
134 ip->wave = wave->next;
135 snd_seq_gf1_wave_free(ops, wave, atomic);
136 }
137}
138
139static int snd_seq_gf1_put(void *private_data, struct snd_seq_kinstr *instr,
140 char __user *instr_data, long len, int atomic,
141 int cmd)
142{
143 struct snd_gf1_ops *ops = private_data;
144 struct gf1_instrument *ip;
145 struct gf1_xinstrument ix;
146 int err;
147 gfp_t gfp_mask;
148
149 if (cmd != SNDRV_SEQ_INSTR_PUT_CMD_CREATE)
150 return -EINVAL;
151 gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL;
152 /* copy instrument data */
153 if (len < (long)sizeof(ix))
154 return -EINVAL;
155 if (copy_from_user(&ix, instr_data, sizeof(ix)))
156 return -EFAULT;
157 if (ix.stype != GF1_STRU_INSTR)
158 return -EINVAL;
159 instr_data += sizeof(ix);
160 len -= sizeof(ix);
161 ip = (struct gf1_instrument *)KINSTR_DATA(instr);
162 ip->exclusion = le16_to_cpu(ix.exclusion);
163 ip->exclusion_group = le16_to_cpu(ix.exclusion_group);
164 ip->effect1 = ix.effect1;
165 ip->effect1_depth = ix.effect1_depth;
166 ip->effect2 = ix.effect2;
167 ip->effect2_depth = ix.effect2_depth;
168 /* copy layers */
169 while (len > (long)sizeof(__u32)) {
170 __u32 stype;
171
172 if (copy_from_user(&stype, instr_data, sizeof(stype)))
173 return -EFAULT;
174 if (stype != GF1_STRU_WAVE) {
175 snd_seq_gf1_instr_free(ops, ip, atomic);
176 return -EINVAL;
177 }
178 err = snd_seq_gf1_copy_wave_from_stream(ops,
179 ip,
180 &instr_data,
181 &len,
182 atomic);
183 if (err < 0) {
184 snd_seq_gf1_instr_free(ops, ip, atomic);
185 return err;
186 }
187 }
188 return 0;
189}
190
191static int snd_seq_gf1_copy_wave_to_stream(struct snd_gf1_ops *ops,
192 struct gf1_instrument *ip,
193 char __user **data,
194 long *len,
195 int atomic)
196{
197 struct gf1_wave *wp;
198 struct gf1_xwave xp;
199 int err;
200 unsigned int real_size;
201
202 for (wp = ip->wave; wp; wp = wp->next) {
203 if (*len < (long)sizeof(xp))
204 return -ENOMEM;
205 memset(&xp, 0, sizeof(xp));
206 xp.stype = GF1_STRU_WAVE;
207 xp.share_id[0] = cpu_to_le32(wp->share_id[0]);
208 xp.share_id[1] = cpu_to_le32(wp->share_id[1]);
209 xp.share_id[2] = cpu_to_le32(wp->share_id[2]);
210 xp.share_id[3] = cpu_to_le32(wp->share_id[3]);
211 xp.format = cpu_to_le32(wp->format);
212 xp.size = cpu_to_le32(wp->size);
213 xp.start = cpu_to_le32(wp->start);
214 xp.loop_start = cpu_to_le32(wp->loop_start);
215 xp.loop_end = cpu_to_le32(wp->loop_end);
216 xp.loop_repeat = cpu_to_le32(wp->loop_repeat);
217 xp.flags = wp->flags;
218 xp.sample_rate = cpu_to_le32(wp->sample_rate);
219 xp.low_frequency = cpu_to_le32(wp->low_frequency);
220 xp.high_frequency = cpu_to_le32(wp->high_frequency);
221 xp.root_frequency = cpu_to_le32(wp->root_frequency);
222 xp.tune = cpu_to_le16(wp->tune);
223 xp.balance = wp->balance;
224 memcpy(xp.envelope_rate, wp->envelope_rate, 6);
225 memcpy(xp.envelope_offset, wp->envelope_offset, 6);
226 xp.tremolo_sweep = wp->tremolo_sweep;
227 xp.tremolo_rate = wp->tremolo_rate;
228 xp.tremolo_depth = wp->tremolo_depth;
229 xp.vibrato_sweep = wp->vibrato_sweep;
230 xp.vibrato_rate = wp->vibrato_rate;
231 xp.vibrato_depth = wp->vibrato_depth;
232 xp.scale_frequency = cpu_to_le16(wp->scale_frequency);
233 xp.scale_factor = cpu_to_le16(wp->scale_factor);
234 if (copy_to_user(*data, &xp, sizeof(xp)))
235 return -EFAULT;
236 *data += sizeof(xp);
237 *len -= sizeof(xp);
238 real_size = snd_seq_gf1_size(wp->size, wp->format);
239 if (*len < (long)real_size)
240 return -ENOMEM;
241 if (ops->get_sample) {
242 err = ops->get_sample(ops->private_data, wp,
243 *data, real_size, atomic);
244 if (err < 0)
245 return err;
246 }
247 *data += wp->size;
248 *len -= wp->size;
249 }
250 return 0;
251}
252
253static int snd_seq_gf1_get(void *private_data, struct snd_seq_kinstr *instr,
254 char __user *instr_data, long len, int atomic,
255 int cmd)
256{
257 struct snd_gf1_ops *ops = private_data;
258 struct gf1_instrument *ip;
259 struct gf1_xinstrument ix;
260
261 if (cmd != SNDRV_SEQ_INSTR_GET_CMD_FULL)
262 return -EINVAL;
263 if (len < (long)sizeof(ix))
264 return -ENOMEM;
265 memset(&ix, 0, sizeof(ix));
266 ip = (struct gf1_instrument *)KINSTR_DATA(instr);
267 ix.stype = GF1_STRU_INSTR;
268 ix.exclusion = cpu_to_le16(ip->exclusion);
269 ix.exclusion_group = cpu_to_le16(ip->exclusion_group);
270 ix.effect1 = cpu_to_le16(ip->effect1);
271 ix.effect1_depth = cpu_to_le16(ip->effect1_depth);
272 ix.effect2 = ip->effect2;
273 ix.effect2_depth = ip->effect2_depth;
274 if (copy_to_user(instr_data, &ix, sizeof(ix)))
275 return -EFAULT;
276 instr_data += sizeof(ix);
277 len -= sizeof(ix);
278 return snd_seq_gf1_copy_wave_to_stream(ops,
279 ip,
280 &instr_data,
281 &len,
282 atomic);
283}
284
285static int snd_seq_gf1_get_size(void *private_data, struct snd_seq_kinstr *instr,
286 long *size)
287{
288 long result;
289 struct gf1_instrument *ip;
290 struct gf1_wave *wp;
291
292 *size = 0;
293 ip = (struct gf1_instrument *)KINSTR_DATA(instr);
294 result = sizeof(struct gf1_xinstrument);
295 for (wp = ip->wave; wp; wp = wp->next) {
296 result += sizeof(struct gf1_xwave);
297 result += wp->size;
298 }
299 *size = result;
300 return 0;
301}
302
303static int snd_seq_gf1_remove(void *private_data,
304 struct snd_seq_kinstr *instr,
305 int atomic)
306{
307 struct snd_gf1_ops *ops = private_data;
308 struct gf1_instrument *ip;
309
310 ip = (struct gf1_instrument *)KINSTR_DATA(instr);
311 snd_seq_gf1_instr_free(ops, ip, atomic);
312 return 0;
313}
314
315static void snd_seq_gf1_notify(void *private_data,
316 struct snd_seq_kinstr *instr,
317 int what)
318{
319 struct snd_gf1_ops *ops = private_data;
320
321 if (ops->notify)
322 ops->notify(ops->private_data, instr, what);
323}
324
325int snd_seq_gf1_init(struct snd_gf1_ops *ops,
326 void *private_data,
327 struct snd_seq_kinstr_ops *next)
328{
329 memset(ops, 0, sizeof(*ops));
330 ops->private_data = private_data;
331 ops->kops.private_data = ops;
332 ops->kops.add_len = sizeof(struct gf1_instrument);
333 ops->kops.instr_type = SNDRV_SEQ_INSTR_ID_GUS_PATCH;
334 ops->kops.put = snd_seq_gf1_put;
335 ops->kops.get = snd_seq_gf1_get;
336 ops->kops.get_size = snd_seq_gf1_get_size;
337 ops->kops.remove = snd_seq_gf1_remove;
338 ops->kops.notify = snd_seq_gf1_notify;
339 ops->kops.next = next;
340 return 0;
341}
342
343/*
344 * Init part
345 */
346
347static int __init alsa_ainstr_gf1_init(void)
348{
349 return 0;
350}
351
352static void __exit alsa_ainstr_gf1_exit(void)
353{
354}
355
356module_init(alsa_ainstr_gf1_init)
357module_exit(alsa_ainstr_gf1_exit)
358
359EXPORT_SYMBOL(snd_seq_gf1_init);
diff --git a/sound/core/seq/instr/ainstr_iw.c b/sound/core/seq/instr/ainstr_iw.c
deleted file mode 100644
index 6c40eb73fa9f..000000000000
--- a/sound/core/seq/instr/ainstr_iw.c
+++ /dev/null
@@ -1,623 +0,0 @@
1/*
2 * IWFFFF - AMD InterWave (tm) - Instrument routines
3 * Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 */
20
21#include <sound/driver.h>
22#include <linux/init.h>
23#include <linux/slab.h>
24#include <sound/core.h>
25#include <sound/ainstr_iw.h>
26#include <sound/initval.h>
27#include <asm/uaccess.h>
28
29MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
30MODULE_DESCRIPTION("Advanced Linux Sound Architecture IWFFFF support.");
31MODULE_LICENSE("GPL");
32
33static unsigned int snd_seq_iwffff_size(unsigned int size, unsigned int format)
34{
35 unsigned int result = size;
36
37 if (format & IWFFFF_WAVE_16BIT)
38 result <<= 1;
39 if (format & IWFFFF_WAVE_STEREO)
40 result <<= 1;
41 return result;
42}
43
44static void snd_seq_iwffff_copy_lfo_from_stream(struct iwffff_lfo *fp,
45 struct iwffff_xlfo *fx)
46{
47 fp->freq = le16_to_cpu(fx->freq);
48 fp->depth = le16_to_cpu(fx->depth);
49 fp->sweep = le16_to_cpu(fx->sweep);
50 fp->shape = fx->shape;
51 fp->delay = fx->delay;
52}
53
54static int snd_seq_iwffff_copy_env_from_stream(__u32 req_stype,
55 struct iwffff_layer *lp,
56 struct iwffff_env *ep,
57 struct iwffff_xenv *ex,
58 char __user **data,
59 long *len,
60 gfp_t gfp_mask)
61{
62 __u32 stype;
63 struct iwffff_env_record *rp, *rp_last;
64 struct iwffff_xenv_record rx;
65 struct iwffff_env_point *pp;
66 struct iwffff_xenv_point px;
67 int points_size, idx;
68
69 ep->flags = ex->flags;
70 ep->mode = ex->mode;
71 ep->index = ex->index;
72 rp_last = NULL;
73 while (1) {
74 if (*len < (long)sizeof(__u32))
75 return -EINVAL;
76 if (copy_from_user(&stype, *data, sizeof(stype)))
77 return -EFAULT;
78 if (stype == IWFFFF_STRU_WAVE)
79 return 0;
80 if (req_stype != stype) {
81 if (stype == IWFFFF_STRU_ENV_RECP ||
82 stype == IWFFFF_STRU_ENV_RECV)
83 return 0;
84 }
85 if (*len < (long)sizeof(rx))
86 return -EINVAL;
87 if (copy_from_user(&rx, *data, sizeof(rx)))
88 return -EFAULT;
89 *data += sizeof(rx);
90 *len -= sizeof(rx);
91 points_size = (le16_to_cpu(rx.nattack) + le16_to_cpu(rx.nrelease)) * 2 * sizeof(__u16);
92 if (points_size > *len)
93 return -EINVAL;
94 rp = kzalloc(sizeof(*rp) + points_size, gfp_mask);
95 if (rp == NULL)
96 return -ENOMEM;
97 rp->nattack = le16_to_cpu(rx.nattack);
98 rp->nrelease = le16_to_cpu(rx.nrelease);
99 rp->sustain_offset = le16_to_cpu(rx.sustain_offset);
100 rp->sustain_rate = le16_to_cpu(rx.sustain_rate);
101 rp->release_rate = le16_to_cpu(rx.release_rate);
102 rp->hirange = rx.hirange;
103 pp = (struct iwffff_env_point *)(rp + 1);
104 for (idx = 0; idx < rp->nattack + rp->nrelease; idx++) {
105 if (copy_from_user(&px, *data, sizeof(px)))
106 return -EFAULT;
107 *data += sizeof(px);
108 *len -= sizeof(px);
109 pp->offset = le16_to_cpu(px.offset);
110 pp->rate = le16_to_cpu(px.rate);
111 }
112 if (ep->record == NULL) {
113 ep->record = rp;
114 } else {
115 rp_last = rp;
116 }
117 rp_last = rp;
118 }
119 return 0;
120}
121
122static int snd_seq_iwffff_copy_wave_from_stream(struct snd_iwffff_ops *ops,
123 struct iwffff_layer *lp,
124 char __user **data,
125 long *len,
126 int atomic)
127{
128 struct iwffff_wave *wp, *prev;
129 struct iwffff_xwave xp;
130 int err;
131 gfp_t gfp_mask;
132 unsigned int real_size;
133
134 gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL;
135 if (*len < (long)sizeof(xp))
136 return -EINVAL;
137 if (copy_from_user(&xp, *data, sizeof(xp)))
138 return -EFAULT;
139 *data += sizeof(xp);
140 *len -= sizeof(xp);
141 wp = kzalloc(sizeof(*wp), gfp_mask);
142 if (wp == NULL)
143 return -ENOMEM;
144 wp->share_id[0] = le32_to_cpu(xp.share_id[0]);
145 wp->share_id[1] = le32_to_cpu(xp.share_id[1]);
146 wp->share_id[2] = le32_to_cpu(xp.share_id[2]);
147 wp->share_id[3] = le32_to_cpu(xp.share_id[3]);
148 wp->format = le32_to_cpu(xp.format);
149 wp->address.memory = le32_to_cpu(xp.offset);
150 wp->size = le32_to_cpu(xp.size);
151 wp->start = le32_to_cpu(xp.start);
152 wp->loop_start = le32_to_cpu(xp.loop_start);
153 wp->loop_end = le32_to_cpu(xp.loop_end);
154 wp->loop_repeat = le16_to_cpu(xp.loop_repeat);
155 wp->sample_ratio = le32_to_cpu(xp.sample_ratio);
156 wp->attenuation = xp.attenuation;
157 wp->low_note = xp.low_note;
158 wp->high_note = xp.high_note;
159 real_size = snd_seq_iwffff_size(wp->size, wp->format);
160 if (!(wp->format & IWFFFF_WAVE_ROM)) {
161 if ((long)real_size > *len) {
162 kfree(wp);
163 return -ENOMEM;
164 }
165 }
166 if (ops->put_sample) {
167 err = ops->put_sample(ops->private_data, wp,
168 *data, real_size, atomic);
169 if (err < 0) {
170 kfree(wp);
171 return err;
172 }
173 }
174 if (!(wp->format & IWFFFF_WAVE_ROM)) {
175 *data += real_size;
176 *len -= real_size;
177 }
178 prev = lp->wave;
179 if (prev) {
180 while (prev->next) prev = prev->next;
181 prev->next = wp;
182 } else {
183 lp->wave = wp;
184 }
185 return 0;
186}
187
188static void snd_seq_iwffff_env_free(struct snd_iwffff_ops *ops,
189 struct iwffff_env *env,
190 int atomic)
191{
192 struct iwffff_env_record *rec;
193
194 while ((rec = env->record) != NULL) {
195 env->record = rec->next;
196 kfree(rec);
197 }
198}
199
200static void snd_seq_iwffff_wave_free(struct snd_iwffff_ops *ops,
201 struct iwffff_wave *wave,
202 int atomic)
203{
204 if (ops->remove_sample)
205 ops->remove_sample(ops->private_data, wave, atomic);
206 kfree(wave);
207}
208
209static void snd_seq_iwffff_instr_free(struct snd_iwffff_ops *ops,
210 struct iwffff_instrument *ip,
211 int atomic)
212{
213 struct iwffff_layer *layer;
214 struct iwffff_wave *wave;
215
216 while ((layer = ip->layer) != NULL) {
217 ip->layer = layer->next;
218 snd_seq_iwffff_env_free(ops, &layer->penv, atomic);
219 snd_seq_iwffff_env_free(ops, &layer->venv, atomic);
220 while ((wave = layer->wave) != NULL) {
221 layer->wave = wave->next;
222 snd_seq_iwffff_wave_free(ops, wave, atomic);
223 }
224 kfree(layer);
225 }
226}
227
228static int snd_seq_iwffff_put(void *private_data, struct snd_seq_kinstr *instr,
229 char __user *instr_data, long len, int atomic,
230 int cmd)
231{
232 struct snd_iwffff_ops *ops = private_data;
233 struct iwffff_instrument *ip;
234 struct iwffff_xinstrument ix;
235 struct iwffff_layer *lp, *prev_lp;
236 struct iwffff_xlayer lx;
237 int err;
238 gfp_t gfp_mask;
239
240 if (cmd != SNDRV_SEQ_INSTR_PUT_CMD_CREATE)
241 return -EINVAL;
242 gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL;
243 /* copy instrument data */
244 if (len < (long)sizeof(ix))
245 return -EINVAL;
246 if (copy_from_user(&ix, instr_data, sizeof(ix)))
247 return -EFAULT;
248 if (ix.stype != IWFFFF_STRU_INSTR)
249 return -EINVAL;
250 instr_data += sizeof(ix);
251 len -= sizeof(ix);
252 ip = (struct iwffff_instrument *)KINSTR_DATA(instr);
253 ip->exclusion = le16_to_cpu(ix.exclusion);
254 ip->layer_type = le16_to_cpu(ix.layer_type);
255 ip->exclusion_group = le16_to_cpu(ix.exclusion_group);
256 ip->effect1 = ix.effect1;
257 ip->effect1_depth = ix.effect1_depth;
258 ip->effect2 = ix.effect2;
259 ip->effect2_depth = ix.effect2_depth;
260 /* copy layers */
261 prev_lp = NULL;
262 while (len > 0) {
263 if (len < (long)sizeof(struct iwffff_xlayer)) {
264 snd_seq_iwffff_instr_free(ops, ip, atomic);
265 return -EINVAL;
266 }
267 if (copy_from_user(&lx, instr_data, sizeof(lx)))
268 return -EFAULT;
269 instr_data += sizeof(lx);
270 len -= sizeof(lx);
271 if (lx.stype != IWFFFF_STRU_LAYER) {
272 snd_seq_iwffff_instr_free(ops, ip, atomic);
273 return -EINVAL;
274 }
275 lp = kzalloc(sizeof(*lp), gfp_mask);
276 if (lp == NULL) {
277 snd_seq_iwffff_instr_free(ops, ip, atomic);
278 return -ENOMEM;
279 }
280 if (prev_lp) {
281 prev_lp->next = lp;
282 } else {
283 ip->layer = lp;
284 }
285 prev_lp = lp;
286 lp->flags = lx.flags;
287 lp->velocity_mode = lx.velocity_mode;
288 lp->layer_event = lx.layer_event;
289 lp->low_range = lx.low_range;
290 lp->high_range = lx.high_range;
291 lp->pan = lx.pan;
292 lp->pan_freq_scale = lx.pan_freq_scale;
293 lp->attenuation = lx.attenuation;
294 snd_seq_iwffff_copy_lfo_from_stream(&lp->tremolo, &lx.tremolo);
295 snd_seq_iwffff_copy_lfo_from_stream(&lp->vibrato, &lx.vibrato);
296 lp->freq_scale = le16_to_cpu(lx.freq_scale);
297 lp->freq_center = lx.freq_center;
298 err = snd_seq_iwffff_copy_env_from_stream(IWFFFF_STRU_ENV_RECP,
299 lp,
300 &lp->penv, &lx.penv,
301 &instr_data, &len,
302 gfp_mask);
303 if (err < 0) {
304 snd_seq_iwffff_instr_free(ops, ip, atomic);
305 return err;
306 }
307 err = snd_seq_iwffff_copy_env_from_stream(IWFFFF_STRU_ENV_RECV,
308 lp,
309 &lp->venv, &lx.venv,
310 &instr_data, &len,
311 gfp_mask);
312 if (err < 0) {
313 snd_seq_iwffff_instr_free(ops, ip, atomic);
314 return err;
315 }
316 while (len > (long)sizeof(__u32)) {
317 __u32 stype;
318
319 if (copy_from_user(&stype, instr_data, sizeof(stype)))
320 return -EFAULT;
321 if (stype != IWFFFF_STRU_WAVE)
322 break;
323 err = snd_seq_iwffff_copy_wave_from_stream(ops,
324 lp,
325 &instr_data,
326 &len,
327 atomic);
328 if (err < 0) {
329 snd_seq_iwffff_instr_free(ops, ip, atomic);
330 return err;
331 }
332 }
333 }
334 return 0;
335}
336
337static void snd_seq_iwffff_copy_lfo_to_stream(struct iwffff_xlfo *fx,
338 struct iwffff_lfo *fp)
339{
340 fx->freq = cpu_to_le16(fp->freq);
341 fx->depth = cpu_to_le16(fp->depth);
342 fx->sweep = cpu_to_le16(fp->sweep);
343 fp->shape = fx->shape;
344 fp->delay = fx->delay;
345}
346
347static int snd_seq_iwffff_copy_env_to_stream(__u32 req_stype,
348 struct iwffff_layer *lp,
349 struct iwffff_xenv *ex,
350 struct iwffff_env *ep,
351 char __user **data,
352 long *len)
353{
354 struct iwffff_env_record *rp;
355 struct iwffff_xenv_record rx;
356 struct iwffff_env_point *pp;
357 struct iwffff_xenv_point px;
358 int points_size, idx;
359
360 ex->flags = ep->flags;
361 ex->mode = ep->mode;
362 ex->index = ep->index;
363 for (rp = ep->record; rp; rp = rp->next) {
364 if (*len < (long)sizeof(rx))
365 return -ENOMEM;
366 memset(&rx, 0, sizeof(rx));
367 rx.stype = req_stype;
368 rx.nattack = cpu_to_le16(rp->nattack);
369 rx.nrelease = cpu_to_le16(rp->nrelease);
370 rx.sustain_offset = cpu_to_le16(rp->sustain_offset);
371 rx.sustain_rate = cpu_to_le16(rp->sustain_rate);
372 rx.release_rate = cpu_to_le16(rp->release_rate);
373 rx.hirange = cpu_to_le16(rp->hirange);
374 if (copy_to_user(*data, &rx, sizeof(rx)))
375 return -EFAULT;
376 *data += sizeof(rx);
377 *len -= sizeof(rx);
378 points_size = (rp->nattack + rp->nrelease) * 2 * sizeof(__u16);
379 if (*len < points_size)
380 return -ENOMEM;
381 pp = (struct iwffff_env_point *)(rp + 1);
382 for (idx = 0; idx < rp->nattack + rp->nrelease; idx++) {
383 px.offset = cpu_to_le16(pp->offset);
384 px.rate = cpu_to_le16(pp->rate);
385 if (copy_to_user(*data, &px, sizeof(px)))
386 return -EFAULT;
387 *data += sizeof(px);
388 *len -= sizeof(px);
389 }
390 }
391 return 0;
392}
393
394static int snd_seq_iwffff_copy_wave_to_stream(struct snd_iwffff_ops *ops,
395 struct iwffff_layer *lp,
396 char __user **data,
397 long *len,
398 int atomic)
399{
400 struct iwffff_wave *wp;
401 struct iwffff_xwave xp;
402 int err;
403 unsigned int real_size;
404
405 for (wp = lp->wave; wp; wp = wp->next) {
406 if (*len < (long)sizeof(xp))
407 return -ENOMEM;
408 memset(&xp, 0, sizeof(xp));
409 xp.stype = IWFFFF_STRU_WAVE;
410 xp.share_id[0] = cpu_to_le32(wp->share_id[0]);
411 xp.share_id[1] = cpu_to_le32(wp->share_id[1]);
412 xp.share_id[2] = cpu_to_le32(wp->share_id[2]);
413 xp.share_id[3] = cpu_to_le32(wp->share_id[3]);
414 xp.format = cpu_to_le32(wp->format);
415 if (wp->format & IWFFFF_WAVE_ROM)
416 xp.offset = cpu_to_le32(wp->address.memory);
417 xp.size = cpu_to_le32(wp->size);
418 xp.start = cpu_to_le32(wp->start);
419 xp.loop_start = cpu_to_le32(wp->loop_start);
420 xp.loop_end = cpu_to_le32(wp->loop_end);
421 xp.loop_repeat = cpu_to_le32(wp->loop_repeat);
422 xp.sample_ratio = cpu_to_le32(wp->sample_ratio);
423 xp.attenuation = wp->attenuation;
424 xp.low_note = wp->low_note;
425 xp.high_note = wp->high_note;
426 if (copy_to_user(*data, &xp, sizeof(xp)))
427 return -EFAULT;
428 *data += sizeof(xp);
429 *len -= sizeof(xp);
430 real_size = snd_seq_iwffff_size(wp->size, wp->format);
431 if (!(wp->format & IWFFFF_WAVE_ROM)) {
432 if (*len < (long)real_size)
433 return -ENOMEM;
434 }
435 if (ops->get_sample) {
436 err = ops->get_sample(ops->private_data, wp,
437 *data, real_size, atomic);
438 if (err < 0)
439 return err;
440 }
441 if (!(wp->format & IWFFFF_WAVE_ROM)) {
442 *data += real_size;
443 *len -= real_size;
444 }
445 }
446 return 0;
447}
448
449static int snd_seq_iwffff_get(void *private_data, struct snd_seq_kinstr *instr,
450 char __user *instr_data, long len, int atomic, int cmd)
451{
452 struct snd_iwffff_ops *ops = private_data;
453 struct iwffff_instrument *ip;
454 struct iwffff_xinstrument ix;
455 struct iwffff_layer *lp;
456 struct iwffff_xlayer lx;
457 char __user *layer_instr_data;
458 int err;
459
460 if (cmd != SNDRV_SEQ_INSTR_GET_CMD_FULL)
461 return -EINVAL;
462 if (len < (long)sizeof(ix))
463 return -ENOMEM;
464 memset(&ix, 0, sizeof(ix));
465 ip = (struct iwffff_instrument *)KINSTR_DATA(instr);
466 ix.stype = IWFFFF_STRU_INSTR;
467 ix.exclusion = cpu_to_le16(ip->exclusion);
468 ix.layer_type = cpu_to_le16(ip->layer_type);
469 ix.exclusion_group = cpu_to_le16(ip->exclusion_group);
470 ix.effect1 = cpu_to_le16(ip->effect1);
471 ix.effect1_depth = cpu_to_le16(ip->effect1_depth);
472 ix.effect2 = ip->effect2;
473 ix.effect2_depth = ip->effect2_depth;
474 if (copy_to_user(instr_data, &ix, sizeof(ix)))
475 return -EFAULT;
476 instr_data += sizeof(ix);
477 len -= sizeof(ix);
478 for (lp = ip->layer; lp; lp = lp->next) {
479 if (len < (long)sizeof(lx))
480 return -ENOMEM;
481 memset(&lx, 0, sizeof(lx));
482 lx.stype = IWFFFF_STRU_LAYER;
483 lx.flags = lp->flags;
484 lx.velocity_mode = lp->velocity_mode;
485 lx.layer_event = lp->layer_event;
486 lx.low_range = lp->low_range;
487 lx.high_range = lp->high_range;
488 lx.pan = lp->pan;
489 lx.pan_freq_scale = lp->pan_freq_scale;
490 lx.attenuation = lp->attenuation;
491 snd_seq_iwffff_copy_lfo_to_stream(&lx.tremolo, &lp->tremolo);
492 snd_seq_iwffff_copy_lfo_to_stream(&lx.vibrato, &lp->vibrato);
493 layer_instr_data = instr_data;
494 instr_data += sizeof(lx);
495 len -= sizeof(lx);
496 err = snd_seq_iwffff_copy_env_to_stream(IWFFFF_STRU_ENV_RECP,
497 lp,
498 &lx.penv, &lp->penv,
499 &instr_data, &len);
500 if (err < 0)
501 return err;
502 err = snd_seq_iwffff_copy_env_to_stream(IWFFFF_STRU_ENV_RECV,
503 lp,
504 &lx.venv, &lp->venv,
505 &instr_data, &len);
506 if (err < 0)
507 return err;
508 /* layer structure updating is now finished */
509 if (copy_to_user(layer_instr_data, &lx, sizeof(lx)))
510 return -EFAULT;
511 err = snd_seq_iwffff_copy_wave_to_stream(ops,
512 lp,
513 &instr_data,
514 &len,
515 atomic);
516 if (err < 0)
517 return err;
518 }
519 return 0;
520}
521
522static long snd_seq_iwffff_env_size_in_stream(struct iwffff_env *ep)
523{
524 long result = 0;
525 struct iwffff_env_record *rp;
526
527 for (rp = ep->record; rp; rp = rp->next) {
528 result += sizeof(struct iwffff_xenv_record);
529 result += (rp->nattack + rp->nrelease) * 2 * sizeof(__u16);
530 }
531 return 0;
532}
533
534static long snd_seq_iwffff_wave_size_in_stream(struct iwffff_layer *lp)
535{
536 long result = 0;
537 struct iwffff_wave *wp;
538
539 for (wp = lp->wave; wp; wp = wp->next) {
540 result += sizeof(struct iwffff_xwave);
541 if (!(wp->format & IWFFFF_WAVE_ROM))
542 result += wp->size;
543 }
544 return result;
545}
546
547static int snd_seq_iwffff_get_size(void *private_data, struct snd_seq_kinstr *instr,
548 long *size)
549{
550 long result;
551 struct iwffff_instrument *ip;
552 struct iwffff_layer *lp;
553
554 *size = 0;
555 ip = (struct iwffff_instrument *)KINSTR_DATA(instr);
556 result = sizeof(struct iwffff_xinstrument);
557 for (lp = ip->layer; lp; lp = lp->next) {
558 result += sizeof(struct iwffff_xlayer);
559 result += snd_seq_iwffff_env_size_in_stream(&lp->penv);
560 result += snd_seq_iwffff_env_size_in_stream(&lp->venv);
561 result += snd_seq_iwffff_wave_size_in_stream(lp);
562 }
563 *size = result;
564 return 0;
565}
566
567static int snd_seq_iwffff_remove(void *private_data,
568 struct snd_seq_kinstr *instr,
569 int atomic)
570{
571 struct snd_iwffff_ops *ops = private_data;
572 struct iwffff_instrument *ip;
573
574 ip = (struct iwffff_instrument *)KINSTR_DATA(instr);
575 snd_seq_iwffff_instr_free(ops, ip, atomic);
576 return 0;
577}
578
579static void snd_seq_iwffff_notify(void *private_data,
580 struct snd_seq_kinstr *instr,
581 int what)
582{
583 struct snd_iwffff_ops *ops = private_data;
584
585 if (ops->notify)
586 ops->notify(ops->private_data, instr, what);
587}
588
589int snd_seq_iwffff_init(struct snd_iwffff_ops *ops,
590 void *private_data,
591 struct snd_seq_kinstr_ops *next)
592{
593 memset(ops, 0, sizeof(*ops));
594 ops->private_data = private_data;
595 ops->kops.private_data = ops;
596 ops->kops.add_len = sizeof(struct iwffff_instrument);
597 ops->kops.instr_type = SNDRV_SEQ_INSTR_ID_INTERWAVE;
598 ops->kops.put = snd_seq_iwffff_put;
599 ops->kops.get = snd_seq_iwffff_get;
600 ops->kops.get_size = snd_seq_iwffff_get_size;
601 ops->kops.remove = snd_seq_iwffff_remove;
602 ops->kops.notify = snd_seq_iwffff_notify;
603 ops->kops.next = next;
604 return 0;
605}
606
607/*
608 * Init part
609 */
610
611static int __init alsa_ainstr_iw_init(void)
612{
613 return 0;
614}
615
616static void __exit alsa_ainstr_iw_exit(void)
617{
618}
619
620module_init(alsa_ainstr_iw_init)
621module_exit(alsa_ainstr_iw_exit)
622
623EXPORT_SYMBOL(snd_seq_iwffff_init);
diff --git a/sound/core/seq/instr/ainstr_simple.c b/sound/core/seq/instr/ainstr_simple.c
deleted file mode 100644
index 78f68bee24fe..000000000000
--- a/sound/core/seq/instr/ainstr_simple.c
+++ /dev/null
@@ -1,215 +0,0 @@
1/*
2 * Simple (MOD player) - Instrument routines
3 * Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 */
20
21#include <sound/driver.h>
22#include <linux/init.h>
23#include <linux/slab.h>
24#include <sound/core.h>
25#include <sound/ainstr_simple.h>
26#include <sound/initval.h>
27#include <asm/uaccess.h>
28
29MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
30MODULE_DESCRIPTION("Advanced Linux Sound Architecture Simple Instrument support.");
31MODULE_LICENSE("GPL");
32
33static unsigned int snd_seq_simple_size(unsigned int size, unsigned int format)
34{
35 unsigned int result = size;
36
37 if (format & SIMPLE_WAVE_16BIT)
38 result <<= 1;
39 if (format & SIMPLE_WAVE_STEREO)
40 result <<= 1;
41 return result;
42}
43
44static void snd_seq_simple_instr_free(struct snd_simple_ops *ops,
45 struct simple_instrument *ip,
46 int atomic)
47{
48 if (ops->remove_sample)
49 ops->remove_sample(ops->private_data, ip, atomic);
50}
51
52static int snd_seq_simple_put(void *private_data, struct snd_seq_kinstr *instr,
53 char __user *instr_data, long len,
54 int atomic, int cmd)
55{
56 struct snd_simple_ops *ops = private_data;
57 struct simple_instrument *ip;
58 struct simple_xinstrument ix;
59 int err;
60 gfp_t gfp_mask;
61 unsigned int real_size;
62
63 if (cmd != SNDRV_SEQ_INSTR_PUT_CMD_CREATE)
64 return -EINVAL;
65 gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL;
66 /* copy instrument data */
67 if (len < (long)sizeof(ix))
68 return -EINVAL;
69 if (copy_from_user(&ix, instr_data, sizeof(ix)))
70 return -EFAULT;
71 if (ix.stype != SIMPLE_STRU_INSTR)
72 return -EINVAL;
73 instr_data += sizeof(ix);
74 len -= sizeof(ix);
75 ip = (struct simple_instrument *)KINSTR_DATA(instr);
76 ip->share_id[0] = le32_to_cpu(ix.share_id[0]);
77 ip->share_id[1] = le32_to_cpu(ix.share_id[1]);
78 ip->share_id[2] = le32_to_cpu(ix.share_id[2]);
79 ip->share_id[3] = le32_to_cpu(ix.share_id[3]);
80 ip->format = le32_to_cpu(ix.format);
81 ip->size = le32_to_cpu(ix.size);
82 ip->start = le32_to_cpu(ix.start);
83 ip->loop_start = le32_to_cpu(ix.loop_start);
84 ip->loop_end = le32_to_cpu(ix.loop_end);
85 ip->loop_repeat = le16_to_cpu(ix.loop_repeat);
86 ip->effect1 = ix.effect1;
87 ip->effect1_depth = ix.effect1_depth;
88 ip->effect2 = ix.effect2;
89 ip->effect2_depth = ix.effect2_depth;
90 real_size = snd_seq_simple_size(ip->size, ip->format);
91 if (len < (long)real_size)
92 return -EINVAL;
93 if (ops->put_sample) {
94 err = ops->put_sample(ops->private_data, ip,
95 instr_data, real_size, atomic);
96 if (err < 0)
97 return err;
98 }
99 return 0;
100}
101
102static int snd_seq_simple_get(void *private_data, struct snd_seq_kinstr *instr,
103 char __user *instr_data, long len,
104 int atomic, int cmd)
105{
106 struct snd_simple_ops *ops = private_data;
107 struct simple_instrument *ip;
108 struct simple_xinstrument ix;
109 int err;
110 unsigned int real_size;
111
112 if (cmd != SNDRV_SEQ_INSTR_GET_CMD_FULL)
113 return -EINVAL;
114 if (len < (long)sizeof(ix))
115 return -ENOMEM;
116 memset(&ix, 0, sizeof(ix));
117 ip = (struct simple_instrument *)KINSTR_DATA(instr);
118 ix.stype = SIMPLE_STRU_INSTR;
119 ix.share_id[0] = cpu_to_le32(ip->share_id[0]);
120 ix.share_id[1] = cpu_to_le32(ip->share_id[1]);
121 ix.share_id[2] = cpu_to_le32(ip->share_id[2]);
122 ix.share_id[3] = cpu_to_le32(ip->share_id[3]);
123 ix.format = cpu_to_le32(ip->format);
124 ix.size = cpu_to_le32(ip->size);
125 ix.start = cpu_to_le32(ip->start);
126 ix.loop_start = cpu_to_le32(ip->loop_start);
127 ix.loop_end = cpu_to_le32(ip->loop_end);
128 ix.loop_repeat = cpu_to_le32(ip->loop_repeat);
129 ix.effect1 = cpu_to_le16(ip->effect1);
130 ix.effect1_depth = cpu_to_le16(ip->effect1_depth);
131 ix.effect2 = ip->effect2;
132 ix.effect2_depth = ip->effect2_depth;
133 if (copy_to_user(instr_data, &ix, sizeof(ix)))
134 return -EFAULT;
135 instr_data += sizeof(ix);
136 len -= sizeof(ix);
137 real_size = snd_seq_simple_size(ip->size, ip->format);
138 if (len < (long)real_size)
139 return -ENOMEM;
140 if (ops->get_sample) {
141 err = ops->get_sample(ops->private_data, ip,
142 instr_data, real_size, atomic);
143 if (err < 0)
144 return err;
145 }
146 return 0;
147}
148
149static int snd_seq_simple_get_size(void *private_data, struct snd_seq_kinstr *instr,
150 long *size)
151{
152 struct simple_instrument *ip;
153
154 ip = (struct simple_instrument *)KINSTR_DATA(instr);
155 *size = sizeof(struct simple_xinstrument) + snd_seq_simple_size(ip->size, ip->format);
156 return 0;
157}
158
159static int snd_seq_simple_remove(void *private_data,
160 struct snd_seq_kinstr *instr,
161 int atomic)
162{
163 struct snd_simple_ops *ops = private_data;
164 struct simple_instrument *ip;
165
166 ip = (struct simple_instrument *)KINSTR_DATA(instr);
167 snd_seq_simple_instr_free(ops, ip, atomic);
168 return 0;
169}
170
171static void snd_seq_simple_notify(void *private_data,
172 struct snd_seq_kinstr *instr,
173 int what)
174{
175 struct snd_simple_ops *ops = private_data;
176
177 if (ops->notify)
178 ops->notify(ops->private_data, instr, what);
179}
180
181int snd_seq_simple_init(struct snd_simple_ops *ops,
182 void *private_data,
183 struct snd_seq_kinstr_ops *next)
184{
185 memset(ops, 0, sizeof(*ops));
186 ops->private_data = private_data;
187 ops->kops.private_data = ops;
188 ops->kops.add_len = sizeof(struct simple_instrument);
189 ops->kops.instr_type = SNDRV_SEQ_INSTR_ID_SIMPLE;
190 ops->kops.put = snd_seq_simple_put;
191 ops->kops.get = snd_seq_simple_get;
192 ops->kops.get_size = snd_seq_simple_get_size;
193 ops->kops.remove = snd_seq_simple_remove;
194 ops->kops.notify = snd_seq_simple_notify;
195 ops->kops.next = next;
196 return 0;
197}
198
199/*
200 * Init part
201 */
202
203static int __init alsa_ainstr_simple_init(void)
204{
205 return 0;
206}
207
208static void __exit alsa_ainstr_simple_exit(void)
209{
210}
211
212module_init(alsa_ainstr_simple_init)
213module_exit(alsa_ainstr_simple_exit)
214
215EXPORT_SYMBOL(snd_seq_simple_init);
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index 2e3fa25ab19f..69421ca68167 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -966,8 +966,7 @@ static int check_event_type_and_length(struct snd_seq_event *ev)
966 return -EINVAL; 966 return -EINVAL;
967 break; 967 break;
968 case SNDRV_SEQ_EVENT_LENGTH_VARUSR: 968 case SNDRV_SEQ_EVENT_LENGTH_VARUSR:
969 if (! snd_seq_ev_is_instr_type(ev) || 969 if (! snd_seq_ev_is_direct(ev))
970 ! snd_seq_ev_is_direct(ev))
971 return -EINVAL; 970 return -EINVAL;
972 break; 971 break;
973 } 972 }
diff --git a/sound/core/seq/seq_instr.c b/sound/core/seq/seq_instr.c
deleted file mode 100644
index 9a6fd56c9109..000000000000
--- a/sound/core/seq/seq_instr.c
+++ /dev/null
@@ -1,655 +0,0 @@
1/*
2 * Generic Instrument routines for ALSA sequencer
3 * Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 */
20
21#include <sound/driver.h>
22#include <linux/init.h>
23#include <linux/slab.h>
24#include <sound/core.h>
25#include "seq_clientmgr.h"
26#include <sound/seq_instr.h>
27#include <sound/initval.h>
28
29MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
30MODULE_DESCRIPTION("Advanced Linux Sound Architecture sequencer instrument library.");
31MODULE_LICENSE("GPL");
32
33
34static void snd_instr_lock_ops(struct snd_seq_kinstr_list *list)
35{
36 if (!(list->flags & SNDRV_SEQ_INSTR_FLG_DIRECT)) {
37 spin_lock_irqsave(&list->ops_lock, list->ops_flags);
38 } else {
39 mutex_lock(&list->ops_mutex);
40 }
41}
42
43static void snd_instr_unlock_ops(struct snd_seq_kinstr_list *list)
44{
45 if (!(list->flags & SNDRV_SEQ_INSTR_FLG_DIRECT)) {
46 spin_unlock_irqrestore(&list->ops_lock, list->ops_flags);
47 } else {
48 mutex_unlock(&list->ops_mutex);
49 }
50}
51
52static struct snd_seq_kinstr *snd_seq_instr_new(int add_len, int atomic)
53{
54 struct snd_seq_kinstr *instr;
55
56 instr = kzalloc(sizeof(struct snd_seq_kinstr) + add_len, atomic ? GFP_ATOMIC : GFP_KERNEL);
57 if (instr == NULL)
58 return NULL;
59 instr->add_len = add_len;
60 return instr;
61}
62
63static int snd_seq_instr_free(struct snd_seq_kinstr *instr, int atomic)
64{
65 int result = 0;
66
67 if (instr == NULL)
68 return -EINVAL;
69 if (instr->ops && instr->ops->remove)
70 result = instr->ops->remove(instr->ops->private_data, instr, 1);
71 if (!result)
72 kfree(instr);
73 return result;
74}
75
76struct snd_seq_kinstr_list *snd_seq_instr_list_new(void)
77{
78 struct snd_seq_kinstr_list *list;
79
80 list = kzalloc(sizeof(struct snd_seq_kinstr_list), GFP_KERNEL);
81 if (list == NULL)
82 return NULL;
83 spin_lock_init(&list->lock);
84 spin_lock_init(&list->ops_lock);
85 mutex_init(&list->ops_mutex);
86 list->owner = -1;
87 return list;
88}
89
90void snd_seq_instr_list_free(struct snd_seq_kinstr_list **list_ptr)
91{
92 struct snd_seq_kinstr_list *list;
93 struct snd_seq_kinstr *instr;
94 struct snd_seq_kcluster *cluster;
95 int idx;
96 unsigned long flags;
97
98 if (list_ptr == NULL)
99 return;
100 list = *list_ptr;
101 *list_ptr = NULL;
102 if (list == NULL)
103 return;
104
105 for (idx = 0; idx < SNDRV_SEQ_INSTR_HASH_SIZE; idx++) {
106 while ((instr = list->hash[idx]) != NULL) {
107 list->hash[idx] = instr->next;
108 list->count--;
109 spin_lock_irqsave(&list->lock, flags);
110 while (instr->use) {
111 spin_unlock_irqrestore(&list->lock, flags);
112 schedule_timeout_uninterruptible(1);
113 spin_lock_irqsave(&list->lock, flags);
114 }
115 spin_unlock_irqrestore(&list->lock, flags);
116 if (snd_seq_instr_free(instr, 0)<0)
117 snd_printk(KERN_WARNING "instrument free problem\n");
118 }
119 while ((cluster = list->chash[idx]) != NULL) {
120 list->chash[idx] = cluster->next;
121 list->ccount--;
122 kfree(cluster);
123 }
124 }
125 kfree(list);
126}
127
128static int instr_free_compare(struct snd_seq_kinstr *instr,
129 struct snd_seq_instr_header *ifree,
130 unsigned int client)
131{
132 switch (ifree->cmd) {
133 case SNDRV_SEQ_INSTR_FREE_CMD_ALL:
134 /* all, except private for other clients */
135 if ((instr->instr.std & 0xff000000) == 0)
136 return 0;
137 if (((instr->instr.std >> 24) & 0xff) == client)
138 return 0;
139 return 1;
140 case SNDRV_SEQ_INSTR_FREE_CMD_PRIVATE:
141 /* all my private instruments */
142 if ((instr->instr.std & 0xff000000) == 0)
143 return 1;
144 if (((instr->instr.std >> 24) & 0xff) == client)
145 return 0;
146 return 1;
147 case SNDRV_SEQ_INSTR_FREE_CMD_CLUSTER:
148 /* all my private instruments */
149 if ((instr->instr.std & 0xff000000) == 0) {
150 if (instr->instr.cluster == ifree->id.cluster)
151 return 0;
152 return 1;
153 }
154 if (((instr->instr.std >> 24) & 0xff) == client) {
155 if (instr->instr.cluster == ifree->id.cluster)
156 return 0;
157 }
158 return 1;
159 }
160 return 1;
161}
162
163int snd_seq_instr_list_free_cond(struct snd_seq_kinstr_list *list,
164 struct snd_seq_instr_header *ifree,
165 int client,
166 int atomic)
167{
168 struct snd_seq_kinstr *instr, *prev, *next, *flist;
169 int idx;
170 unsigned long flags;
171
172 snd_instr_lock_ops(list);
173 for (idx = 0; idx < SNDRV_SEQ_INSTR_HASH_SIZE; idx++) {
174 spin_lock_irqsave(&list->lock, flags);
175 instr = list->hash[idx];
176 prev = flist = NULL;
177 while (instr) {
178 while (instr && instr_free_compare(instr, ifree, (unsigned int)client)) {
179 prev = instr;
180 instr = instr->next;
181 }
182 if (instr == NULL)
183 continue;
184 if (instr->ops && instr->ops->notify)
185 instr->ops->notify(instr->ops->private_data, instr, SNDRV_SEQ_INSTR_NOTIFY_REMOVE);
186 next = instr->next;
187 if (prev == NULL) {
188 list->hash[idx] = next;
189 } else {
190 prev->next = next;
191 }
192 list->count--;
193 instr->next = flist;
194 flist = instr;
195 instr = next;
196 }
197 spin_unlock_irqrestore(&list->lock, flags);
198 while (flist) {
199 instr = flist;
200 flist = instr->next;
201 while (instr->use) {
202 schedule_timeout_uninterruptible(1);
203 barrier();
204 }
205 if (snd_seq_instr_free(instr, atomic)<0)
206 snd_printk(KERN_WARNING "instrument free problem\n");
207 instr = next;
208 }
209 }
210 snd_instr_unlock_ops(list);
211 return 0;
212}
213
214static int compute_hash_instr_key(struct snd_seq_instr *instr)
215{
216 int result;
217
218 result = instr->bank | (instr->prg << 16);
219 result += result >> 24;
220 result += result >> 16;
221 result += result >> 8;
222 return result & (SNDRV_SEQ_INSTR_HASH_SIZE-1);
223}
224
225#if 0
226static int compute_hash_cluster_key(snd_seq_instr_cluster_t cluster)
227{
228 int result;
229
230 result = cluster;
231 result += result >> 24;
232 result += result >> 16;
233 result += result >> 8;
234 return result & (SNDRV_SEQ_INSTR_HASH_SIZE-1);
235}
236#endif
237
238static int compare_instr(struct snd_seq_instr *i1, struct snd_seq_instr *i2, int exact)
239{
240 if (exact) {
241 if (i1->cluster != i2->cluster ||
242 i1->bank != i2->bank ||
243 i1->prg != i2->prg)
244 return 1;
245 if ((i1->std & 0xff000000) != (i2->std & 0xff000000))
246 return 1;
247 if (!(i1->std & i2->std))
248 return 1;
249 return 0;
250 } else {
251 unsigned int client_check;
252
253 if (i2->cluster && i1->cluster != i2->cluster)
254 return 1;
255 client_check = i2->std & 0xff000000;
256 if (client_check) {
257 if ((i1->std & 0xff000000) != client_check)
258 return 1;
259 } else {
260 if ((i1->std & i2->std) != i2->std)
261 return 1;
262 }
263 return i1->bank != i2->bank || i1->prg != i2->prg;
264 }
265}
266
267struct snd_seq_kinstr *snd_seq_instr_find(struct snd_seq_kinstr_list *list,
268 struct snd_seq_instr *instr,
269 int exact,
270 int follow_alias)
271{
272 unsigned long flags;
273 int depth = 0;
274 struct snd_seq_kinstr *result;
275
276 if (list == NULL || instr == NULL)
277 return NULL;
278 spin_lock_irqsave(&list->lock, flags);
279 __again:
280 result = list->hash[compute_hash_instr_key(instr)];
281 while (result) {
282 if (!compare_instr(&result->instr, instr, exact)) {
283 if (follow_alias && (result->type == SNDRV_SEQ_INSTR_ATYPE_ALIAS)) {
284 instr = (struct snd_seq_instr *)KINSTR_DATA(result);
285 if (++depth > 10)
286 goto __not_found;
287 goto __again;
288 }
289 result->use++;
290 spin_unlock_irqrestore(&list->lock, flags);
291 return result;
292 }
293 result = result->next;
294 }
295 __not_found:
296 spin_unlock_irqrestore(&list->lock, flags);
297 return NULL;
298}
299
300void snd_seq_instr_free_use(struct snd_seq_kinstr_list *list,
301 struct snd_seq_kinstr *instr)
302{
303 unsigned long flags;
304
305 if (list == NULL || instr == NULL)
306 return;
307 spin_lock_irqsave(&list->lock, flags);
308 if (instr->use <= 0) {
309 snd_printk(KERN_ERR "free_use: fatal!!! use = %i, name = '%s'\n", instr->use, instr->name);
310 } else {
311 instr->use--;
312 }
313 spin_unlock_irqrestore(&list->lock, flags);
314}
315
316static struct snd_seq_kinstr_ops *instr_ops(struct snd_seq_kinstr_ops *ops,
317 char *instr_type)
318{
319 while (ops) {
320 if (!strcmp(ops->instr_type, instr_type))
321 return ops;
322 ops = ops->next;
323 }
324 return NULL;
325}
326
327static int instr_result(struct snd_seq_event *ev,
328 int type, int result,
329 int atomic)
330{
331 struct snd_seq_event sev;
332
333 memset(&sev, 0, sizeof(sev));
334 sev.type = SNDRV_SEQ_EVENT_RESULT;
335 sev.flags = SNDRV_SEQ_TIME_STAMP_REAL | SNDRV_SEQ_EVENT_LENGTH_FIXED |
336 SNDRV_SEQ_PRIORITY_NORMAL;
337 sev.source = ev->dest;
338 sev.dest = ev->source;
339 sev.data.result.event = type;
340 sev.data.result.result = result;
341#if 0
342 printk("instr result - type = %i, result = %i, queue = %i, source.client:port = %i:%i, dest.client:port = %i:%i\n",
343 type, result,
344 sev.queue,
345 sev.source.client, sev.source.port,
346 sev.dest.client, sev.dest.port);
347#endif
348 return snd_seq_kernel_client_dispatch(sev.source.client, &sev, atomic, 0);
349}
350
351static int instr_begin(struct snd_seq_kinstr_ops *ops,
352 struct snd_seq_kinstr_list *list,
353 struct snd_seq_event *ev,
354 int atomic, int hop)
355{
356 unsigned long flags;
357
358 spin_lock_irqsave(&list->lock, flags);
359 if (list->owner >= 0 && list->owner != ev->source.client) {
360 spin_unlock_irqrestore(&list->lock, flags);
361 return instr_result(ev, SNDRV_SEQ_EVENT_INSTR_BEGIN, -EBUSY, atomic);
362 }
363 list->owner = ev->source.client;
364 spin_unlock_irqrestore(&list->lock, flags);
365 return instr_result(ev, SNDRV_SEQ_EVENT_INSTR_BEGIN, 0, atomic);
366}
367
368static int instr_end(struct snd_seq_kinstr_ops *ops,
369 struct snd_seq_kinstr_list *list,
370 struct snd_seq_event *ev,
371 int atomic, int hop)
372{
373 unsigned long flags;
374
375 /* TODO: timeout handling */
376 spin_lock_irqsave(&list->lock, flags);
377 if (list->owner == ev->source.client) {
378 list->owner = -1;
379 spin_unlock_irqrestore(&list->lock, flags);
380 return instr_result(ev, SNDRV_SEQ_EVENT_INSTR_END, 0, atomic);
381 }
382 spin_unlock_irqrestore(&list->lock, flags);
383 return instr_result(ev, SNDRV_SEQ_EVENT_INSTR_END, -EINVAL, atomic);
384}
385
386static int instr_info(struct snd_seq_kinstr_ops *ops,
387 struct snd_seq_kinstr_list *list,
388 struct snd_seq_event *ev,
389 int atomic, int hop)
390{
391 return -ENXIO;
392}
393
394static int instr_format_info(struct snd_seq_kinstr_ops *ops,
395 struct snd_seq_kinstr_list *list,
396 struct snd_seq_event *ev,
397 int atomic, int hop)
398{
399 return -ENXIO;
400}
401
402static int instr_reset(struct snd_seq_kinstr_ops *ops,
403 struct snd_seq_kinstr_list *list,
404 struct snd_seq_event *ev,
405 int atomic, int hop)
406{
407 return -ENXIO;
408}
409
410static int instr_status(struct snd_seq_kinstr_ops *ops,
411 struct snd_seq_kinstr_list *list,
412 struct snd_seq_event *ev,
413 int atomic, int hop)
414{
415 return -ENXIO;
416}
417
418static int instr_put(struct snd_seq_kinstr_ops *ops,
419 struct snd_seq_kinstr_list *list,
420 struct snd_seq_event *ev,
421 int atomic, int hop)
422{
423 unsigned long flags;
424 struct snd_seq_instr_header put;
425 struct snd_seq_kinstr *instr;
426 int result = -EINVAL, len, key;
427
428 if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) != SNDRV_SEQ_EVENT_LENGTH_VARUSR)
429 goto __return;
430
431 if (ev->data.ext.len < sizeof(struct snd_seq_instr_header))
432 goto __return;
433 if (copy_from_user(&put, (void __user *)ev->data.ext.ptr,
434 sizeof(struct snd_seq_instr_header))) {
435 result = -EFAULT;
436 goto __return;
437 }
438 snd_instr_lock_ops(list);
439 if (put.id.instr.std & 0xff000000) { /* private instrument */
440 put.id.instr.std &= 0x00ffffff;
441 put.id.instr.std |= (unsigned int)ev->source.client << 24;
442 }
443 if ((instr = snd_seq_instr_find(list, &put.id.instr, 1, 0))) {
444 snd_seq_instr_free_use(list, instr);
445 snd_instr_unlock_ops(list);
446 result = -EBUSY;
447 goto __return;
448 }
449 ops = instr_ops(ops, put.data.data.format);
450 if (ops == NULL) {
451 snd_instr_unlock_ops(list);
452 goto __return;
453 }
454 len = ops->add_len;
455 if (put.data.type == SNDRV_SEQ_INSTR_ATYPE_ALIAS)
456 len = sizeof(struct snd_seq_instr);
457 instr = snd_seq_instr_new(len, atomic);
458 if (instr == NULL) {
459 snd_instr_unlock_ops(list);
460 result = -ENOMEM;
461 goto __return;
462 }
463 instr->ops = ops;
464 instr->instr = put.id.instr;
465 strlcpy(instr->name, put.data.name, sizeof(instr->name));
466 instr->type = put.data.type;
467 if (instr->type == SNDRV_SEQ_INSTR_ATYPE_DATA) {
468 result = ops->put(ops->private_data,
469 instr,
470 (void __user *)ev->data.ext.ptr + sizeof(struct snd_seq_instr_header),
471 ev->data.ext.len - sizeof(struct snd_seq_instr_header),
472 atomic,
473 put.cmd);
474 if (result < 0) {
475 snd_seq_instr_free(instr, atomic);
476 snd_instr_unlock_ops(list);
477 goto __return;
478 }
479 }
480 key = compute_hash_instr_key(&instr->instr);
481 spin_lock_irqsave(&list->lock, flags);
482 instr->next = list->hash[key];
483 list->hash[key] = instr;
484 list->count++;
485 spin_unlock_irqrestore(&list->lock, flags);
486 snd_instr_unlock_ops(list);
487 result = 0;
488 __return:
489 instr_result(ev, SNDRV_SEQ_EVENT_INSTR_PUT, result, atomic);
490 return result;
491}
492
493static int instr_get(struct snd_seq_kinstr_ops *ops,
494 struct snd_seq_kinstr_list *list,
495 struct snd_seq_event *ev,
496 int atomic, int hop)
497{
498 return -ENXIO;
499}
500
501static int instr_free(struct snd_seq_kinstr_ops *ops,
502 struct snd_seq_kinstr_list *list,
503 struct snd_seq_event *ev,
504 int atomic, int hop)
505{
506 struct snd_seq_instr_header ifree;
507 struct snd_seq_kinstr *instr, *prev;
508 int result = -EINVAL;
509 unsigned long flags;
510 unsigned int hash;
511
512 if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) != SNDRV_SEQ_EVENT_LENGTH_VARUSR)
513 goto __return;
514
515 if (ev->data.ext.len < sizeof(struct snd_seq_instr_header))
516 goto __return;
517 if (copy_from_user(&ifree, (void __user *)ev->data.ext.ptr,
518 sizeof(struct snd_seq_instr_header))) {
519 result = -EFAULT;
520 goto __return;
521 }
522 if (ifree.cmd == SNDRV_SEQ_INSTR_FREE_CMD_ALL ||
523 ifree.cmd == SNDRV_SEQ_INSTR_FREE_CMD_PRIVATE ||
524 ifree.cmd == SNDRV_SEQ_INSTR_FREE_CMD_CLUSTER) {
525 result = snd_seq_instr_list_free_cond(list, &ifree, ev->dest.client, atomic);
526 goto __return;
527 }
528 if (ifree.cmd == SNDRV_SEQ_INSTR_FREE_CMD_SINGLE) {
529 if (ifree.id.instr.std & 0xff000000) {
530 ifree.id.instr.std &= 0x00ffffff;
531 ifree.id.instr.std |= (unsigned int)ev->source.client << 24;
532 }
533 hash = compute_hash_instr_key(&ifree.id.instr);
534 snd_instr_lock_ops(list);
535 spin_lock_irqsave(&list->lock, flags);
536 instr = list->hash[hash];
537 prev = NULL;
538 while (instr) {
539 if (!compare_instr(&instr->instr, &ifree.id.instr, 1))
540 goto __free_single;
541 prev = instr;
542 instr = instr->next;
543 }
544 result = -ENOENT;
545 spin_unlock_irqrestore(&list->lock, flags);
546 snd_instr_unlock_ops(list);
547 goto __return;
548
549 __free_single:
550 if (prev) {
551 prev->next = instr->next;
552 } else {
553 list->hash[hash] = instr->next;
554 }
555 if (instr->ops && instr->ops->notify)
556 instr->ops->notify(instr->ops->private_data, instr,
557 SNDRV_SEQ_INSTR_NOTIFY_REMOVE);
558 while (instr->use) {
559 spin_unlock_irqrestore(&list->lock, flags);
560 schedule_timeout_uninterruptible(1);
561 spin_lock_irqsave(&list->lock, flags);
562 }
563 spin_unlock_irqrestore(&list->lock, flags);
564 result = snd_seq_instr_free(instr, atomic);
565 snd_instr_unlock_ops(list);
566 goto __return;
567 }
568
569 __return:
570 instr_result(ev, SNDRV_SEQ_EVENT_INSTR_FREE, result, atomic);
571 return result;
572}
573
574static int instr_list(struct snd_seq_kinstr_ops *ops,
575 struct snd_seq_kinstr_list *list,
576 struct snd_seq_event *ev,
577 int atomic, int hop)
578{
579 return -ENXIO;
580}
581
582static int instr_cluster(struct snd_seq_kinstr_ops *ops,
583 struct snd_seq_kinstr_list *list,
584 struct snd_seq_event *ev,
585 int atomic, int hop)
586{
587 return -ENXIO;
588}
589
590int snd_seq_instr_event(struct snd_seq_kinstr_ops *ops,
591 struct snd_seq_kinstr_list *list,
592 struct snd_seq_event *ev,
593 int client,
594 int atomic,
595 int hop)
596{
597 int direct = 0;
598
599 snd_assert(ops != NULL && list != NULL && ev != NULL, return -EINVAL);
600 if (snd_seq_ev_is_direct(ev)) {
601 direct = 1;
602 switch (ev->type) {
603 case SNDRV_SEQ_EVENT_INSTR_BEGIN:
604 return instr_begin(ops, list, ev, atomic, hop);
605 case SNDRV_SEQ_EVENT_INSTR_END:
606 return instr_end(ops, list, ev, atomic, hop);
607 }
608 }
609 if ((list->flags & SNDRV_SEQ_INSTR_FLG_DIRECT) && !direct)
610 return -EINVAL;
611 switch (ev->type) {
612 case SNDRV_SEQ_EVENT_INSTR_INFO:
613 return instr_info(ops, list, ev, atomic, hop);
614 case SNDRV_SEQ_EVENT_INSTR_FINFO:
615 return instr_format_info(ops, list, ev, atomic, hop);
616 case SNDRV_SEQ_EVENT_INSTR_RESET:
617 return instr_reset(ops, list, ev, atomic, hop);
618 case SNDRV_SEQ_EVENT_INSTR_STATUS:
619 return instr_status(ops, list, ev, atomic, hop);
620 case SNDRV_SEQ_EVENT_INSTR_PUT:
621 return instr_put(ops, list, ev, atomic, hop);
622 case SNDRV_SEQ_EVENT_INSTR_GET:
623 return instr_get(ops, list, ev, atomic, hop);
624 case SNDRV_SEQ_EVENT_INSTR_FREE:
625 return instr_free(ops, list, ev, atomic, hop);
626 case SNDRV_SEQ_EVENT_INSTR_LIST:
627 return instr_list(ops, list, ev, atomic, hop);
628 case SNDRV_SEQ_EVENT_INSTR_CLUSTER:
629 return instr_cluster(ops, list, ev, atomic, hop);
630 }
631 return -EINVAL;
632}
633
634/*
635 * Init part
636 */
637
638static int __init alsa_seq_instr_init(void)
639{
640 return 0;
641}
642
643static void __exit alsa_seq_instr_exit(void)
644{
645}
646
647module_init(alsa_seq_instr_init)
648module_exit(alsa_seq_instr_exit)
649
650EXPORT_SYMBOL(snd_seq_instr_list_new);
651EXPORT_SYMBOL(snd_seq_instr_list_free);
652EXPORT_SYMBOL(snd_seq_instr_list_free_cond);
653EXPORT_SYMBOL(snd_seq_instr_find);
654EXPORT_SYMBOL(snd_seq_instr_free_use);
655EXPORT_SYMBOL(snd_seq_instr_event);
diff --git a/sound/core/seq/seq_midi_emul.c b/sound/core/seq/seq_midi_emul.c
index 17b3e6f13ca3..6645fc544621 100644
--- a/sound/core/seq/seq_midi_emul.c
+++ b/sound/core/seq/seq_midi_emul.c
@@ -229,13 +229,6 @@ snd_midi_process_event(struct snd_midi_op *ops,
229 case SNDRV_SEQ_EVENT_PORT_START: 229 case SNDRV_SEQ_EVENT_PORT_START:
230 case SNDRV_SEQ_EVENT_PORT_EXIT: 230 case SNDRV_SEQ_EVENT_PORT_EXIT:
231 case SNDRV_SEQ_EVENT_PORT_CHANGE: 231 case SNDRV_SEQ_EVENT_PORT_CHANGE:
232 case SNDRV_SEQ_EVENT_SAMPLE:
233 case SNDRV_SEQ_EVENT_SAMPLE_START:
234 case SNDRV_SEQ_EVENT_SAMPLE_STOP:
235 case SNDRV_SEQ_EVENT_SAMPLE_FREQ:
236 case SNDRV_SEQ_EVENT_SAMPLE_VOLUME:
237 case SNDRV_SEQ_EVENT_SAMPLE_LOOP:
238 case SNDRV_SEQ_EVENT_SAMPLE_POSITION:
239 case SNDRV_SEQ_EVENT_ECHO: 232 case SNDRV_SEQ_EVENT_ECHO:
240 not_yet: 233 not_yet:
241 default: 234 default: