diff options
author | Takashi Iwai <tiwai@suse.de> | 2007-10-30 07:17:17 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@perex.cz> | 2008-01-31 11:29:13 -0500 |
commit | e5723b41abe559bafc52591dcf8ee19cc131d3a1 (patch) | |
tree | a1d035132ae1354c43eb9fccf60c9668e0abb266 /sound/core | |
parent | 05c1afe75fcebf456017ec186811cf1599f4360e (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/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: |