1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * OSS compatible sequencer driver
7 * Copyright (C) 1998,99 Takashi Iwai <tiwai@suse.de>
10 #include <sound/asoundef.h>
11 #include "seq_oss_midi.h"
12 #include "seq_oss_readq.h"
13 #include "seq_oss_timer.h"
14 #include "seq_oss_event.h"
15 #include <sound/seq_midi_event.h>
16 #include "../seq_lock.h"
17 #include <linux/init.h>
18 #include <linux/slab.h>
19 #include <linux/nospec.h>
25 #define SNDRV_SEQ_OSS_MAX_MIDI_NAME 30
28 * definition of midi device record
31 int seq_device; /* device number */
32 int client; /* sequencer client number */
33 int port; /* sequencer port number */
34 unsigned int flags; /* port capability */
35 int opened; /* flag for opening */
36 unsigned char name[SNDRV_SEQ_OSS_MAX_MIDI_NAME];
37 struct snd_midi_event *coder; /* MIDI event coder */
38 struct seq_oss_devinfo *devinfo; /* assigned OSSseq device */
39 snd_use_lock_t use_lock;
40 struct mutex open_mutex;
47 static int max_midi_devs;
48 static struct seq_oss_midi *midi_devs[SNDRV_SEQ_OSS_MAX_MIDI_DEVS];
50 static DEFINE_SPINLOCK(register_lock);
55 static struct seq_oss_midi *get_mdev(int dev);
56 static struct seq_oss_midi *get_mididev(struct seq_oss_devinfo *dp, int dev);
57 static int send_synth_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, int dev);
58 static int send_midi_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, struct seq_oss_midi *mdev);
61 * look up the existing ports
62 * this looks a very exhausting job.
65 snd_seq_oss_midi_lookup_ports(int client)
67 struct snd_seq_client_info *clinfo;
68 struct snd_seq_port_info *pinfo;
70 clinfo = kzalloc(sizeof(*clinfo), GFP_KERNEL);
71 pinfo = kzalloc(sizeof(*pinfo), GFP_KERNEL);
72 if (! clinfo || ! pinfo) {
78 while (snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT, clinfo) == 0) {
79 if (clinfo->client == client)
80 continue; /* ignore myself */
81 pinfo->addr.client = clinfo->client;
82 pinfo->addr.port = -1;
83 while (snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT, pinfo) == 0)
84 snd_seq_oss_midi_check_new_port(pinfo);
94 static struct seq_oss_midi *
97 struct seq_oss_midi *mdev;
100 spin_lock_irqsave(®ister_lock, flags);
101 mdev = midi_devs[dev];
103 snd_use_lock_use(&mdev->use_lock);
104 spin_unlock_irqrestore(®ister_lock, flags);
109 * look for the identical slot
111 static struct seq_oss_midi *
112 find_slot(int client, int port)
115 struct seq_oss_midi *mdev;
118 spin_lock_irqsave(®ister_lock, flags);
119 for (i = 0; i < max_midi_devs; i++) {
121 if (mdev && mdev->client == client && mdev->port == port) {
123 snd_use_lock_use(&mdev->use_lock);
124 spin_unlock_irqrestore(®ister_lock, flags);
128 spin_unlock_irqrestore(®ister_lock, flags);
133 #define PERM_WRITE (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_SUBS_WRITE)
134 #define PERM_READ (SNDRV_SEQ_PORT_CAP_READ|SNDRV_SEQ_PORT_CAP_SUBS_READ)
136 * register a new port if it doesn't exist yet
139 snd_seq_oss_midi_check_new_port(struct snd_seq_port_info *pinfo)
142 struct seq_oss_midi *mdev;
145 /* the port must include generic midi */
146 if (! (pinfo->type & SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC))
148 /* either read or write subscribable */
149 if ((pinfo->capability & PERM_WRITE) != PERM_WRITE &&
150 (pinfo->capability & PERM_READ) != PERM_READ)
154 * look for the identical slot
156 mdev = find_slot(pinfo->addr.client, pinfo->addr.port);
159 snd_use_lock_free(&mdev->use_lock);
164 * allocate midi info record
166 mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
170 /* copy the port information */
171 mdev->client = pinfo->addr.client;
172 mdev->port = pinfo->addr.port;
173 mdev->flags = pinfo->capability;
175 snd_use_lock_init(&mdev->use_lock);
176 mutex_init(&mdev->open_mutex);
178 /* copy and truncate the name of synth device */
179 strscpy(mdev->name, pinfo->name, sizeof(mdev->name));
181 /* create MIDI coder */
182 if (snd_midi_event_new(MAX_MIDI_EVENT_BUF, &mdev->coder) < 0) {
183 pr_err("ALSA: seq_oss: can't malloc midi coder\n");
187 /* OSS sequencer adds running status to all sequences */
188 snd_midi_event_no_status(mdev->coder, 1);
191 * look for en empty slot
193 spin_lock_irqsave(®ister_lock, flags);
194 for (i = 0; i < max_midi_devs; i++) {
195 if (midi_devs[i] == NULL)
198 if (i >= max_midi_devs) {
199 if (max_midi_devs >= SNDRV_SEQ_OSS_MAX_MIDI_DEVS) {
200 spin_unlock_irqrestore(®ister_lock, flags);
201 snd_midi_event_free(mdev->coder);
207 mdev->seq_device = i;
208 midi_devs[mdev->seq_device] = mdev;
209 spin_unlock_irqrestore(®ister_lock, flags);
215 * release the midi device if it was registered
218 snd_seq_oss_midi_check_exit_port(int client, int port)
220 struct seq_oss_midi *mdev;
224 mdev = find_slot(client, port);
226 spin_lock_irqsave(®ister_lock, flags);
227 midi_devs[mdev->seq_device] = NULL;
228 spin_unlock_irqrestore(®ister_lock, flags);
229 snd_use_lock_free(&mdev->use_lock);
230 snd_use_lock_sync(&mdev->use_lock);
231 snd_midi_event_free(mdev->coder);
234 spin_lock_irqsave(®ister_lock, flags);
235 for (index = max_midi_devs - 1; index >= 0; index--) {
236 if (midi_devs[index])
239 max_midi_devs = index + 1;
240 spin_unlock_irqrestore(®ister_lock, flags);
246 * release the midi device if it was registered
249 snd_seq_oss_midi_clear_all(void)
252 struct seq_oss_midi *mdev;
255 spin_lock_irqsave(®ister_lock, flags);
256 for (i = 0; i < max_midi_devs; i++) {
259 snd_midi_event_free(mdev->coder);
265 spin_unlock_irqrestore(®ister_lock, flags);
273 snd_seq_oss_midi_setup(struct seq_oss_devinfo *dp)
275 spin_lock_irq(®ister_lock);
276 dp->max_mididev = max_midi_devs;
277 spin_unlock_irq(®ister_lock);
281 * clean up midi tables
284 snd_seq_oss_midi_cleanup(struct seq_oss_devinfo *dp)
287 for (i = 0; i < dp->max_mididev; i++)
288 snd_seq_oss_midi_close(dp, i);
294 * open all midi devices. ignore errors.
297 snd_seq_oss_midi_open_all(struct seq_oss_devinfo *dp, int file_mode)
300 for (i = 0; i < dp->max_mididev; i++)
301 snd_seq_oss_midi_open(dp, i, file_mode);
306 * get the midi device information
308 static struct seq_oss_midi *
309 get_mididev(struct seq_oss_devinfo *dp, int dev)
311 if (dev < 0 || dev >= dp->max_mididev)
313 dev = array_index_nospec(dev, dp->max_mididev);
314 return get_mdev(dev);
319 * open the midi device if not opened yet
322 snd_seq_oss_midi_open(struct seq_oss_devinfo *dp, int dev, int fmode)
325 struct seq_oss_midi *mdev;
326 struct snd_seq_port_subscribe subs;
329 mdev = get_mididev(dp, dev);
333 mutex_lock(&mdev->open_mutex);
335 if (mdev->opened && mdev->devinfo != dp) {
341 if (is_write_mode(fmode))
343 if (is_read_mode(fmode))
351 /* already opened? */
352 if ((mdev->opened & perm) == perm) {
357 perm &= ~mdev->opened;
359 memset(&subs, 0, sizeof(subs));
361 if (perm & PERM_WRITE) {
362 subs.sender = dp->addr;
363 subs.dest.client = mdev->client;
364 subs.dest.port = mdev->port;
365 if (snd_seq_kernel_client_ctl(dp->cseq, SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, &subs) >= 0)
366 mdev->opened |= PERM_WRITE;
368 if (perm & PERM_READ) {
369 subs.sender.client = mdev->client;
370 subs.sender.port = mdev->port;
371 subs.dest = dp->addr;
372 subs.flags = SNDRV_SEQ_PORT_SUBS_TIMESTAMP;
373 subs.queue = dp->queue; /* queue for timestamps */
374 if (snd_seq_kernel_client_ctl(dp->cseq, SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, &subs) >= 0)
375 mdev->opened |= PERM_READ;
378 if (! mdev->opened) {
387 mutex_unlock(&mdev->open_mutex);
388 snd_use_lock_free(&mdev->use_lock);
393 * close the midi device if already opened
396 snd_seq_oss_midi_close(struct seq_oss_devinfo *dp, int dev)
398 struct seq_oss_midi *mdev;
399 struct snd_seq_port_subscribe subs;
401 mdev = get_mididev(dp, dev);
404 mutex_lock(&mdev->open_mutex);
405 if (!mdev->opened || mdev->devinfo != dp)
408 memset(&subs, 0, sizeof(subs));
409 if (mdev->opened & PERM_WRITE) {
410 subs.sender = dp->addr;
411 subs.dest.client = mdev->client;
412 subs.dest.port = mdev->port;
413 snd_seq_kernel_client_ctl(dp->cseq, SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT, &subs);
415 if (mdev->opened & PERM_READ) {
416 subs.sender.client = mdev->client;
417 subs.sender.port = mdev->port;
418 subs.dest = dp->addr;
419 snd_seq_kernel_client_ctl(dp->cseq, SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT, &subs);
423 mdev->devinfo = NULL;
426 mutex_unlock(&mdev->open_mutex);
427 snd_use_lock_free(&mdev->use_lock);
432 * change seq capability flags to file mode flags
435 snd_seq_oss_midi_filemode(struct seq_oss_devinfo *dp, int dev)
437 struct seq_oss_midi *mdev;
440 mdev = get_mididev(dp, dev);
445 if (mdev->opened & PERM_WRITE)
446 mode |= SNDRV_SEQ_OSS_FILE_WRITE;
447 if (mdev->opened & PERM_READ)
448 mode |= SNDRV_SEQ_OSS_FILE_READ;
450 snd_use_lock_free(&mdev->use_lock);
455 * reset the midi device and close it:
456 * so far, only close the device.
459 snd_seq_oss_midi_reset(struct seq_oss_devinfo *dp, int dev)
461 struct seq_oss_midi *mdev;
463 mdev = get_mididev(dp, dev);
466 if (! mdev->opened) {
467 snd_use_lock_free(&mdev->use_lock);
471 if (mdev->opened & PERM_WRITE) {
472 struct snd_seq_event ev;
475 memset(&ev, 0, sizeof(ev));
476 ev.dest.client = mdev->client;
477 ev.dest.port = mdev->port;
478 ev.queue = dp->queue;
479 ev.source.port = dp->port;
480 if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_SYNTH) {
481 ev.type = SNDRV_SEQ_EVENT_SENSING;
482 snd_seq_oss_dispatch(dp, &ev, 0, 0);
484 for (c = 0; c < 16; c++) {
485 ev.type = SNDRV_SEQ_EVENT_CONTROLLER;
486 ev.data.control.channel = c;
487 ev.data.control.param = MIDI_CTL_ALL_NOTES_OFF;
488 snd_seq_oss_dispatch(dp, &ev, 0, 0);
489 if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC) {
490 ev.data.control.param =
491 MIDI_CTL_RESET_CONTROLLERS;
492 snd_seq_oss_dispatch(dp, &ev, 0, 0);
493 ev.type = SNDRV_SEQ_EVENT_PITCHBEND;
494 ev.data.control.value = 0;
495 snd_seq_oss_dispatch(dp, &ev, 0, 0);
499 // snd_seq_oss_midi_close(dp, dev);
500 snd_use_lock_free(&mdev->use_lock);
505 * get client/port of the specified MIDI device
508 snd_seq_oss_midi_get_addr(struct seq_oss_devinfo *dp, int dev, struct snd_seq_addr *addr)
510 struct seq_oss_midi *mdev;
512 mdev = get_mididev(dp, dev);
515 addr->client = mdev->client;
516 addr->port = mdev->port;
517 snd_use_lock_free(&mdev->use_lock);
522 * input callback - this can be atomic
525 snd_seq_oss_midi_input(struct snd_seq_event *ev, int direct, void *private_data)
527 struct seq_oss_devinfo *dp = (struct seq_oss_devinfo *)private_data;
528 struct seq_oss_midi *mdev;
531 if (dp->readq == NULL)
533 mdev = find_slot(ev->source.client, ev->source.port);
536 if (! (mdev->opened & PERM_READ)) {
537 snd_use_lock_free(&mdev->use_lock);
541 if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC)
542 rc = send_synth_event(dp, ev, mdev->seq_device);
544 rc = send_midi_event(dp, ev, mdev);
546 snd_use_lock_free(&mdev->use_lock);
551 * convert ALSA sequencer event to OSS synth event
554 send_synth_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, int dev)
558 memset(&ossev, 0, sizeof(ossev));
561 case SNDRV_SEQ_EVENT_NOTEON:
562 ossev.v.cmd = MIDI_NOTEON; break;
563 case SNDRV_SEQ_EVENT_NOTEOFF:
564 ossev.v.cmd = MIDI_NOTEOFF; break;
565 case SNDRV_SEQ_EVENT_KEYPRESS:
566 ossev.v.cmd = MIDI_KEY_PRESSURE; break;
567 case SNDRV_SEQ_EVENT_CONTROLLER:
568 ossev.l.cmd = MIDI_CTL_CHANGE; break;
569 case SNDRV_SEQ_EVENT_PGMCHANGE:
570 ossev.l.cmd = MIDI_PGM_CHANGE; break;
571 case SNDRV_SEQ_EVENT_CHANPRESS:
572 ossev.l.cmd = MIDI_CHN_PRESSURE; break;
573 case SNDRV_SEQ_EVENT_PITCHBEND:
574 ossev.l.cmd = MIDI_PITCH_BEND; break;
576 return 0; /* not supported */
582 case SNDRV_SEQ_EVENT_NOTEON:
583 case SNDRV_SEQ_EVENT_NOTEOFF:
584 case SNDRV_SEQ_EVENT_KEYPRESS:
585 ossev.v.code = EV_CHN_VOICE;
586 ossev.v.note = ev->data.note.note;
587 ossev.v.parm = ev->data.note.velocity;
588 ossev.v.chn = ev->data.note.channel;
590 case SNDRV_SEQ_EVENT_CONTROLLER:
591 case SNDRV_SEQ_EVENT_PGMCHANGE:
592 case SNDRV_SEQ_EVENT_CHANPRESS:
593 ossev.l.code = EV_CHN_COMMON;
594 ossev.l.p1 = ev->data.control.param;
595 ossev.l.val = ev->data.control.value;
596 ossev.l.chn = ev->data.control.channel;
598 case SNDRV_SEQ_EVENT_PITCHBEND:
599 ossev.l.code = EV_CHN_COMMON;
600 ossev.l.val = ev->data.control.value + 8192;
601 ossev.l.chn = ev->data.control.channel;
605 snd_seq_oss_readq_put_timestamp(dp->readq, ev->time.tick, dp->seq_mode);
606 snd_seq_oss_readq_put_event(dp->readq, &ossev);
612 * decode event and send MIDI bytes to read queue
615 send_midi_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, struct seq_oss_midi *mdev)
620 snd_seq_oss_readq_put_timestamp(dp->readq, ev->time.tick, dp->seq_mode);
621 if (!dp->timer->running)
622 len = snd_seq_oss_timer_start(dp->timer);
623 if (ev->type == SNDRV_SEQ_EVENT_SYSEX) {
624 snd_seq_oss_readq_sysex(dp->readq, mdev->seq_device, ev);
625 snd_midi_event_reset_decode(mdev->coder);
627 len = snd_midi_event_decode(mdev->coder, msg, sizeof(msg), ev);
629 snd_seq_oss_readq_puts(dp->readq, mdev->seq_device, msg, len);
638 * return 0 : enqueued
639 * non-zero : invalid - ignored
642 snd_seq_oss_midi_putc(struct seq_oss_devinfo *dp, int dev, unsigned char c, struct snd_seq_event *ev)
644 struct seq_oss_midi *mdev;
646 mdev = get_mididev(dp, dev);
649 if (snd_midi_event_encode_byte(mdev->coder, c, ev)) {
650 snd_seq_oss_fill_addr(dp, ev, mdev->client, mdev->port);
651 snd_use_lock_free(&mdev->use_lock);
654 snd_use_lock_free(&mdev->use_lock);
659 * create OSS compatible midi_info record
662 snd_seq_oss_midi_make_info(struct seq_oss_devinfo *dp, int dev, struct midi_info *inf)
664 struct seq_oss_midi *mdev;
666 mdev = get_mididev(dp, dev);
670 inf->dev_type = 0; /* FIXME: ?? */
671 inf->capabilities = 0; /* FIXME: ?? */
672 strscpy(inf->name, mdev->name, sizeof(inf->name));
673 snd_use_lock_free(&mdev->use_lock);
678 #ifdef CONFIG_SND_PROC_FS
685 val &= PERM_READ|PERM_WRITE;
686 if (val == (PERM_READ|PERM_WRITE))
688 else if (val == PERM_READ)
690 else if (val == PERM_WRITE)
697 snd_seq_oss_midi_info_read(struct snd_info_buffer *buf)
700 struct seq_oss_midi *mdev;
702 snd_iprintf(buf, "\nNumber of MIDI devices: %d\n", max_midi_devs);
703 for (i = 0; i < max_midi_devs; i++) {
704 snd_iprintf(buf, "\nmidi %d: ", i);
707 snd_iprintf(buf, "*empty*\n");
710 snd_iprintf(buf, "[%s] ALSA port %d:%d\n", mdev->name,
711 mdev->client, mdev->port);
712 snd_iprintf(buf, " capability %s / opened %s\n",
713 capmode_str(mdev->flags),
714 capmode_str(mdev->opened));
715 snd_use_lock_free(&mdev->use_lock);
718 #endif /* CONFIG_SND_PROC_FS */