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