2 * GF1 (GUS) Patch - Instrument routines
3 * Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz>
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.
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.
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
21 #include <sound/driver.h>
22 #include <linux/init.h>
23 #include <linux/sched.h>
24 #include <linux/slab.h>
25 #include <sound/core.h>
26 #include <sound/ainstr_gf1.h>
27 #include <sound/initval.h>
28 #include <asm/uaccess.h>
30 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
31 MODULE_DESCRIPTION("Advanced Linux Sound Architecture GF1 (GUS) Patch support.");
32 MODULE_LICENSE("GPL");
34 static unsigned int snd_seq_gf1_size(unsigned int size
, unsigned int format
)
36 unsigned int result
= size
;
38 if (format
& GF1_WAVE_16BIT
)
40 if (format
& GF1_WAVE_STEREO
)
45 static int snd_seq_gf1_copy_wave_from_stream(snd_gf1_ops_t
*ops
,
51 gf1_wave_t
*wp
, *prev
;
54 unsigned int gfp_mask
;
55 unsigned int real_size
;
57 gfp_mask
= atomic
? GFP_ATOMIC
: GFP_KERNEL
;
58 if (*len
< (long)sizeof(xp
))
60 if (copy_from_user(&xp
, *data
, sizeof(xp
)))
64 wp
= kcalloc(1, sizeof(*wp
), gfp_mask
);
67 wp
->share_id
[0] = le32_to_cpu(xp
.share_id
[0]);
68 wp
->share_id
[1] = le32_to_cpu(xp
.share_id
[1]);
69 wp
->share_id
[2] = le32_to_cpu(xp
.share_id
[2]);
70 wp
->share_id
[3] = le32_to_cpu(xp
.share_id
[3]);
71 wp
->format
= le32_to_cpu(xp
.format
);
72 wp
->size
= le32_to_cpu(xp
.size
);
73 wp
->start
= le32_to_cpu(xp
.start
);
74 wp
->loop_start
= le32_to_cpu(xp
.loop_start
);
75 wp
->loop_end
= le32_to_cpu(xp
.loop_end
);
76 wp
->loop_repeat
= le16_to_cpu(xp
.loop_repeat
);
78 wp
->sample_rate
= le32_to_cpu(xp
.sample_rate
);
79 wp
->low_frequency
= le32_to_cpu(xp
.low_frequency
);
80 wp
->high_frequency
= le32_to_cpu(xp
.high_frequency
);
81 wp
->root_frequency
= le32_to_cpu(xp
.root_frequency
);
82 wp
->tune
= le16_to_cpu(xp
.tune
);
83 wp
->balance
= xp
.balance
;
84 memcpy(wp
->envelope_rate
, xp
.envelope_rate
, 6);
85 memcpy(wp
->envelope_offset
, xp
.envelope_offset
, 6);
86 wp
->tremolo_sweep
= xp
.tremolo_sweep
;
87 wp
->tremolo_rate
= xp
.tremolo_rate
;
88 wp
->tremolo_depth
= xp
.tremolo_depth
;
89 wp
->vibrato_sweep
= xp
.vibrato_sweep
;
90 wp
->vibrato_rate
= xp
.vibrato_rate
;
91 wp
->vibrato_depth
= xp
.vibrato_depth
;
92 wp
->scale_frequency
= le16_to_cpu(xp
.scale_frequency
);
93 wp
->scale_factor
= le16_to_cpu(xp
.scale_factor
);
94 real_size
= snd_seq_gf1_size(wp
->size
, wp
->format
);
95 if ((long)real_size
> *len
) {
99 if (ops
->put_sample
) {
100 err
= ops
->put_sample(ops
->private_data
, wp
,
101 *data
, real_size
, atomic
);
111 while (prev
->next
) prev
= prev
->next
;
119 static void snd_seq_gf1_wave_free(snd_gf1_ops_t
*ops
,
123 if (ops
->remove_sample
)
124 ops
->remove_sample(ops
->private_data
, wave
, atomic
);
128 static void snd_seq_gf1_instr_free(snd_gf1_ops_t
*ops
,
129 gf1_instrument_t
*ip
,
134 while ((wave
= ip
->wave
) != NULL
) {
135 ip
->wave
= wave
->next
;
136 snd_seq_gf1_wave_free(ops
, wave
, atomic
);
140 static int snd_seq_gf1_put(void *private_data
, snd_seq_kinstr_t
*instr
,
141 char __user
*instr_data
, long len
, int atomic
,
144 snd_gf1_ops_t
*ops
= (snd_gf1_ops_t
*)private_data
;
145 gf1_instrument_t
*ip
;
146 gf1_xinstrument_t ix
;
149 if (cmd
!= SNDRV_SEQ_INSTR_PUT_CMD_CREATE
)
151 gfp_mask
= atomic
? GFP_ATOMIC
: GFP_KERNEL
;
152 /* copy instrument data */
153 if (len
< (long)sizeof(ix
))
155 if (copy_from_user(&ix
, instr_data
, sizeof(ix
)))
157 if (ix
.stype
!= GF1_STRU_INSTR
)
159 instr_data
+= sizeof(ix
);
161 ip
= (gf1_instrument_t
*)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
;
169 while (len
> (long)sizeof(__u32
)) {
172 if (copy_from_user(&stype
, instr_data
, sizeof(stype
)))
174 if (stype
!= GF1_STRU_WAVE
) {
175 snd_seq_gf1_instr_free(ops
, ip
, atomic
);
178 err
= snd_seq_gf1_copy_wave_from_stream(ops
,
184 snd_seq_gf1_instr_free(ops
, ip
, atomic
);
191 static int snd_seq_gf1_copy_wave_to_stream(snd_gf1_ops_t
*ops
,
192 gf1_instrument_t
*ip
,
200 unsigned int real_size
;
202 for (wp
= ip
->wave
; wp
; wp
= wp
->next
) {
203 if (*len
< (long)sizeof(xp
))
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
)))
238 real_size
= snd_seq_gf1_size(wp
->size
, wp
->format
);
239 if (*len
< (long)real_size
)
241 if (ops
->get_sample
) {
242 err
= ops
->get_sample(ops
->private_data
, wp
,
243 *data
, real_size
, atomic
);
253 static int snd_seq_gf1_get(void *private_data
, snd_seq_kinstr_t
*instr
,
254 char __user
*instr_data
, long len
, int atomic
,
257 snd_gf1_ops_t
*ops
= (snd_gf1_ops_t
*)private_data
;
258 gf1_instrument_t
*ip
;
259 gf1_xinstrument_t ix
;
261 if (cmd
!= SNDRV_SEQ_INSTR_GET_CMD_FULL
)
263 if (len
< (long)sizeof(ix
))
265 memset(&ix
, 0, sizeof(ix
));
266 ip
= (gf1_instrument_t
*)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
)))
276 instr_data
+= sizeof(ix
);
278 return snd_seq_gf1_copy_wave_to_stream(ops
,
285 static int snd_seq_gf1_get_size(void *private_data
, snd_seq_kinstr_t
*instr
,
289 gf1_instrument_t
*ip
;
293 ip
= (gf1_instrument_t
*)KINSTR_DATA(instr
);
294 result
= sizeof(gf1_xinstrument_t
);
295 for (wp
= ip
->wave
; wp
; wp
= wp
->next
) {
296 result
+= sizeof(gf1_xwave_t
);
303 static int snd_seq_gf1_remove(void *private_data
,
304 snd_seq_kinstr_t
*instr
,
307 snd_gf1_ops_t
*ops
= (snd_gf1_ops_t
*)private_data
;
308 gf1_instrument_t
*ip
;
310 ip
= (gf1_instrument_t
*)KINSTR_DATA(instr
);
311 snd_seq_gf1_instr_free(ops
, ip
, atomic
);
315 static void snd_seq_gf1_notify(void *private_data
,
316 snd_seq_kinstr_t
*instr
,
319 snd_gf1_ops_t
*ops
= (snd_gf1_ops_t
*)private_data
;
322 ops
->notify(ops
->private_data
, instr
, what
);
325 int snd_seq_gf1_init(snd_gf1_ops_t
*ops
,
327 snd_seq_kinstr_ops_t
*next
)
329 memset(ops
, 0, sizeof(*ops
));
330 ops
->private_data
= private_data
;
331 ops
->kops
.private_data
= ops
;
332 ops
->kops
.add_len
= sizeof(gf1_instrument_t
);
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
;
347 static int __init
alsa_ainstr_gf1_init(void)
352 static void __exit
alsa_ainstr_gf1_exit(void)
356 module_init(alsa_ainstr_gf1_init
)
357 module_exit(alsa_ainstr_gf1_exit
)
359 EXPORT_SYMBOL(snd_seq_gf1_init
);