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