diff options
Diffstat (limited to 'sound/core')
-rw-r--r-- | sound/core/seq/Makefile | 8 | ||||
-rw-r--r-- | sound/core/seq/instr/Makefile | 23 | ||||
-rw-r--r-- | sound/core/seq/instr/ainstr_fm.c | 155 | ||||
-rw-r--r-- | sound/core/seq/instr/ainstr_gf1.c | 359 | ||||
-rw-r--r-- | sound/core/seq/instr/ainstr_iw.c | 623 | ||||
-rw-r--r-- | sound/core/seq/instr/ainstr_simple.c | 215 | ||||
-rw-r--r-- | sound/core/seq/seq_clientmgr.c | 3 | ||||
-rw-r--r-- | sound/core/seq/seq_instr.c | 655 | ||||
-rw-r--r-- | sound/core/seq/seq_midi_emul.c | 7 |
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 | ||
6 | obj-$(CONFIG_SND) += instr/ | ||
7 | ifeq ($(CONFIG_SND_SEQUENCER_OSS),y) | 6 | ifeq ($(CONFIG_SND_SEQUENCER_OSS),y) |
8 | obj-$(CONFIG_SND_SEQUENCER) += oss/ | 7 | obj-$(CONFIG_SND_SEQUENCER) += oss/ |
9 | endif | 8 | endif |
@@ -15,7 +14,6 @@ snd-seq-objs := seq.o seq_lock.o seq_clientmgr.o seq_memory.o seq_queue.o \ | |||
15 | snd-seq-midi-objs := seq_midi.o | 14 | snd-seq-midi-objs := seq_midi.o |
16 | snd-seq-midi-emul-objs := seq_midi_emul.o | 15 | snd-seq-midi-emul-objs := seq_midi_emul.o |
17 | snd-seq-midi-event-objs := seq_midi_event.o | 16 | snd-seq-midi-event-objs := seq_midi_event.o |
18 | snd-seq-instr-objs := seq_instr.o | ||
19 | snd-seq-dummy-objs := seq_dummy.o | 17 | snd-seq-dummy-objs := seq_dummy.o |
20 | snd-seq-virmidi-objs := seq_virmidi.o | 18 | snd-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 |
37 | obj-$(CONFIG_SND_VIRMIDI) += snd-seq-virmidi.o snd-seq-midi-event.o | 35 | obj-$(CONFIG_SND_VIRMIDI) += snd-seq-virmidi.o snd-seq-midi-event.o |
38 | obj-$(call sequencer,$(CONFIG_SND_RAWMIDI)) += snd-seq-midi.o snd-seq-midi-event.o | 36 | obj-$(call sequencer,$(CONFIG_SND_RAWMIDI)) += snd-seq-midi.o snd-seq-midi-event.o |
39 | obj-$(call sequencer,$(CONFIG_SND_OPL3_LIB)) += snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o | 37 | obj-$(call sequencer,$(CONFIG_SND_OPL3_LIB)) += snd-seq-midi-event.o snd-seq-midi-emul.o |
40 | obj-$(call sequencer,$(CONFIG_SND_OPL4_LIB)) += snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o | 38 | obj-$(call sequencer,$(CONFIG_SND_OPL4_LIB)) += snd-seq-midi-event.o snd-seq-midi-emul.o |
41 | obj-$(call sequencer,$(CONFIG_SND_GUS_SYNTH)) += snd-seq-midi-emul.o snd-seq-instr.o | ||
42 | obj-$(call sequencer,$(CONFIG_SND_SBAWE)) += snd-seq-midi-emul.o snd-seq-virmidi.o | 39 | obj-$(call sequencer,$(CONFIG_SND_SBAWE)) += snd-seq-midi-emul.o snd-seq-virmidi.o |
43 | obj-$(call sequencer,$(CONFIG_SND_EMU10K1)) += snd-seq-midi-emul.o snd-seq-virmidi.o | 40 | obj-$(call sequencer,$(CONFIG_SND_EMU10K1)) += snd-seq-midi-emul.o snd-seq-virmidi.o |
44 | obj-$(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 | |||
6 | snd-ainstr-fm-objs := ainstr_fm.o | ||
7 | snd-ainstr-simple-objs := ainstr_simple.o | ||
8 | snd-ainstr-gf1-objs := ainstr_gf1.o | ||
9 | snd-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 | # | ||
17 | sequencer = $(if $(subst y,,$(CONFIG_SND_SEQUENCER)),$(if $(1),m),$(if $(CONFIG_SND_SEQUENCER),$(1))) | ||
18 | |||
19 | # Toplevel Module Dependency | ||
20 | obj-$(call sequencer,$(CONFIG_SND_OPL3_LIB)) += snd-ainstr-fm.o | ||
21 | obj-$(call sequencer,$(CONFIG_SND_OPL4_LIB)) += snd-ainstr-fm.o | ||
22 | obj-$(call sequencer,$(CONFIG_SND_GUS_SYNTH)) += snd-ainstr-gf1.o snd-ainstr-simple.o snd-ainstr-iw.o | ||
23 | obj-$(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 | |||
28 | MODULE_AUTHOR("Uros Bizjak <uros@kss-loka.si>"); | ||
29 | MODULE_DESCRIPTION("Advanced Linux Sound Architecture FM Instrument support."); | ||
30 | MODULE_LICENSE("GPL"); | ||
31 | |||
32 | static 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 | |||
74 | static 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 | |||
116 | static 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 | |||
123 | int 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 | |||
143 | static int __init alsa_ainstr_fm_init(void) | ||
144 | { | ||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | static void __exit alsa_ainstr_fm_exit(void) | ||
149 | { | ||
150 | } | ||
151 | |||
152 | module_init(alsa_ainstr_fm_init) | ||
153 | module_exit(alsa_ainstr_fm_exit) | ||
154 | |||
155 | EXPORT_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 | |||
29 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); | ||
30 | MODULE_DESCRIPTION("Advanced Linux Sound Architecture GF1 (GUS) Patch support."); | ||
31 | MODULE_LICENSE("GPL"); | ||
32 | |||
33 | static 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 | |||
44 | static 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 | |||
118 | static 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 | |||
127 | static 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 | |||
139 | static 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 | |||
191 | static 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 | |||
253 | static 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 | |||
285 | static 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 | |||
303 | static 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 | |||
315 | static 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 | |||
325 | int 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 | |||
347 | static int __init alsa_ainstr_gf1_init(void) | ||
348 | { | ||
349 | return 0; | ||
350 | } | ||
351 | |||
352 | static void __exit alsa_ainstr_gf1_exit(void) | ||
353 | { | ||
354 | } | ||
355 | |||
356 | module_init(alsa_ainstr_gf1_init) | ||
357 | module_exit(alsa_ainstr_gf1_exit) | ||
358 | |||
359 | EXPORT_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 | |||
29 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); | ||
30 | MODULE_DESCRIPTION("Advanced Linux Sound Architecture IWFFFF support."); | ||
31 | MODULE_LICENSE("GPL"); | ||
32 | |||
33 | static 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 | |||
44 | static 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 | |||
54 | static 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 | |||
122 | static 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 | |||
188 | static 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 | |||
200 | static 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 | |||
209 | static 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 | |||
228 | static 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 | |||
337 | static 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 | |||
347 | static 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 | |||
394 | static 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 | |||
449 | static 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 | |||
522 | static 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 | |||
534 | static 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 | |||
547 | static 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 | |||
567 | static 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 | |||
579 | static 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 | |||
589 | int 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 | |||
611 | static int __init alsa_ainstr_iw_init(void) | ||
612 | { | ||
613 | return 0; | ||
614 | } | ||
615 | |||
616 | static void __exit alsa_ainstr_iw_exit(void) | ||
617 | { | ||
618 | } | ||
619 | |||
620 | module_init(alsa_ainstr_iw_init) | ||
621 | module_exit(alsa_ainstr_iw_exit) | ||
622 | |||
623 | EXPORT_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 | |||
29 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); | ||
30 | MODULE_DESCRIPTION("Advanced Linux Sound Architecture Simple Instrument support."); | ||
31 | MODULE_LICENSE("GPL"); | ||
32 | |||
33 | static 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 | |||
44 | static 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 | |||
52 | static 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 | |||
102 | static 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 | |||
149 | static 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 | |||
159 | static 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 | |||
171 | static 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 | |||
181 | int 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 | |||
203 | static int __init alsa_ainstr_simple_init(void) | ||
204 | { | ||
205 | return 0; | ||
206 | } | ||
207 | |||
208 | static void __exit alsa_ainstr_simple_exit(void) | ||
209 | { | ||
210 | } | ||
211 | |||
212 | module_init(alsa_ainstr_simple_init) | ||
213 | module_exit(alsa_ainstr_simple_exit) | ||
214 | |||
215 | EXPORT_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 | |||
29 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); | ||
30 | MODULE_DESCRIPTION("Advanced Linux Sound Architecture sequencer instrument library."); | ||
31 | MODULE_LICENSE("GPL"); | ||
32 | |||
33 | |||
34 | static 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 | |||
43 | static 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 | |||
52 | static 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 | |||
63 | static 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 | |||
76 | struct 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 | |||
90 | void 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 | |||
128 | static 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 | |||
163 | int 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 | |||
214 | static 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 | ||
226 | static 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 | |||
238 | static 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 | |||
267 | struct 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 | |||
300 | void 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 | |||
316 | static 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 | |||
327 | static 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 | |||
351 | static 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 | |||
368 | static 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 | |||
386 | static 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 | |||
394 | static 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 | |||
402 | static 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 | |||
410 | static 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 | |||
418 | static 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 | |||
493 | static 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 | |||
501 | static 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 | |||
574 | static 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 | |||
582 | static 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 | |||
590 | int 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 | |||
638 | static int __init alsa_seq_instr_init(void) | ||
639 | { | ||
640 | return 0; | ||
641 | } | ||
642 | |||
643 | static void __exit alsa_seq_instr_exit(void) | ||
644 | { | ||
645 | } | ||
646 | |||
647 | module_init(alsa_seq_instr_init) | ||
648 | module_exit(alsa_seq_instr_exit) | ||
649 | |||
650 | EXPORT_SYMBOL(snd_seq_instr_list_new); | ||
651 | EXPORT_SYMBOL(snd_seq_instr_list_free); | ||
652 | EXPORT_SYMBOL(snd_seq_instr_list_free_cond); | ||
653 | EXPORT_SYMBOL(snd_seq_instr_find); | ||
654 | EXPORT_SYMBOL(snd_seq_instr_free_use); | ||
655 | EXPORT_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: |