0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <sound/asoundef.h>
0011 #include "seq_oss_midi.h"
0012 #include "seq_oss_readq.h"
0013 #include "seq_oss_timer.h"
0014 #include "seq_oss_event.h"
0015 #include <sound/seq_midi_event.h>
0016 #include "../seq_lock.h"
0017 #include <linux/init.h>
0018 #include <linux/slab.h>
0019 #include <linux/nospec.h>
0020
0021
0022
0023
0024
0025 #define SNDRV_SEQ_OSS_MAX_MIDI_NAME 30
0026
0027
0028
0029
0030 struct seq_oss_midi {
0031 int seq_device;
0032 int client;
0033 int port;
0034 unsigned int flags;
0035 int opened;
0036 unsigned char name[SNDRV_SEQ_OSS_MAX_MIDI_NAME];
0037 struct snd_midi_event *coder;
0038 struct seq_oss_devinfo *devinfo;
0039 snd_use_lock_t use_lock;
0040 };
0041
0042
0043
0044
0045
0046 static int max_midi_devs;
0047 static struct seq_oss_midi *midi_devs[SNDRV_SEQ_OSS_MAX_MIDI_DEVS];
0048
0049 static DEFINE_SPINLOCK(register_lock);
0050
0051
0052
0053
0054 static struct seq_oss_midi *get_mdev(int dev);
0055 static struct seq_oss_midi *get_mididev(struct seq_oss_devinfo *dp, int dev);
0056 static int send_synth_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, int dev);
0057 static int send_midi_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, struct seq_oss_midi *mdev);
0058
0059
0060
0061
0062
0063 int
0064 snd_seq_oss_midi_lookup_ports(int client)
0065 {
0066 struct snd_seq_client_info *clinfo;
0067 struct snd_seq_port_info *pinfo;
0068
0069 clinfo = kzalloc(sizeof(*clinfo), GFP_KERNEL);
0070 pinfo = kzalloc(sizeof(*pinfo), GFP_KERNEL);
0071 if (! clinfo || ! pinfo) {
0072 kfree(clinfo);
0073 kfree(pinfo);
0074 return -ENOMEM;
0075 }
0076 clinfo->client = -1;
0077 while (snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT, clinfo) == 0) {
0078 if (clinfo->client == client)
0079 continue;
0080 pinfo->addr.client = clinfo->client;
0081 pinfo->addr.port = -1;
0082 while (snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT, pinfo) == 0)
0083 snd_seq_oss_midi_check_new_port(pinfo);
0084 }
0085 kfree(clinfo);
0086 kfree(pinfo);
0087 return 0;
0088 }
0089
0090
0091
0092
0093 static struct seq_oss_midi *
0094 get_mdev(int dev)
0095 {
0096 struct seq_oss_midi *mdev;
0097 unsigned long flags;
0098
0099 spin_lock_irqsave(®ister_lock, flags);
0100 mdev = midi_devs[dev];
0101 if (mdev)
0102 snd_use_lock_use(&mdev->use_lock);
0103 spin_unlock_irqrestore(®ister_lock, flags);
0104 return mdev;
0105 }
0106
0107
0108
0109
0110 static struct seq_oss_midi *
0111 find_slot(int client, int port)
0112 {
0113 int i;
0114 struct seq_oss_midi *mdev;
0115 unsigned long flags;
0116
0117 spin_lock_irqsave(®ister_lock, flags);
0118 for (i = 0; i < max_midi_devs; i++) {
0119 mdev = midi_devs[i];
0120 if (mdev && mdev->client == client && mdev->port == port) {
0121
0122 snd_use_lock_use(&mdev->use_lock);
0123 spin_unlock_irqrestore(®ister_lock, flags);
0124 return mdev;
0125 }
0126 }
0127 spin_unlock_irqrestore(®ister_lock, flags);
0128 return NULL;
0129 }
0130
0131
0132 #define PERM_WRITE (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_SUBS_WRITE)
0133 #define PERM_READ (SNDRV_SEQ_PORT_CAP_READ|SNDRV_SEQ_PORT_CAP_SUBS_READ)
0134
0135
0136
0137 int
0138 snd_seq_oss_midi_check_new_port(struct snd_seq_port_info *pinfo)
0139 {
0140 int i;
0141 struct seq_oss_midi *mdev;
0142 unsigned long flags;
0143
0144
0145 if (! (pinfo->type & SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC))
0146 return 0;
0147
0148 if ((pinfo->capability & PERM_WRITE) != PERM_WRITE &&
0149 (pinfo->capability & PERM_READ) != PERM_READ)
0150 return 0;
0151
0152
0153
0154
0155 mdev = find_slot(pinfo->addr.client, pinfo->addr.port);
0156 if (mdev) {
0157
0158 snd_use_lock_free(&mdev->use_lock);
0159 return 0;
0160 }
0161
0162
0163
0164
0165 mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
0166 if (!mdev)
0167 return -ENOMEM;
0168
0169
0170 mdev->client = pinfo->addr.client;
0171 mdev->port = pinfo->addr.port;
0172 mdev->flags = pinfo->capability;
0173 mdev->opened = 0;
0174 snd_use_lock_init(&mdev->use_lock);
0175
0176
0177 strscpy(mdev->name, pinfo->name, sizeof(mdev->name));
0178
0179
0180 if (snd_midi_event_new(MAX_MIDI_EVENT_BUF, &mdev->coder) < 0) {
0181 pr_err("ALSA: seq_oss: can't malloc midi coder\n");
0182 kfree(mdev);
0183 return -ENOMEM;
0184 }
0185
0186 snd_midi_event_no_status(mdev->coder, 1);
0187
0188
0189
0190
0191 spin_lock_irqsave(®ister_lock, flags);
0192 for (i = 0; i < max_midi_devs; i++) {
0193 if (midi_devs[i] == NULL)
0194 break;
0195 }
0196 if (i >= max_midi_devs) {
0197 if (max_midi_devs >= SNDRV_SEQ_OSS_MAX_MIDI_DEVS) {
0198 spin_unlock_irqrestore(®ister_lock, flags);
0199 snd_midi_event_free(mdev->coder);
0200 kfree(mdev);
0201 return -ENOMEM;
0202 }
0203 max_midi_devs++;
0204 }
0205 mdev->seq_device = i;
0206 midi_devs[mdev->seq_device] = mdev;
0207 spin_unlock_irqrestore(®ister_lock, flags);
0208
0209 return 0;
0210 }
0211
0212
0213
0214
0215 int
0216 snd_seq_oss_midi_check_exit_port(int client, int port)
0217 {
0218 struct seq_oss_midi *mdev;
0219 unsigned long flags;
0220 int index;
0221
0222 mdev = find_slot(client, port);
0223 if (mdev) {
0224 spin_lock_irqsave(®ister_lock, flags);
0225 midi_devs[mdev->seq_device] = NULL;
0226 spin_unlock_irqrestore(®ister_lock, flags);
0227 snd_use_lock_free(&mdev->use_lock);
0228 snd_use_lock_sync(&mdev->use_lock);
0229 snd_midi_event_free(mdev->coder);
0230 kfree(mdev);
0231 }
0232 spin_lock_irqsave(®ister_lock, flags);
0233 for (index = max_midi_devs - 1; index >= 0; index--) {
0234 if (midi_devs[index])
0235 break;
0236 }
0237 max_midi_devs = index + 1;
0238 spin_unlock_irqrestore(®ister_lock, flags);
0239 return 0;
0240 }
0241
0242
0243
0244
0245
0246 void
0247 snd_seq_oss_midi_clear_all(void)
0248 {
0249 int i;
0250 struct seq_oss_midi *mdev;
0251 unsigned long flags;
0252
0253 spin_lock_irqsave(®ister_lock, flags);
0254 for (i = 0; i < max_midi_devs; i++) {
0255 mdev = midi_devs[i];
0256 if (mdev) {
0257 snd_midi_event_free(mdev->coder);
0258 kfree(mdev);
0259 midi_devs[i] = NULL;
0260 }
0261 }
0262 max_midi_devs = 0;
0263 spin_unlock_irqrestore(®ister_lock, flags);
0264 }
0265
0266
0267
0268
0269
0270 void
0271 snd_seq_oss_midi_setup(struct seq_oss_devinfo *dp)
0272 {
0273 spin_lock_irq(®ister_lock);
0274 dp->max_mididev = max_midi_devs;
0275 spin_unlock_irq(®ister_lock);
0276 }
0277
0278
0279
0280
0281 void
0282 snd_seq_oss_midi_cleanup(struct seq_oss_devinfo *dp)
0283 {
0284 int i;
0285 for (i = 0; i < dp->max_mididev; i++)
0286 snd_seq_oss_midi_close(dp, i);
0287 dp->max_mididev = 0;
0288 }
0289
0290
0291
0292
0293
0294 void
0295 snd_seq_oss_midi_open_all(struct seq_oss_devinfo *dp, int file_mode)
0296 {
0297 int i;
0298 for (i = 0; i < dp->max_mididev; i++)
0299 snd_seq_oss_midi_open(dp, i, file_mode);
0300 }
0301
0302
0303
0304
0305
0306 static struct seq_oss_midi *
0307 get_mididev(struct seq_oss_devinfo *dp, int dev)
0308 {
0309 if (dev < 0 || dev >= dp->max_mididev)
0310 return NULL;
0311 dev = array_index_nospec(dev, dp->max_mididev);
0312 return get_mdev(dev);
0313 }
0314
0315
0316
0317
0318
0319 int
0320 snd_seq_oss_midi_open(struct seq_oss_devinfo *dp, int dev, int fmode)
0321 {
0322 int perm;
0323 struct seq_oss_midi *mdev;
0324 struct snd_seq_port_subscribe subs;
0325
0326 mdev = get_mididev(dp, dev);
0327 if (!mdev)
0328 return -ENODEV;
0329
0330
0331 if (mdev->opened && mdev->devinfo != dp) {
0332 snd_use_lock_free(&mdev->use_lock);
0333 return -EBUSY;
0334 }
0335
0336 perm = 0;
0337 if (is_write_mode(fmode))
0338 perm |= PERM_WRITE;
0339 if (is_read_mode(fmode))
0340 perm |= PERM_READ;
0341 perm &= mdev->flags;
0342 if (perm == 0) {
0343 snd_use_lock_free(&mdev->use_lock);
0344 return -ENXIO;
0345 }
0346
0347
0348 if ((mdev->opened & perm) == perm) {
0349 snd_use_lock_free(&mdev->use_lock);
0350 return 0;
0351 }
0352
0353 perm &= ~mdev->opened;
0354
0355 memset(&subs, 0, sizeof(subs));
0356
0357 if (perm & PERM_WRITE) {
0358 subs.sender = dp->addr;
0359 subs.dest.client = mdev->client;
0360 subs.dest.port = mdev->port;
0361 if (snd_seq_kernel_client_ctl(dp->cseq, SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, &subs) >= 0)
0362 mdev->opened |= PERM_WRITE;
0363 }
0364 if (perm & PERM_READ) {
0365 subs.sender.client = mdev->client;
0366 subs.sender.port = mdev->port;
0367 subs.dest = dp->addr;
0368 subs.flags = SNDRV_SEQ_PORT_SUBS_TIMESTAMP;
0369 subs.queue = dp->queue;
0370 if (snd_seq_kernel_client_ctl(dp->cseq, SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, &subs) >= 0)
0371 mdev->opened |= PERM_READ;
0372 }
0373
0374 if (! mdev->opened) {
0375 snd_use_lock_free(&mdev->use_lock);
0376 return -ENXIO;
0377 }
0378
0379 mdev->devinfo = dp;
0380 snd_use_lock_free(&mdev->use_lock);
0381 return 0;
0382 }
0383
0384
0385
0386
0387 int
0388 snd_seq_oss_midi_close(struct seq_oss_devinfo *dp, int dev)
0389 {
0390 struct seq_oss_midi *mdev;
0391 struct snd_seq_port_subscribe subs;
0392
0393 mdev = get_mididev(dp, dev);
0394 if (!mdev)
0395 return -ENODEV;
0396 if (! mdev->opened || mdev->devinfo != dp) {
0397 snd_use_lock_free(&mdev->use_lock);
0398 return 0;
0399 }
0400
0401 memset(&subs, 0, sizeof(subs));
0402 if (mdev->opened & PERM_WRITE) {
0403 subs.sender = dp->addr;
0404 subs.dest.client = mdev->client;
0405 subs.dest.port = mdev->port;
0406 snd_seq_kernel_client_ctl(dp->cseq, SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT, &subs);
0407 }
0408 if (mdev->opened & PERM_READ) {
0409 subs.sender.client = mdev->client;
0410 subs.sender.port = mdev->port;
0411 subs.dest = dp->addr;
0412 snd_seq_kernel_client_ctl(dp->cseq, SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT, &subs);
0413 }
0414
0415 mdev->opened = 0;
0416 mdev->devinfo = NULL;
0417
0418 snd_use_lock_free(&mdev->use_lock);
0419 return 0;
0420 }
0421
0422
0423
0424
0425 int
0426 snd_seq_oss_midi_filemode(struct seq_oss_devinfo *dp, int dev)
0427 {
0428 struct seq_oss_midi *mdev;
0429 int mode;
0430
0431 mdev = get_mididev(dp, dev);
0432 if (!mdev)
0433 return 0;
0434
0435 mode = 0;
0436 if (mdev->opened & PERM_WRITE)
0437 mode |= SNDRV_SEQ_OSS_FILE_WRITE;
0438 if (mdev->opened & PERM_READ)
0439 mode |= SNDRV_SEQ_OSS_FILE_READ;
0440
0441 snd_use_lock_free(&mdev->use_lock);
0442 return mode;
0443 }
0444
0445
0446
0447
0448
0449 void
0450 snd_seq_oss_midi_reset(struct seq_oss_devinfo *dp, int dev)
0451 {
0452 struct seq_oss_midi *mdev;
0453
0454 mdev = get_mididev(dp, dev);
0455 if (!mdev)
0456 return;
0457 if (! mdev->opened) {
0458 snd_use_lock_free(&mdev->use_lock);
0459 return;
0460 }
0461
0462 if (mdev->opened & PERM_WRITE) {
0463 struct snd_seq_event ev;
0464 int c;
0465
0466 memset(&ev, 0, sizeof(ev));
0467 ev.dest.client = mdev->client;
0468 ev.dest.port = mdev->port;
0469 ev.queue = dp->queue;
0470 ev.source.port = dp->port;
0471 if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_SYNTH) {
0472 ev.type = SNDRV_SEQ_EVENT_SENSING;
0473 snd_seq_oss_dispatch(dp, &ev, 0, 0);
0474 }
0475 for (c = 0; c < 16; c++) {
0476 ev.type = SNDRV_SEQ_EVENT_CONTROLLER;
0477 ev.data.control.channel = c;
0478 ev.data.control.param = MIDI_CTL_ALL_NOTES_OFF;
0479 snd_seq_oss_dispatch(dp, &ev, 0, 0);
0480 if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC) {
0481 ev.data.control.param =
0482 MIDI_CTL_RESET_CONTROLLERS;
0483 snd_seq_oss_dispatch(dp, &ev, 0, 0);
0484 ev.type = SNDRV_SEQ_EVENT_PITCHBEND;
0485 ev.data.control.value = 0;
0486 snd_seq_oss_dispatch(dp, &ev, 0, 0);
0487 }
0488 }
0489 }
0490
0491 snd_use_lock_free(&mdev->use_lock);
0492 }
0493
0494
0495
0496
0497
0498 void
0499 snd_seq_oss_midi_get_addr(struct seq_oss_devinfo *dp, int dev, struct snd_seq_addr *addr)
0500 {
0501 struct seq_oss_midi *mdev;
0502
0503 mdev = get_mididev(dp, dev);
0504 if (!mdev)
0505 return;
0506 addr->client = mdev->client;
0507 addr->port = mdev->port;
0508 snd_use_lock_free(&mdev->use_lock);
0509 }
0510
0511
0512
0513
0514
0515 int
0516 snd_seq_oss_midi_input(struct snd_seq_event *ev, int direct, void *private_data)
0517 {
0518 struct seq_oss_devinfo *dp = (struct seq_oss_devinfo *)private_data;
0519 struct seq_oss_midi *mdev;
0520 int rc;
0521
0522 if (dp->readq == NULL)
0523 return 0;
0524 mdev = find_slot(ev->source.client, ev->source.port);
0525 if (!mdev)
0526 return 0;
0527 if (! (mdev->opened & PERM_READ)) {
0528 snd_use_lock_free(&mdev->use_lock);
0529 return 0;
0530 }
0531
0532 if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC)
0533 rc = send_synth_event(dp, ev, mdev->seq_device);
0534 else
0535 rc = send_midi_event(dp, ev, mdev);
0536
0537 snd_use_lock_free(&mdev->use_lock);
0538 return rc;
0539 }
0540
0541
0542
0543
0544 static int
0545 send_synth_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, int dev)
0546 {
0547 union evrec ossev;
0548
0549 memset(&ossev, 0, sizeof(ossev));
0550
0551 switch (ev->type) {
0552 case SNDRV_SEQ_EVENT_NOTEON:
0553 ossev.v.cmd = MIDI_NOTEON; break;
0554 case SNDRV_SEQ_EVENT_NOTEOFF:
0555 ossev.v.cmd = MIDI_NOTEOFF; break;
0556 case SNDRV_SEQ_EVENT_KEYPRESS:
0557 ossev.v.cmd = MIDI_KEY_PRESSURE; break;
0558 case SNDRV_SEQ_EVENT_CONTROLLER:
0559 ossev.l.cmd = MIDI_CTL_CHANGE; break;
0560 case SNDRV_SEQ_EVENT_PGMCHANGE:
0561 ossev.l.cmd = MIDI_PGM_CHANGE; break;
0562 case SNDRV_SEQ_EVENT_CHANPRESS:
0563 ossev.l.cmd = MIDI_CHN_PRESSURE; break;
0564 case SNDRV_SEQ_EVENT_PITCHBEND:
0565 ossev.l.cmd = MIDI_PITCH_BEND; break;
0566 default:
0567 return 0;
0568 }
0569
0570 ossev.v.dev = dev;
0571
0572 switch (ev->type) {
0573 case SNDRV_SEQ_EVENT_NOTEON:
0574 case SNDRV_SEQ_EVENT_NOTEOFF:
0575 case SNDRV_SEQ_EVENT_KEYPRESS:
0576 ossev.v.code = EV_CHN_VOICE;
0577 ossev.v.note = ev->data.note.note;
0578 ossev.v.parm = ev->data.note.velocity;
0579 ossev.v.chn = ev->data.note.channel;
0580 break;
0581 case SNDRV_SEQ_EVENT_CONTROLLER:
0582 case SNDRV_SEQ_EVENT_PGMCHANGE:
0583 case SNDRV_SEQ_EVENT_CHANPRESS:
0584 ossev.l.code = EV_CHN_COMMON;
0585 ossev.l.p1 = ev->data.control.param;
0586 ossev.l.val = ev->data.control.value;
0587 ossev.l.chn = ev->data.control.channel;
0588 break;
0589 case SNDRV_SEQ_EVENT_PITCHBEND:
0590 ossev.l.code = EV_CHN_COMMON;
0591 ossev.l.val = ev->data.control.value + 8192;
0592 ossev.l.chn = ev->data.control.channel;
0593 break;
0594 }
0595
0596 snd_seq_oss_readq_put_timestamp(dp->readq, ev->time.tick, dp->seq_mode);
0597 snd_seq_oss_readq_put_event(dp->readq, &ossev);
0598
0599 return 0;
0600 }
0601
0602
0603
0604
0605 static int
0606 send_midi_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, struct seq_oss_midi *mdev)
0607 {
0608 char msg[32];
0609 int len;
0610
0611 snd_seq_oss_readq_put_timestamp(dp->readq, ev->time.tick, dp->seq_mode);
0612 if (!dp->timer->running)
0613 len = snd_seq_oss_timer_start(dp->timer);
0614 if (ev->type == SNDRV_SEQ_EVENT_SYSEX) {
0615 snd_seq_oss_readq_sysex(dp->readq, mdev->seq_device, ev);
0616 snd_midi_event_reset_decode(mdev->coder);
0617 } else {
0618 len = snd_midi_event_decode(mdev->coder, msg, sizeof(msg), ev);
0619 if (len > 0)
0620 snd_seq_oss_readq_puts(dp->readq, mdev->seq_device, msg, len);
0621 }
0622
0623 return 0;
0624 }
0625
0626
0627
0628
0629
0630
0631
0632 int
0633 snd_seq_oss_midi_putc(struct seq_oss_devinfo *dp, int dev, unsigned char c, struct snd_seq_event *ev)
0634 {
0635 struct seq_oss_midi *mdev;
0636
0637 mdev = get_mididev(dp, dev);
0638 if (!mdev)
0639 return -ENODEV;
0640 if (snd_midi_event_encode_byte(mdev->coder, c, ev)) {
0641 snd_seq_oss_fill_addr(dp, ev, mdev->client, mdev->port);
0642 snd_use_lock_free(&mdev->use_lock);
0643 return 0;
0644 }
0645 snd_use_lock_free(&mdev->use_lock);
0646 return -EINVAL;
0647 }
0648
0649
0650
0651
0652 int
0653 snd_seq_oss_midi_make_info(struct seq_oss_devinfo *dp, int dev, struct midi_info *inf)
0654 {
0655 struct seq_oss_midi *mdev;
0656
0657 mdev = get_mididev(dp, dev);
0658 if (!mdev)
0659 return -ENXIO;
0660 inf->device = dev;
0661 inf->dev_type = 0;
0662 inf->capabilities = 0;
0663 strscpy(inf->name, mdev->name, sizeof(inf->name));
0664 snd_use_lock_free(&mdev->use_lock);
0665 return 0;
0666 }
0667
0668
0669 #ifdef CONFIG_SND_PROC_FS
0670
0671
0672
0673 static char *
0674 capmode_str(int val)
0675 {
0676 val &= PERM_READ|PERM_WRITE;
0677 if (val == (PERM_READ|PERM_WRITE))
0678 return "read/write";
0679 else if (val == PERM_READ)
0680 return "read";
0681 else if (val == PERM_WRITE)
0682 return "write";
0683 else
0684 return "none";
0685 }
0686
0687 void
0688 snd_seq_oss_midi_info_read(struct snd_info_buffer *buf)
0689 {
0690 int i;
0691 struct seq_oss_midi *mdev;
0692
0693 snd_iprintf(buf, "\nNumber of MIDI devices: %d\n", max_midi_devs);
0694 for (i = 0; i < max_midi_devs; i++) {
0695 snd_iprintf(buf, "\nmidi %d: ", i);
0696 mdev = get_mdev(i);
0697 if (mdev == NULL) {
0698 snd_iprintf(buf, "*empty*\n");
0699 continue;
0700 }
0701 snd_iprintf(buf, "[%s] ALSA port %d:%d\n", mdev->name,
0702 mdev->client, mdev->port);
0703 snd_iprintf(buf, " capability %s / opened %s\n",
0704 capmode_str(mdev->flags),
0705 capmode_str(mdev->opened));
0706 snd_use_lock_free(&mdev->use_lock);
0707 }
0708 }
0709 #endif