aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2007-10-30 07:17:17 -0400
committerJaroslav Kysela <perex@perex.cz>2008-01-31 11:29:13 -0500
commite5723b41abe559bafc52591dcf8ee19cc131d3a1 (patch)
treea1d035132ae1354c43eb9fccf60c9668e0abb266 /sound/core
parent05c1afe75fcebf456017ec186811cf1599f4360e (diff)
[ALSA] Remove sequencer instrument layer
Remove sequencer instrument layer from the tree. This mechanism hasn't been used much with the actual devices. The only reasonable user was OPL3 loader, and now it was rewritten to use hwdep instead. So, let's remove the rest of rotten codes. Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@perex.cz>
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: