seq_oss_synth.c (14532B)
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/* sysex buffer */ 30struct seq_oss_synth_sysex { 31 int len; 32 int skip; 33 unsigned char buf[MAX_SYSEX_BUFLEN]; 34}; 35 36/* synth info */ 37struct seq_oss_synth { 38 int seq_device; 39 40 /* for synth_info */ 41 int synth_type; 42 int synth_subtype; 43 int nr_voices; 44 45 char name[SNDRV_SEQ_OSS_MAX_SYNTH_NAME]; 46 struct snd_seq_oss_callback oper; 47 48 int opened; 49 50 void *private_data; 51 snd_use_lock_t use_lock; 52}; 53 54 55/* 56 * device table 57 */ 58static int max_synth_devs; 59static struct seq_oss_synth *synth_devs[SNDRV_SEQ_OSS_MAX_SYNTH_DEVS]; 60static struct seq_oss_synth midi_synth_dev = { 61 .seq_device = -1, 62 .synth_type = SYNTH_TYPE_MIDI, 63 .synth_subtype = 0, 64 .nr_voices = 16, 65 .name = "MIDI", 66}; 67 68static DEFINE_SPINLOCK(register_lock); 69 70/* 71 * prototypes 72 */ 73static struct seq_oss_synth *get_synthdev(struct seq_oss_devinfo *dp, int dev); 74static void reset_channels(struct seq_oss_synthinfo *info); 75 76/* 77 * global initialization 78 */ 79void __init 80snd_seq_oss_synth_init(void) 81{ 82 snd_use_lock_init(&midi_synth_dev.use_lock); 83} 84 85/* 86 * registration of the synth device 87 */ 88int 89snd_seq_oss_synth_probe(struct device *_dev) 90{ 91 struct snd_seq_device *dev = to_seq_dev(_dev); 92 int i; 93 struct seq_oss_synth *rec; 94 struct snd_seq_oss_reg *reg = SNDRV_SEQ_DEVICE_ARGPTR(dev); 95 unsigned long flags; 96 97 rec = kzalloc(sizeof(*rec), GFP_KERNEL); 98 if (!rec) 99 return -ENOMEM; 100 rec->seq_device = -1; 101 rec->synth_type = reg->type; 102 rec->synth_subtype = reg->subtype; 103 rec->nr_voices = reg->nvoices; 104 rec->oper = reg->oper; 105 rec->private_data = reg->private_data; 106 rec->opened = 0; 107 snd_use_lock_init(&rec->use_lock); 108 109 /* copy and truncate the name of synth device */ 110 strscpy(rec->name, dev->name, sizeof(rec->name)); 111 112 /* registration */ 113 spin_lock_irqsave(®ister_lock, flags); 114 for (i = 0; i < max_synth_devs; i++) { 115 if (synth_devs[i] == NULL) 116 break; 117 } 118 if (i >= max_synth_devs) { 119 if (max_synth_devs >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS) { 120 spin_unlock_irqrestore(®ister_lock, flags); 121 pr_err("ALSA: seq_oss: no more synth slot\n"); 122 kfree(rec); 123 return -ENOMEM; 124 } 125 max_synth_devs++; 126 } 127 rec->seq_device = i; 128 synth_devs[i] = rec; 129 spin_unlock_irqrestore(®ister_lock, flags); 130 dev->driver_data = rec; 131#ifdef SNDRV_OSS_INFO_DEV_SYNTH 132 if (i < SNDRV_CARDS) 133 snd_oss_info_register(SNDRV_OSS_INFO_DEV_SYNTH, i, rec->name); 134#endif 135 return 0; 136} 137 138 139int 140snd_seq_oss_synth_remove(struct device *_dev) 141{ 142 struct snd_seq_device *dev = to_seq_dev(_dev); 143 int index; 144 struct seq_oss_synth *rec = dev->driver_data; 145 unsigned long flags; 146 147 spin_lock_irqsave(®ister_lock, flags); 148 for (index = 0; index < max_synth_devs; index++) { 149 if (synth_devs[index] == rec) 150 break; 151 } 152 if (index >= max_synth_devs) { 153 spin_unlock_irqrestore(®ister_lock, flags); 154 pr_err("ALSA: seq_oss: can't unregister synth\n"); 155 return -EINVAL; 156 } 157 synth_devs[index] = NULL; 158 if (index == max_synth_devs - 1) { 159 for (index--; index >= 0; index--) { 160 if (synth_devs[index]) 161 break; 162 } 163 max_synth_devs = index + 1; 164 } 165 spin_unlock_irqrestore(®ister_lock, flags); 166#ifdef SNDRV_OSS_INFO_DEV_SYNTH 167 if (rec->seq_device < SNDRV_CARDS) 168 snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_SYNTH, rec->seq_device); 169#endif 170 171 snd_use_lock_sync(&rec->use_lock); 172 kfree(rec); 173 174 return 0; 175} 176 177 178/* 179 */ 180static struct seq_oss_synth * 181get_sdev(int dev) 182{ 183 struct seq_oss_synth *rec; 184 unsigned long flags; 185 186 spin_lock_irqsave(®ister_lock, flags); 187 rec = synth_devs[dev]; 188 if (rec) 189 snd_use_lock_use(&rec->use_lock); 190 spin_unlock_irqrestore(®ister_lock, flags); 191 return rec; 192} 193 194 195/* 196 * set up synth tables 197 */ 198 199void 200snd_seq_oss_synth_setup(struct seq_oss_devinfo *dp) 201{ 202 int i; 203 struct seq_oss_synth *rec; 204 struct seq_oss_synthinfo *info; 205 206 dp->max_synthdev = max_synth_devs; 207 dp->synth_opened = 0; 208 memset(dp->synths, 0, sizeof(dp->synths)); 209 for (i = 0; i < dp->max_synthdev; i++) { 210 rec = get_sdev(i); 211 if (rec == NULL) 212 continue; 213 if (rec->oper.open == NULL || rec->oper.close == NULL) { 214 snd_use_lock_free(&rec->use_lock); 215 continue; 216 } 217 info = &dp->synths[i]; 218 info->arg.app_index = dp->port; 219 info->arg.file_mode = dp->file_mode; 220 info->arg.seq_mode = dp->seq_mode; 221 if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_SYNTH) 222 info->arg.event_passing = SNDRV_SEQ_OSS_PROCESS_EVENTS; 223 else 224 info->arg.event_passing = SNDRV_SEQ_OSS_PASS_EVENTS; 225 info->opened = 0; 226 if (!try_module_get(rec->oper.owner)) { 227 snd_use_lock_free(&rec->use_lock); 228 continue; 229 } 230 if (rec->oper.open(&info->arg, rec->private_data) < 0) { 231 module_put(rec->oper.owner); 232 snd_use_lock_free(&rec->use_lock); 233 continue; 234 } 235 info->nr_voices = rec->nr_voices; 236 if (info->nr_voices > 0) { 237 info->ch = kcalloc(info->nr_voices, sizeof(struct seq_oss_chinfo), GFP_KERNEL); 238 if (!info->ch) { 239 rec->oper.close(&info->arg); 240 module_put(rec->oper.owner); 241 snd_use_lock_free(&rec->use_lock); 242 continue; 243 } 244 reset_channels(info); 245 } 246 info->opened++; 247 rec->opened++; 248 dp->synth_opened++; 249 snd_use_lock_free(&rec->use_lock); 250 } 251} 252 253 254/* 255 * set up synth tables for MIDI emulation - /dev/music mode only 256 */ 257 258void 259snd_seq_oss_synth_setup_midi(struct seq_oss_devinfo *dp) 260{ 261 int i; 262 263 if (dp->max_synthdev >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS) 264 return; 265 266 for (i = 0; i < dp->max_mididev; i++) { 267 struct seq_oss_synthinfo *info; 268 info = &dp->synths[dp->max_synthdev]; 269 if (snd_seq_oss_midi_open(dp, i, dp->file_mode) < 0) 270 continue; 271 info->arg.app_index = dp->port; 272 info->arg.file_mode = dp->file_mode; 273 info->arg.seq_mode = dp->seq_mode; 274 info->arg.private_data = info; 275 info->is_midi = 1; 276 info->midi_mapped = i; 277 info->arg.event_passing = SNDRV_SEQ_OSS_PASS_EVENTS; 278 snd_seq_oss_midi_get_addr(dp, i, &info->arg.addr); 279 info->opened = 1; 280 midi_synth_dev.opened++; 281 dp->max_synthdev++; 282 if (dp->max_synthdev >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS) 283 break; 284 } 285} 286 287 288/* 289 * clean up synth tables 290 */ 291 292void 293snd_seq_oss_synth_cleanup(struct seq_oss_devinfo *dp) 294{ 295 int i; 296 struct seq_oss_synth *rec; 297 struct seq_oss_synthinfo *info; 298 299 if (snd_BUG_ON(dp->max_synthdev > SNDRV_SEQ_OSS_MAX_SYNTH_DEVS)) 300 return; 301 for (i = 0; i < dp->max_synthdev; i++) { 302 info = &dp->synths[i]; 303 if (! info->opened) 304 continue; 305 if (info->is_midi) { 306 if (midi_synth_dev.opened > 0) { 307 snd_seq_oss_midi_close(dp, info->midi_mapped); 308 midi_synth_dev.opened--; 309 } 310 } else { 311 rec = get_sdev(i); 312 if (rec == NULL) 313 continue; 314 if (rec->opened > 0) { 315 rec->oper.close(&info->arg); 316 module_put(rec->oper.owner); 317 rec->opened = 0; 318 } 319 snd_use_lock_free(&rec->use_lock); 320 } 321 kfree(info->sysex); 322 info->sysex = NULL; 323 kfree(info->ch); 324 info->ch = NULL; 325 } 326 dp->synth_opened = 0; 327 dp->max_synthdev = 0; 328} 329 330static struct seq_oss_synthinfo * 331get_synthinfo_nospec(struct seq_oss_devinfo *dp, int dev) 332{ 333 if (dev < 0 || dev >= dp->max_synthdev) 334 return NULL; 335 dev = array_index_nospec(dev, SNDRV_SEQ_OSS_MAX_SYNTH_DEVS); 336 return &dp->synths[dev]; 337} 338 339/* 340 * return synth device information pointer 341 */ 342static struct seq_oss_synth * 343get_synthdev(struct seq_oss_devinfo *dp, int dev) 344{ 345 struct seq_oss_synth *rec; 346 struct seq_oss_synthinfo *info = get_synthinfo_nospec(dp, dev); 347 348 if (!info) 349 return NULL; 350 if (!info->opened) 351 return NULL; 352 if (info->is_midi) { 353 rec = &midi_synth_dev; 354 snd_use_lock_use(&rec->use_lock); 355 } else { 356 rec = get_sdev(dev); 357 if (!rec) 358 return NULL; 359 } 360 if (! rec->opened) { 361 snd_use_lock_free(&rec->use_lock); 362 return NULL; 363 } 364 return rec; 365} 366 367 368/* 369 * reset note and velocity on each channel. 370 */ 371static void 372reset_channels(struct seq_oss_synthinfo *info) 373{ 374 int i; 375 if (info->ch == NULL || ! info->nr_voices) 376 return; 377 for (i = 0; i < info->nr_voices; i++) { 378 info->ch[i].note = -1; 379 info->ch[i].vel = 0; 380 } 381} 382 383 384/* 385 * reset synth device: 386 * call reset callback. if no callback is defined, send a heartbeat 387 * event to the corresponding port. 388 */ 389void 390snd_seq_oss_synth_reset(struct seq_oss_devinfo *dp, int dev) 391{ 392 struct seq_oss_synth *rec; 393 struct seq_oss_synthinfo *info; 394 395 info = get_synthinfo_nospec(dp, dev); 396 if (!info || !info->opened) 397 return; 398 if (info->sysex) 399 info->sysex->len = 0; /* reset sysex */ 400 reset_channels(info); 401 if (info->is_midi) { 402 if (midi_synth_dev.opened <= 0) 403 return; 404 snd_seq_oss_midi_reset(dp, info->midi_mapped); 405 /* reopen the device */ 406 snd_seq_oss_midi_close(dp, dev); 407 if (snd_seq_oss_midi_open(dp, info->midi_mapped, 408 dp->file_mode) < 0) { 409 midi_synth_dev.opened--; 410 info->opened = 0; 411 kfree(info->sysex); 412 info->sysex = NULL; 413 kfree(info->ch); 414 info->ch = NULL; 415 } 416 return; 417 } 418 419 rec = get_sdev(dev); 420 if (rec == NULL) 421 return; 422 if (rec->oper.reset) { 423 rec->oper.reset(&info->arg); 424 } else { 425 struct snd_seq_event ev; 426 memset(&ev, 0, sizeof(ev)); 427 snd_seq_oss_fill_addr(dp, &ev, info->arg.addr.client, 428 info->arg.addr.port); 429 ev.type = SNDRV_SEQ_EVENT_RESET; 430 snd_seq_oss_dispatch(dp, &ev, 0, 0); 431 } 432 snd_use_lock_free(&rec->use_lock); 433} 434 435 436/* 437 * load a patch record: 438 * call load_patch callback function 439 */ 440int 441snd_seq_oss_synth_load_patch(struct seq_oss_devinfo *dp, int dev, int fmt, 442 const char __user *buf, int p, int c) 443{ 444 struct seq_oss_synth *rec; 445 struct seq_oss_synthinfo *info; 446 int rc; 447 448 info = get_synthinfo_nospec(dp, dev); 449 if (!info) 450 return -ENXIO; 451 452 if (info->is_midi) 453 return 0; 454 rec = get_synthdev(dp, dev); 455 if (!rec) 456 return -ENXIO; 457 458 if (rec->oper.load_patch == NULL) 459 rc = -ENXIO; 460 else 461 rc = rec->oper.load_patch(&info->arg, fmt, buf, p, c); 462 snd_use_lock_free(&rec->use_lock); 463 return rc; 464} 465 466/* 467 * check if the device is valid synth device and return the synth info 468 */ 469struct seq_oss_synthinfo * 470snd_seq_oss_synth_info(struct seq_oss_devinfo *dp, int dev) 471{ 472 struct seq_oss_synth *rec; 473 474 rec = get_synthdev(dp, dev); 475 if (rec) { 476 snd_use_lock_free(&rec->use_lock); 477 return get_synthinfo_nospec(dp, dev); 478 } 479 return NULL; 480} 481 482 483/* 484 * receive OSS 6 byte sysex packet: 485 * the full sysex message will be sent if it reaches to the end of data 486 * (0xff). 487 */ 488int 489snd_seq_oss_synth_sysex(struct seq_oss_devinfo *dp, int dev, unsigned char *buf, struct snd_seq_event *ev) 490{ 491 int i, send; 492 unsigned char *dest; 493 struct seq_oss_synth_sysex *sysex; 494 struct seq_oss_synthinfo *info; 495 496 info = snd_seq_oss_synth_info(dp, dev); 497 if (!info) 498 return -ENXIO; 499 500 sysex = info->sysex; 501 if (sysex == NULL) { 502 sysex = kzalloc(sizeof(*sysex), GFP_KERNEL); 503 if (sysex == NULL) 504 return -ENOMEM; 505 info->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 struct seq_oss_synthinfo *info = snd_seq_oss_synth_info(dp, dev); 551 552 if (!info) 553 return -EINVAL; 554 snd_seq_oss_fill_addr(dp, ev, info->arg.addr.client, 555 info->arg.addr.port); 556 return 0; 557} 558 559 560/* 561 * OSS compatible ioctl 562 */ 563int 564snd_seq_oss_synth_ioctl(struct seq_oss_devinfo *dp, int dev, unsigned int cmd, unsigned long addr) 565{ 566 struct seq_oss_synth *rec; 567 struct seq_oss_synthinfo *info; 568 int rc; 569 570 info = get_synthinfo_nospec(dp, dev); 571 if (!info || info->is_midi) 572 return -ENXIO; 573 rec = get_synthdev(dp, dev); 574 if (!rec) 575 return -ENXIO; 576 if (rec->oper.ioctl == NULL) 577 rc = -ENXIO; 578 else 579 rc = rec->oper.ioctl(&info->arg, cmd, addr); 580 snd_use_lock_free(&rec->use_lock); 581 return rc; 582} 583 584 585/* 586 * send OSS raw events - SEQ_PRIVATE and SEQ_VOLUME 587 */ 588int 589snd_seq_oss_synth_raw_event(struct seq_oss_devinfo *dp, int dev, unsigned char *data, struct snd_seq_event *ev) 590{ 591 struct seq_oss_synthinfo *info; 592 593 info = snd_seq_oss_synth_info(dp, dev); 594 if (!info || info->is_midi) 595 return -ENXIO; 596 ev->type = SNDRV_SEQ_EVENT_OSS; 597 memcpy(ev->data.raw8.d, data, 8); 598 return snd_seq_oss_synth_addr(dp, dev, ev); 599} 600 601 602/* 603 * create OSS compatible synth_info record 604 */ 605int 606snd_seq_oss_synth_make_info(struct seq_oss_devinfo *dp, int dev, struct synth_info *inf) 607{ 608 struct seq_oss_synth *rec; 609 struct seq_oss_synthinfo *info = get_synthinfo_nospec(dp, dev); 610 611 if (!info) 612 return -ENXIO; 613 614 if (info->is_midi) { 615 struct midi_info minf; 616 if (snd_seq_oss_midi_make_info(dp, info->midi_mapped, &minf)) 617 return -ENXIO; 618 inf->synth_type = SYNTH_TYPE_MIDI; 619 inf->synth_subtype = 0; 620 inf->nr_voices = 16; 621 inf->device = dev; 622 strscpy(inf->name, minf.name, sizeof(inf->name)); 623 } else { 624 rec = get_synthdev(dp, dev); 625 if (!rec) 626 return -ENXIO; 627 inf->synth_type = rec->synth_type; 628 inf->synth_subtype = rec->synth_subtype; 629 inf->nr_voices = rec->nr_voices; 630 inf->device = dev; 631 strscpy(inf->name, rec->name, sizeof(inf->name)); 632 snd_use_lock_free(&rec->use_lock); 633 } 634 return 0; 635} 636 637 638#ifdef CONFIG_SND_PROC_FS 639/* 640 * proc interface 641 */ 642void 643snd_seq_oss_synth_info_read(struct snd_info_buffer *buf) 644{ 645 int i; 646 struct seq_oss_synth *rec; 647 648 snd_iprintf(buf, "\nNumber of synth devices: %d\n", max_synth_devs); 649 for (i = 0; i < max_synth_devs; i++) { 650 snd_iprintf(buf, "\nsynth %d: ", i); 651 rec = get_sdev(i); 652 if (rec == NULL) { 653 snd_iprintf(buf, "*empty*\n"); 654 continue; 655 } 656 snd_iprintf(buf, "[%s]\n", rec->name); 657 snd_iprintf(buf, " type 0x%x : subtype 0x%x : voices %d\n", 658 rec->synth_type, rec->synth_subtype, 659 rec->nr_voices); 660 snd_iprintf(buf, " capabilities : ioctl %s / load_patch %s\n", 661 enabled_str((long)rec->oper.ioctl), 662 enabled_str((long)rec->oper.load_patch)); 663 snd_use_lock_free(&rec->use_lock); 664 } 665} 666#endif /* CONFIG_SND_PROC_FS */