1/*
2 * OSS compatible sequencer driver
3 *
4 * synth device handlers
5 *
6 * Copyright (C) 1998,99 Takashi Iwai <tiwai@suse.de>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
21 */
22
23#include "seq_oss_synth.h"
24#include "seq_oss_midi.h"
25#include "../seq_lock.h"
26#include <linux/init.h>
27
28/*
29 * constants
30 */
31#define SNDRV_SEQ_OSS_MAX_SYNTH_NAME	30
32#define MAX_SYSEX_BUFLEN		128
33
34
35/*
36 * definition of synth info records
37 */
38
39/* sysex buffer */
40struct seq_oss_synth_sysex {
41	int len;
42	int skip;
43	unsigned char buf[MAX_SYSEX_BUFLEN];
44};
45
46/* synth info */
47struct seq_oss_synth {
48	int seq_device;
49
50	/* for synth_info */
51	int synth_type;
52	int synth_subtype;
53	int nr_voices;
54
55	char name[SNDRV_SEQ_OSS_MAX_SYNTH_NAME];
56	struct snd_seq_oss_callback oper;
57
58	int opened;
59
60	void *private_data;
61	snd_use_lock_t use_lock;
62};
63
64
65/*
66 * device table
67 */
68static int max_synth_devs;
69static struct seq_oss_synth *synth_devs[SNDRV_SEQ_OSS_MAX_SYNTH_DEVS];
70static struct seq_oss_synth midi_synth_dev = {
71	-1, /* seq_device */
72	SYNTH_TYPE_MIDI, /* synth_type */
73	0, /* synth_subtype */
74	16, /* nr_voices */
75	"MIDI", /* name */
76};
77
78static DEFINE_SPINLOCK(register_lock);
79
80/*
81 * prototypes
82 */
83static struct seq_oss_synth *get_synthdev(struct seq_oss_devinfo *dp, int dev);
84static void reset_channels(struct seq_oss_synthinfo *info);
85
86/*
87 * global initialization
88 */
89void __init
90snd_seq_oss_synth_init(void)
91{
92	snd_use_lock_init(&midi_synth_dev.use_lock);
93}
94
95/*
96 * registration of the synth device
97 */
98int
99snd_seq_oss_synth_register(struct snd_seq_device *dev)
100{
101	int i;
102	struct seq_oss_synth *rec;
103	struct snd_seq_oss_reg *reg = SNDRV_SEQ_DEVICE_ARGPTR(dev);
104	unsigned long flags;
105
106	if ((rec = kzalloc(sizeof(*rec), GFP_KERNEL)) == NULL) {
107		snd_printk(KERN_ERR "can't malloc synth info\n");
108		return -ENOMEM;
109	}
110	rec->seq_device = -1;
111	rec->synth_type = reg->type;
112	rec->synth_subtype = reg->subtype;
113	rec->nr_voices = reg->nvoices;
114	rec->oper = reg->oper;
115	rec->private_data = reg->private_data;
116	rec->opened = 0;
117	snd_use_lock_init(&rec->use_lock);
118
119	/* copy and truncate the name of synth device */
120	strlcpy(rec->name, dev->name, sizeof(rec->name));
121
122	/* registration */
123	spin_lock_irqsave(&register_lock, flags);
124	for (i = 0; i < max_synth_devs; i++) {
125		if (synth_devs[i] == NULL)
126			break;
127	}
128	if (i >= max_synth_devs) {
129		if (max_synth_devs >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS) {
130			spin_unlock_irqrestore(&register_lock, flags);
131			snd_printk(KERN_ERR "no more synth slot\n");
132			kfree(rec);
133			return -ENOMEM;
134		}
135		max_synth_devs++;
136	}
137	rec->seq_device = i;
138	synth_devs[i] = rec;
139	debug_printk(("synth %s registered %d\n", rec->name, i));
140	spin_unlock_irqrestore(&register_lock, flags);
141	dev->driver_data = rec;
142#ifdef SNDRV_OSS_INFO_DEV_SYNTH
143	if (i < SNDRV_CARDS)
144		snd_oss_info_register(SNDRV_OSS_INFO_DEV_SYNTH, i, rec->name);
145#endif
146	return 0;
147}
148
149
150int
151snd_seq_oss_synth_unregister(struct snd_seq_device *dev)
152{
153	int index;
154	struct seq_oss_synth *rec = dev->driver_data;
155	unsigned long flags;
156
157	spin_lock_irqsave(&register_lock, flags);
158	for (index = 0; index < max_synth_devs; index++) {
159		if (synth_devs[index] == rec)
160			break;
161	}
162	if (index >= max_synth_devs) {
163		spin_unlock_irqrestore(&register_lock, flags);
164		snd_printk(KERN_ERR "can't unregister synth\n");
165		return -EINVAL;
166	}
167	synth_devs[index] = NULL;
168	if (index == max_synth_devs - 1) {
169		for (index--; index >= 0; index--) {
170			if (synth_devs[index])
171				break;
172		}
173		max_synth_devs = index + 1;
174	}
175	spin_unlock_irqrestore(&register_lock, flags);
176#ifdef SNDRV_OSS_INFO_DEV_SYNTH
177	if (rec->seq_device < SNDRV_CARDS)
178		snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_SYNTH, rec->seq_device);
179#endif
180
181	snd_use_lock_sync(&rec->use_lock);
182	kfree(rec);
183
184	return 0;
185}
186
187
188/*
189 */
190static struct seq_oss_synth *
191get_sdev(int dev)
192{
193	struct seq_oss_synth *rec;
194	unsigned long flags;
195
196	spin_lock_irqsave(&register_lock, flags);
197	rec = synth_devs[dev];
198	if (rec)
199		snd_use_lock_use(&rec->use_lock);
200	spin_unlock_irqrestore(&register_lock, flags);
201	return rec;
202}
203
204
205/*
206 * set up synth tables
207 */
208
209void
210snd_seq_oss_synth_setup(struct seq_oss_devinfo *dp)
211{
212	int i;
213	struct seq_oss_synth *rec;
214	struct seq_oss_synthinfo *info;
215
216	dp->max_synthdev = max_synth_devs;
217	dp->synth_opened = 0;
218	memset(dp->synths, 0, sizeof(dp->synths));
219	for (i = 0; i < dp->max_synthdev; i++) {
220		rec = get_sdev(i);
221		if (rec == NULL)
222			continue;
223		if (rec->oper.open == NULL || rec->oper.close == NULL) {
224			snd_use_lock_free(&rec->use_lock);
225			continue;
226		}
227		info = &dp->synths[i];
228		info->arg.app_index = dp->port;
229		info->arg.file_mode = dp->file_mode;
230		info->arg.seq_mode = dp->seq_mode;
231		if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_SYNTH)
232			info->arg.event_passing = SNDRV_SEQ_OSS_PROCESS_EVENTS;
233		else
234			info->arg.event_passing = SNDRV_SEQ_OSS_PASS_EVENTS;
235		info->opened = 0;
236		if (!try_module_get(rec->oper.owner)) {
237			snd_use_lock_free(&rec->use_lock);
238			continue;
239		}
240		if (rec->oper.open(&info->arg, rec->private_data) < 0) {
241			module_put(rec->oper.owner);
242			snd_use_lock_free(&rec->use_lock);
243			continue;
244		}
245		info->nr_voices = rec->nr_voices;
246		if (info->nr_voices > 0) {
247			info->ch = kcalloc(info->nr_voices, sizeof(struct seq_oss_chinfo), GFP_KERNEL);
248			if (!info->ch)
249				BUG();
250			reset_channels(info);
251		}
252		debug_printk(("synth %d assigned\n", i));
253		info->opened++;
254		rec->opened++;
255		dp->synth_opened++;
256		snd_use_lock_free(&rec->use_lock);
257	}
258}
259
260
261/*
262 * set up synth tables for MIDI emulation - /dev/music mode only
263 */
264
265void
266snd_seq_oss_synth_setup_midi(struct seq_oss_devinfo *dp)
267{
268	int i;
269
270	if (dp->max_synthdev >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS)
271		return;
272
273	for (i = 0; i < dp->max_mididev; i++) {
274		struct seq_oss_synthinfo *info;
275		info = &dp->synths[dp->max_synthdev];
276		if (snd_seq_oss_midi_open(dp, i, dp->file_mode) < 0)
277			continue;
278		info->arg.app_index = dp->port;
279		info->arg.file_mode = dp->file_mode;
280		info->arg.seq_mode = dp->seq_mode;
281		info->arg.private_data = info;
282		info->is_midi = 1;
283		info->midi_mapped = i;
284		info->arg.event_passing = SNDRV_SEQ_OSS_PASS_EVENTS;
285		snd_seq_oss_midi_get_addr(dp, i, &info->arg.addr);
286		info->opened = 1;
287		midi_synth_dev.opened++;
288		dp->max_synthdev++;
289		if (dp->max_synthdev >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS)
290			break;
291	}
292}
293
294
295/*
296 * clean up synth tables
297 */
298
299void
300snd_seq_oss_synth_cleanup(struct seq_oss_devinfo *dp)
301{
302	int i;
303	struct seq_oss_synth *rec;
304	struct seq_oss_synthinfo *info;
305
306	snd_assert(dp->max_synthdev <= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS, return);
307	for (i = 0; i < dp->max_synthdev; i++) {
308		info = &dp->synths[i];
309		if (! info->opened)
310			continue;
311		if (info->is_midi) {
312			if (midi_synth_dev.opened > 0) {
313				snd_seq_oss_midi_close(dp, info->midi_mapped);
314				midi_synth_dev.opened--;
315			}
316		} else {
317			rec = get_sdev(i);
318			if (rec == NULL)
319				continue;
320			if (rec->opened > 0) {
321				debug_printk(("synth %d closed\n", i));
322				rec->oper.close(&info->arg);
323				module_put(rec->oper.owner);
324				rec->opened = 0;
325			}
326			snd_use_lock_free(&rec->use_lock);
327		}
328		kfree(info->sysex);
329		info->sysex = NULL;
330		kfree(info->ch);
331		info->ch = NULL;
332	}
333	dp->synth_opened = 0;
334	dp->max_synthdev = 0;
335}
336
337/*
338 * check if the specified device is MIDI mapped device
339 */
340static int
341is_midi_dev(struct seq_oss_devinfo *dp, int dev)
342{
343	if (dev < 0 || dev >= dp->max_synthdev)
344		return 0;
345	if (dp->synths[dev].is_midi)
346		return 1;
347	return 0;
348}
349
350/*
351 * return synth device information pointer
352 */
353static struct seq_oss_synth *
354get_synthdev(struct seq_oss_devinfo *dp, int dev)
355{
356	struct seq_oss_synth *rec;
357	if (dev < 0 || dev >= dp->max_synthdev)
358		return NULL;
359	if (! dp->synths[dev].opened)
360		return NULL;
361	if (dp->synths[dev].is_midi)
362		return &midi_synth_dev;
363	if ((rec = get_sdev(dev)) == NULL)
364		return NULL;
365	if (! rec->opened) {
366		snd_use_lock_free(&rec->use_lock);
367		return NULL;
368	}
369	return rec;
370}
371
372
373/*
374 * reset note and velocity on each channel.
375 */
376static void
377reset_channels(struct seq_oss_synthinfo *info)
378{
379	int i;
380	if (info->ch == NULL || ! info->nr_voices)
381		return;
382	for (i = 0; i < info->nr_voices; i++) {
383		info->ch[i].note = -1;
384		info->ch[i].vel = 0;
385	}
386}
387
388
389/*
390 * reset synth device:
391 * call reset callback.  if no callback is defined, send a heartbeat
392 * event to the corresponding port.
393 */
394void
395snd_seq_oss_synth_reset(struct seq_oss_devinfo *dp, int dev)
396{
397	struct seq_oss_synth *rec;
398	struct seq_oss_synthinfo *info;
399
400	snd_assert(dev >= 0 && dev < dp->max_synthdev, return);
401	info = &dp->synths[dev];
402	if (! info->opened)
403		return;
404	if (info->sysex)
405		info->sysex->len = 0; /* reset sysex */
406	reset_channels(info);
407	if (info->is_midi) {
408		if (midi_synth_dev.opened <= 0)
409			return;
410		snd_seq_oss_midi_reset(dp, info->midi_mapped);
411		/* reopen the device */
412		snd_seq_oss_midi_close(dp, dev);
413		if (snd_seq_oss_midi_open(dp, info->midi_mapped,
414					  dp->file_mode) < 0) {
415			midi_synth_dev.opened--;
416			info->opened = 0;
417			kfree(info->sysex);
418			info->sysex = NULL;
419			kfree(info->ch);
420			info->ch = NULL;
421		}
422		return;
423	}
424
425	rec = get_sdev(dev);
426	if (rec == NULL)
427		return;
428	if (rec->oper.reset) {
429		rec->oper.reset(&info->arg);
430	} else {
431		struct snd_seq_event ev;
432		memset(&ev, 0, sizeof(ev));
433		snd_seq_oss_fill_addr(dp, &ev, info->arg.addr.client,
434				      info->arg.addr.port);
435		ev.type = SNDRV_SEQ_EVENT_RESET;
436		snd_seq_oss_dispatch(dp, &ev, 0, 0);
437	}
438	snd_use_lock_free(&rec->use_lock);
439}
440
441
442/*
443 * load a patch record:
444 * call load_patch callback function
445 */
446int
447snd_seq_oss_synth_load_patch(struct seq_oss_devinfo *dp, int dev, int fmt,
448			    const char __user *buf, int p, int c)
449{
450	struct seq_oss_synth *rec;
451	int rc;
452
453	if (dev < 0 || dev >= dp->max_synthdev)
454		return -ENXIO;
455
456	if (is_midi_dev(dp, dev))
457		return 0;
458	if ((rec = get_synthdev(dp, dev)) == NULL)
459		return -ENXIO;
460
461	if (rec->oper.load_patch == NULL)
462		rc = -ENXIO;
463	else
464		rc = rec->oper.load_patch(&dp->synths[dev].arg, fmt, buf, p, c);
465	snd_use_lock_free(&rec->use_lock);
466	return rc;
467}
468
469/*
470 * check if the device is valid synth device
471 */
472int
473snd_seq_oss_synth_is_valid(struct seq_oss_devinfo *dp, int dev)
474{
475	struct seq_oss_synth *rec;
476	rec = get_synthdev(dp, dev);
477	if (rec) {
478		snd_use_lock_free(&rec->use_lock);
479		return 1;
480	}
481	return 0;
482}
483
484
485/*
486 * receive OSS 6 byte sysex packet:
487 * the full sysex message will be sent if it reaches to the end of data
488 * (0xff).
489 */
490int
491snd_seq_oss_synth_sysex(struct seq_oss_devinfo *dp, int dev, unsigned char *buf, struct snd_seq_event *ev)
492{
493	int i, send;
494	unsigned char *dest;
495	struct seq_oss_synth_sysex *sysex;
496
497	if (! snd_seq_oss_synth_is_valid(dp, dev))
498		return -ENXIO;
499
500	sysex = dp->synths[dev].sysex;
501	if (sysex == NULL) {
502		sysex = kzalloc(sizeof(*sysex), GFP_KERNEL);
503		if (sysex == NULL)
504			return -ENOMEM;
505		dp->synths[dev].sysex = sysex;
506	}
507
508	send = 0;
509	dest = sysex->buf + sysex->len;
510	/* copy 6 byte packet to the buffer */
511	for (i = 0; i < 6; i++) {
512		if (buf[i] == 0xff) {
513			send = 1;
514			break;
515		}
516		dest[i] = buf[i];
517		sysex->len++;
518		if (sysex->len >= MAX_SYSEX_BUFLEN) {
519			sysex->len = 0;
520			sysex->skip = 1;
521			break;
522		}
523	}
524
525	if (sysex->len && send) {
526		if (sysex->skip) {
527			sysex->skip = 0;
528			sysex->len = 0;
529			return -EINVAL; /* skip */
530		}
531		/* copy the data to event record and send it */
532		ev->flags = SNDRV_SEQ_EVENT_LENGTH_VARIABLE;
533		if (snd_seq_oss_synth_addr(dp, dev, ev))
534			return -EINVAL;
535		ev->data.ext.len = sysex->len;
536		ev->data.ext.ptr = sysex->buf;
537		sysex->len = 0;
538		return 0;
539	}
540
541	return -EINVAL; /* skip */
542}
543
544/*
545 * fill the event source/destination addresses
546 */
547int
548snd_seq_oss_synth_addr(struct seq_oss_devinfo *dp, int dev, struct snd_seq_event *ev)
549{
550	if (! snd_seq_oss_synth_is_valid(dp, dev))
551		return -EINVAL;
552	snd_seq_oss_fill_addr(dp, ev, dp->synths[dev].arg.addr.client,
553			      dp->synths[dev].arg.addr.port);
554	return 0;
555}
556
557
558/*
559 * OSS compatible ioctl
560 */
561int
562snd_seq_oss_synth_ioctl(struct seq_oss_devinfo *dp, int dev, unsigned int cmd, unsigned long addr)
563{
564	struct seq_oss_synth *rec;
565	int rc;
566
567	if (is_midi_dev(dp, dev))
568		return -ENXIO;
569	if ((rec = get_synthdev(dp, dev)) == NULL)
570		return -ENXIO;
571	if (rec->oper.ioctl == NULL)
572		rc = -ENXIO;
573	else
574		rc = rec->oper.ioctl(&dp->synths[dev].arg, cmd, addr);
575	snd_use_lock_free(&rec->use_lock);
576	return rc;
577}
578
579
580/*
581 * send OSS raw events - SEQ_PRIVATE and SEQ_VOLUME
582 */
583int
584snd_seq_oss_synth_raw_event(struct seq_oss_devinfo *dp, int dev, unsigned char *data, struct snd_seq_event *ev)
585{
586	if (! snd_seq_oss_synth_is_valid(dp, dev) || is_midi_dev(dp, dev))
587		return -ENXIO;
588	ev->type = SNDRV_SEQ_EVENT_OSS;
589	memcpy(ev->data.raw8.d, data, 8);
590	return snd_seq_oss_synth_addr(dp, dev, ev);
591}
592
593
594/*
595 * create OSS compatible synth_info record
596 */
597int
598snd_seq_oss_synth_make_info(struct seq_oss_devinfo *dp, int dev, struct synth_info *inf)
599{
600	struct seq_oss_synth *rec;
601
602	if (dp->synths[dev].is_midi) {
603		struct midi_info minf;
604		snd_seq_oss_midi_make_info(dp, dp->synths[dev].midi_mapped, &minf);
605		inf->synth_type = SYNTH_TYPE_MIDI;
606		inf->synth_subtype = 0;
607		inf->nr_voices = 16;
608		inf->device = dev;
609		strlcpy(inf->name, minf.name, sizeof(inf->name));
610	} else {
611		if ((rec = get_synthdev(dp, dev)) == NULL)
612			return -ENXIO;
613		inf->synth_type = rec->synth_type;
614		inf->synth_subtype = rec->synth_subtype;
615		inf->nr_voices = rec->nr_voices;
616		inf->device = dev;
617		strlcpy(inf->name, rec->name, sizeof(inf->name));
618		snd_use_lock_free(&rec->use_lock);
619	}
620	return 0;
621}
622
623
624#ifdef CONFIG_PROC_FS
625/*
626 * proc interface
627 */
628void
629snd_seq_oss_synth_info_read(struct snd_info_buffer *buf)
630{
631	int i;
632	struct seq_oss_synth *rec;
633
634	snd_iprintf(buf, "\nNumber of synth devices: %d\n", max_synth_devs);
635	for (i = 0; i < max_synth_devs; i++) {
636		snd_iprintf(buf, "\nsynth %d: ", i);
637		rec = get_sdev(i);
638		if (rec == NULL) {
639			snd_iprintf(buf, "*empty*\n");
640			continue;
641		}
642		snd_iprintf(buf, "[%s]\n", rec->name);
643		snd_iprintf(buf, "  type 0x%x : subtype 0x%x : voices %d\n",
644			    rec->synth_type, rec->synth_subtype,
645			    rec->nr_voices);
646		snd_iprintf(buf, "  capabilities : ioctl %s / load_patch %s\n",
647			    enabled_str((long)rec->oper.ioctl),
648			    enabled_str((long)rec->oper.load_patch));
649		snd_use_lock_free(&rec->use_lock);
650	}
651}
652#endif /* CONFIG_PROC_FS */
653