0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include "seq_oss_synth.h"
0011 #include "seq_oss_midi.h"
0012 #include "../seq_lock.h"
0013 #include <linux/init.h>
0014 #include <linux/module.h>
0015 #include <linux/slab.h>
0016 #include <linux/nospec.h>
0017
0018
0019
0020
0021 #define SNDRV_SEQ_OSS_MAX_SYNTH_NAME 30
0022 #define MAX_SYSEX_BUFLEN 128
0023
0024
0025
0026
0027
0028
0029
0030 struct seq_oss_synth_sysex {
0031 int len;
0032 int skip;
0033 unsigned char buf[MAX_SYSEX_BUFLEN];
0034 };
0035
0036
0037 struct seq_oss_synth {
0038 int seq_device;
0039
0040
0041 int synth_type;
0042 int synth_subtype;
0043 int nr_voices;
0044
0045 char name[SNDRV_SEQ_OSS_MAX_SYNTH_NAME];
0046 struct snd_seq_oss_callback oper;
0047
0048 int opened;
0049
0050 void *private_data;
0051 snd_use_lock_t use_lock;
0052 };
0053
0054
0055
0056
0057
0058 static int max_synth_devs;
0059 static struct seq_oss_synth *synth_devs[SNDRV_SEQ_OSS_MAX_SYNTH_DEVS];
0060 static struct seq_oss_synth midi_synth_dev = {
0061 .seq_device = -1,
0062 .synth_type = SYNTH_TYPE_MIDI,
0063 .synth_subtype = 0,
0064 .nr_voices = 16,
0065 .name = "MIDI",
0066 };
0067
0068 static DEFINE_SPINLOCK(register_lock);
0069
0070
0071
0072
0073 static struct seq_oss_synth *get_synthdev(struct seq_oss_devinfo *dp, int dev);
0074 static void reset_channels(struct seq_oss_synthinfo *info);
0075
0076
0077
0078
0079 void __init
0080 snd_seq_oss_synth_init(void)
0081 {
0082 snd_use_lock_init(&midi_synth_dev.use_lock);
0083 }
0084
0085
0086
0087
0088 int
0089 snd_seq_oss_synth_probe(struct device *_dev)
0090 {
0091 struct snd_seq_device *dev = to_seq_dev(_dev);
0092 int i;
0093 struct seq_oss_synth *rec;
0094 struct snd_seq_oss_reg *reg = SNDRV_SEQ_DEVICE_ARGPTR(dev);
0095 unsigned long flags;
0096
0097 rec = kzalloc(sizeof(*rec), GFP_KERNEL);
0098 if (!rec)
0099 return -ENOMEM;
0100 rec->seq_device = -1;
0101 rec->synth_type = reg->type;
0102 rec->synth_subtype = reg->subtype;
0103 rec->nr_voices = reg->nvoices;
0104 rec->oper = reg->oper;
0105 rec->private_data = reg->private_data;
0106 rec->opened = 0;
0107 snd_use_lock_init(&rec->use_lock);
0108
0109
0110 strscpy(rec->name, dev->name, sizeof(rec->name));
0111
0112
0113 spin_lock_irqsave(®ister_lock, flags);
0114 for (i = 0; i < max_synth_devs; i++) {
0115 if (synth_devs[i] == NULL)
0116 break;
0117 }
0118 if (i >= max_synth_devs) {
0119 if (max_synth_devs >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS) {
0120 spin_unlock_irqrestore(®ister_lock, flags);
0121 pr_err("ALSA: seq_oss: no more synth slot\n");
0122 kfree(rec);
0123 return -ENOMEM;
0124 }
0125 max_synth_devs++;
0126 }
0127 rec->seq_device = i;
0128 synth_devs[i] = rec;
0129 spin_unlock_irqrestore(®ister_lock, flags);
0130 dev->driver_data = rec;
0131 #ifdef SNDRV_OSS_INFO_DEV_SYNTH
0132 if (i < SNDRV_CARDS)
0133 snd_oss_info_register(SNDRV_OSS_INFO_DEV_SYNTH, i, rec->name);
0134 #endif
0135 return 0;
0136 }
0137
0138
0139 int
0140 snd_seq_oss_synth_remove(struct device *_dev)
0141 {
0142 struct snd_seq_device *dev = to_seq_dev(_dev);
0143 int index;
0144 struct seq_oss_synth *rec = dev->driver_data;
0145 unsigned long flags;
0146
0147 spin_lock_irqsave(®ister_lock, flags);
0148 for (index = 0; index < max_synth_devs; index++) {
0149 if (synth_devs[index] == rec)
0150 break;
0151 }
0152 if (index >= max_synth_devs) {
0153 spin_unlock_irqrestore(®ister_lock, flags);
0154 pr_err("ALSA: seq_oss: can't unregister synth\n");
0155 return -EINVAL;
0156 }
0157 synth_devs[index] = NULL;
0158 if (index == max_synth_devs - 1) {
0159 for (index--; index >= 0; index--) {
0160 if (synth_devs[index])
0161 break;
0162 }
0163 max_synth_devs = index + 1;
0164 }
0165 spin_unlock_irqrestore(®ister_lock, flags);
0166 #ifdef SNDRV_OSS_INFO_DEV_SYNTH
0167 if (rec->seq_device < SNDRV_CARDS)
0168 snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_SYNTH, rec->seq_device);
0169 #endif
0170
0171 snd_use_lock_sync(&rec->use_lock);
0172 kfree(rec);
0173
0174 return 0;
0175 }
0176
0177
0178
0179
0180 static struct seq_oss_synth *
0181 get_sdev(int dev)
0182 {
0183 struct seq_oss_synth *rec;
0184 unsigned long flags;
0185
0186 spin_lock_irqsave(®ister_lock, flags);
0187 rec = synth_devs[dev];
0188 if (rec)
0189 snd_use_lock_use(&rec->use_lock);
0190 spin_unlock_irqrestore(®ister_lock, flags);
0191 return rec;
0192 }
0193
0194
0195
0196
0197
0198
0199 void
0200 snd_seq_oss_synth_setup(struct seq_oss_devinfo *dp)
0201 {
0202 int i;
0203 struct seq_oss_synth *rec;
0204 struct seq_oss_synthinfo *info;
0205
0206 dp->max_synthdev = max_synth_devs;
0207 dp->synth_opened = 0;
0208 memset(dp->synths, 0, sizeof(dp->synths));
0209 for (i = 0; i < dp->max_synthdev; i++) {
0210 rec = get_sdev(i);
0211 if (rec == NULL)
0212 continue;
0213 if (rec->oper.open == NULL || rec->oper.close == NULL) {
0214 snd_use_lock_free(&rec->use_lock);
0215 continue;
0216 }
0217 info = &dp->synths[i];
0218 info->arg.app_index = dp->port;
0219 info->arg.file_mode = dp->file_mode;
0220 info->arg.seq_mode = dp->seq_mode;
0221 if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_SYNTH)
0222 info->arg.event_passing = SNDRV_SEQ_OSS_PROCESS_EVENTS;
0223 else
0224 info->arg.event_passing = SNDRV_SEQ_OSS_PASS_EVENTS;
0225 info->opened = 0;
0226 if (!try_module_get(rec->oper.owner)) {
0227 snd_use_lock_free(&rec->use_lock);
0228 continue;
0229 }
0230 if (rec->oper.open(&info->arg, rec->private_data) < 0) {
0231 module_put(rec->oper.owner);
0232 snd_use_lock_free(&rec->use_lock);
0233 continue;
0234 }
0235 info->nr_voices = rec->nr_voices;
0236 if (info->nr_voices > 0) {
0237 info->ch = kcalloc(info->nr_voices, sizeof(struct seq_oss_chinfo), GFP_KERNEL);
0238 if (!info->ch) {
0239 rec->oper.close(&info->arg);
0240 module_put(rec->oper.owner);
0241 snd_use_lock_free(&rec->use_lock);
0242 continue;
0243 }
0244 reset_channels(info);
0245 }
0246 info->opened++;
0247 rec->opened++;
0248 dp->synth_opened++;
0249 snd_use_lock_free(&rec->use_lock);
0250 }
0251 }
0252
0253
0254
0255
0256
0257
0258 void
0259 snd_seq_oss_synth_setup_midi(struct seq_oss_devinfo *dp)
0260 {
0261 int i;
0262
0263 if (dp->max_synthdev >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS)
0264 return;
0265
0266 for (i = 0; i < dp->max_mididev; i++) {
0267 struct seq_oss_synthinfo *info;
0268 info = &dp->synths[dp->max_synthdev];
0269 if (snd_seq_oss_midi_open(dp, i, dp->file_mode) < 0)
0270 continue;
0271 info->arg.app_index = dp->port;
0272 info->arg.file_mode = dp->file_mode;
0273 info->arg.seq_mode = dp->seq_mode;
0274 info->arg.private_data = info;
0275 info->is_midi = 1;
0276 info->midi_mapped = i;
0277 info->arg.event_passing = SNDRV_SEQ_OSS_PASS_EVENTS;
0278 snd_seq_oss_midi_get_addr(dp, i, &info->arg.addr);
0279 info->opened = 1;
0280 midi_synth_dev.opened++;
0281 dp->max_synthdev++;
0282 if (dp->max_synthdev >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS)
0283 break;
0284 }
0285 }
0286
0287
0288
0289
0290
0291
0292 void
0293 snd_seq_oss_synth_cleanup(struct seq_oss_devinfo *dp)
0294 {
0295 int i;
0296 struct seq_oss_synth *rec;
0297 struct seq_oss_synthinfo *info;
0298
0299 if (snd_BUG_ON(dp->max_synthdev > SNDRV_SEQ_OSS_MAX_SYNTH_DEVS))
0300 return;
0301 for (i = 0; i < dp->max_synthdev; i++) {
0302 info = &dp->synths[i];
0303 if (! info->opened)
0304 continue;
0305 if (info->is_midi) {
0306 if (midi_synth_dev.opened > 0) {
0307 snd_seq_oss_midi_close(dp, info->midi_mapped);
0308 midi_synth_dev.opened--;
0309 }
0310 } else {
0311 rec = get_sdev(i);
0312 if (rec == NULL)
0313 continue;
0314 if (rec->opened > 0) {
0315 rec->oper.close(&info->arg);
0316 module_put(rec->oper.owner);
0317 rec->opened = 0;
0318 }
0319 snd_use_lock_free(&rec->use_lock);
0320 }
0321 kfree(info->sysex);
0322 info->sysex = NULL;
0323 kfree(info->ch);
0324 info->ch = NULL;
0325 }
0326 dp->synth_opened = 0;
0327 dp->max_synthdev = 0;
0328 }
0329
0330 static struct seq_oss_synthinfo *
0331 get_synthinfo_nospec(struct seq_oss_devinfo *dp, int dev)
0332 {
0333 if (dev < 0 || dev >= dp->max_synthdev)
0334 return NULL;
0335 dev = array_index_nospec(dev, SNDRV_SEQ_OSS_MAX_SYNTH_DEVS);
0336 return &dp->synths[dev];
0337 }
0338
0339
0340
0341
0342 static struct seq_oss_synth *
0343 get_synthdev(struct seq_oss_devinfo *dp, int dev)
0344 {
0345 struct seq_oss_synth *rec;
0346 struct seq_oss_synthinfo *info = get_synthinfo_nospec(dp, dev);
0347
0348 if (!info)
0349 return NULL;
0350 if (!info->opened)
0351 return NULL;
0352 if (info->is_midi) {
0353 rec = &midi_synth_dev;
0354 snd_use_lock_use(&rec->use_lock);
0355 } else {
0356 rec = get_sdev(dev);
0357 if (!rec)
0358 return NULL;
0359 }
0360 if (! rec->opened) {
0361 snd_use_lock_free(&rec->use_lock);
0362 return NULL;
0363 }
0364 return rec;
0365 }
0366
0367
0368
0369
0370
0371 static void
0372 reset_channels(struct seq_oss_synthinfo *info)
0373 {
0374 int i;
0375 if (info->ch == NULL || ! info->nr_voices)
0376 return;
0377 for (i = 0; i < info->nr_voices; i++) {
0378 info->ch[i].note = -1;
0379 info->ch[i].vel = 0;
0380 }
0381 }
0382
0383
0384
0385
0386
0387
0388
0389 void
0390 snd_seq_oss_synth_reset(struct seq_oss_devinfo *dp, int dev)
0391 {
0392 struct seq_oss_synth *rec;
0393 struct seq_oss_synthinfo *info;
0394
0395 info = get_synthinfo_nospec(dp, dev);
0396 if (!info || !info->opened)
0397 return;
0398 if (info->sysex)
0399 info->sysex->len = 0;
0400 reset_channels(info);
0401 if (info->is_midi) {
0402 if (midi_synth_dev.opened <= 0)
0403 return;
0404 snd_seq_oss_midi_reset(dp, info->midi_mapped);
0405
0406 snd_seq_oss_midi_close(dp, dev);
0407 if (snd_seq_oss_midi_open(dp, info->midi_mapped,
0408 dp->file_mode) < 0) {
0409 midi_synth_dev.opened--;
0410 info->opened = 0;
0411 kfree(info->sysex);
0412 info->sysex = NULL;
0413 kfree(info->ch);
0414 info->ch = NULL;
0415 }
0416 return;
0417 }
0418
0419 rec = get_sdev(dev);
0420 if (rec == NULL)
0421 return;
0422 if (rec->oper.reset) {
0423 rec->oper.reset(&info->arg);
0424 } else {
0425 struct snd_seq_event ev;
0426 memset(&ev, 0, sizeof(ev));
0427 snd_seq_oss_fill_addr(dp, &ev, info->arg.addr.client,
0428 info->arg.addr.port);
0429 ev.type = SNDRV_SEQ_EVENT_RESET;
0430 snd_seq_oss_dispatch(dp, &ev, 0, 0);
0431 }
0432 snd_use_lock_free(&rec->use_lock);
0433 }
0434
0435
0436
0437
0438
0439
0440 int
0441 snd_seq_oss_synth_load_patch(struct seq_oss_devinfo *dp, int dev, int fmt,
0442 const char __user *buf, int p, int c)
0443 {
0444 struct seq_oss_synth *rec;
0445 struct seq_oss_synthinfo *info;
0446 int rc;
0447
0448 info = get_synthinfo_nospec(dp, dev);
0449 if (!info)
0450 return -ENXIO;
0451
0452 if (info->is_midi)
0453 return 0;
0454 rec = get_synthdev(dp, dev);
0455 if (!rec)
0456 return -ENXIO;
0457
0458 if (rec->oper.load_patch == NULL)
0459 rc = -ENXIO;
0460 else
0461 rc = rec->oper.load_patch(&info->arg, fmt, buf, p, c);
0462 snd_use_lock_free(&rec->use_lock);
0463 return rc;
0464 }
0465
0466
0467
0468
0469 struct seq_oss_synthinfo *
0470 snd_seq_oss_synth_info(struct seq_oss_devinfo *dp, int dev)
0471 {
0472 struct seq_oss_synth *rec;
0473
0474 rec = get_synthdev(dp, dev);
0475 if (rec) {
0476 snd_use_lock_free(&rec->use_lock);
0477 return get_synthinfo_nospec(dp, dev);
0478 }
0479 return NULL;
0480 }
0481
0482
0483
0484
0485
0486
0487
0488 int
0489 snd_seq_oss_synth_sysex(struct seq_oss_devinfo *dp, int dev, unsigned char *buf, struct snd_seq_event *ev)
0490 {
0491 int i, send;
0492 unsigned char *dest;
0493 struct seq_oss_synth_sysex *sysex;
0494 struct seq_oss_synthinfo *info;
0495
0496 info = snd_seq_oss_synth_info(dp, dev);
0497 if (!info)
0498 return -ENXIO;
0499
0500 sysex = info->sysex;
0501 if (sysex == NULL) {
0502 sysex = kzalloc(sizeof(*sysex), GFP_KERNEL);
0503 if (sysex == NULL)
0504 return -ENOMEM;
0505 info->sysex = sysex;
0506 }
0507
0508 send = 0;
0509 dest = sysex->buf + sysex->len;
0510
0511 for (i = 0; i < 6; i++) {
0512 if (buf[i] == 0xff) {
0513 send = 1;
0514 break;
0515 }
0516 dest[i] = buf[i];
0517 sysex->len++;
0518 if (sysex->len >= MAX_SYSEX_BUFLEN) {
0519 sysex->len = 0;
0520 sysex->skip = 1;
0521 break;
0522 }
0523 }
0524
0525 if (sysex->len && send) {
0526 if (sysex->skip) {
0527 sysex->skip = 0;
0528 sysex->len = 0;
0529 return -EINVAL;
0530 }
0531
0532 ev->flags = SNDRV_SEQ_EVENT_LENGTH_VARIABLE;
0533 if (snd_seq_oss_synth_addr(dp, dev, ev))
0534 return -EINVAL;
0535 ev->data.ext.len = sysex->len;
0536 ev->data.ext.ptr = sysex->buf;
0537 sysex->len = 0;
0538 return 0;
0539 }
0540
0541 return -EINVAL;
0542 }
0543
0544
0545
0546
0547 int
0548 snd_seq_oss_synth_addr(struct seq_oss_devinfo *dp, int dev, struct snd_seq_event *ev)
0549 {
0550 struct seq_oss_synthinfo *info = snd_seq_oss_synth_info(dp, dev);
0551
0552 if (!info)
0553 return -EINVAL;
0554 snd_seq_oss_fill_addr(dp, ev, info->arg.addr.client,
0555 info->arg.addr.port);
0556 return 0;
0557 }
0558
0559
0560
0561
0562
0563 int
0564 snd_seq_oss_synth_ioctl(struct seq_oss_devinfo *dp, int dev, unsigned int cmd, unsigned long addr)
0565 {
0566 struct seq_oss_synth *rec;
0567 struct seq_oss_synthinfo *info;
0568 int rc;
0569
0570 info = get_synthinfo_nospec(dp, dev);
0571 if (!info || info->is_midi)
0572 return -ENXIO;
0573 rec = get_synthdev(dp, dev);
0574 if (!rec)
0575 return -ENXIO;
0576 if (rec->oper.ioctl == NULL)
0577 rc = -ENXIO;
0578 else
0579 rc = rec->oper.ioctl(&info->arg, cmd, addr);
0580 snd_use_lock_free(&rec->use_lock);
0581 return rc;
0582 }
0583
0584
0585
0586
0587
0588 int
0589 snd_seq_oss_synth_raw_event(struct seq_oss_devinfo *dp, int dev, unsigned char *data, struct snd_seq_event *ev)
0590 {
0591 struct seq_oss_synthinfo *info;
0592
0593 info = snd_seq_oss_synth_info(dp, dev);
0594 if (!info || info->is_midi)
0595 return -ENXIO;
0596 ev->type = SNDRV_SEQ_EVENT_OSS;
0597 memcpy(ev->data.raw8.d, data, 8);
0598 return snd_seq_oss_synth_addr(dp, dev, ev);
0599 }
0600
0601
0602
0603
0604
0605 int
0606 snd_seq_oss_synth_make_info(struct seq_oss_devinfo *dp, int dev, struct synth_info *inf)
0607 {
0608 struct seq_oss_synth *rec;
0609 struct seq_oss_synthinfo *info = get_synthinfo_nospec(dp, dev);
0610
0611 if (!info)
0612 return -ENXIO;
0613
0614 if (info->is_midi) {
0615 struct midi_info minf;
0616 if (snd_seq_oss_midi_make_info(dp, info->midi_mapped, &minf))
0617 return -ENXIO;
0618 inf->synth_type = SYNTH_TYPE_MIDI;
0619 inf->synth_subtype = 0;
0620 inf->nr_voices = 16;
0621 inf->device = dev;
0622 strscpy(inf->name, minf.name, sizeof(inf->name));
0623 } else {
0624 rec = get_synthdev(dp, dev);
0625 if (!rec)
0626 return -ENXIO;
0627 inf->synth_type = rec->synth_type;
0628 inf->synth_subtype = rec->synth_subtype;
0629 inf->nr_voices = rec->nr_voices;
0630 inf->device = dev;
0631 strscpy(inf->name, rec->name, sizeof(inf->name));
0632 snd_use_lock_free(&rec->use_lock);
0633 }
0634 return 0;
0635 }
0636
0637
0638 #ifdef CONFIG_SND_PROC_FS
0639
0640
0641
0642 void
0643 snd_seq_oss_synth_info_read(struct snd_info_buffer *buf)
0644 {
0645 int i;
0646 struct seq_oss_synth *rec;
0647
0648 snd_iprintf(buf, "\nNumber of synth devices: %d\n", max_synth_devs);
0649 for (i = 0; i < max_synth_devs; i++) {
0650 snd_iprintf(buf, "\nsynth %d: ", i);
0651 rec = get_sdev(i);
0652 if (rec == NULL) {
0653 snd_iprintf(buf, "*empty*\n");
0654 continue;
0655 }
0656 snd_iprintf(buf, "[%s]\n", rec->name);
0657 snd_iprintf(buf, " type 0x%x : subtype 0x%x : voices %d\n",
0658 rec->synth_type, rec->synth_subtype,
0659 rec->nr_voices);
0660 snd_iprintf(buf, " capabilities : ioctl %s / load_patch %s\n",
0661 enabled_str((long)rec->oper.ioctl),
0662 enabled_str((long)rec->oper.load_patch));
0663 snd_use_lock_free(&rec->use_lock);
0664 }
0665 }
0666 #endif