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