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/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        .seq_device = -1,
  74        .synth_type = SYNTH_TYPE_MIDI,
  75        .synth_subtype = 0,
  76        .nr_voices = 16,
  77        .name = "MIDI",
  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_probe(struct device *_dev)
 102{
 103        struct snd_seq_device *dev = to_seq_dev(_dev);
 104        int i;
 105        struct seq_oss_synth *rec;
 106        struct snd_seq_oss_reg *reg = SNDRV_SEQ_DEVICE_ARGPTR(dev);
 107        unsigned long flags;
 108
 109        rec = kzalloc(sizeof(*rec), GFP_KERNEL);
 110        if (!rec)
 111                return -ENOMEM;
 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                        pr_err("ALSA: seq_oss: 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        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_remove(struct device *_dev)
 153{
 154        struct snd_seq_device *dev = to_seq_dev(_dev);
 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                pr_err("ALSA: seq_oss: 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                                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                info->opened++;
 259                rec->opened++;
 260                dp->synth_opened++;
 261                snd_use_lock_free(&rec->use_lock);
 262        }
 263}
 264
 265
 266/*
 267 * set up synth tables for MIDI emulation - /dev/music mode only
 268 */
 269
 270void
 271snd_seq_oss_synth_setup_midi(struct seq_oss_devinfo *dp)
 272{
 273        int i;
 274
 275        if (dp->max_synthdev >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS)
 276                return;
 277
 278        for (i = 0; i < dp->max_mididev; i++) {
 279                struct seq_oss_synthinfo *info;
 280                info = &dp->synths[dp->max_synthdev];
 281                if (snd_seq_oss_midi_open(dp, i, dp->file_mode) < 0)
 282                        continue;
 283                info->arg.app_index = dp->port;
 284                info->arg.file_mode = dp->file_mode;
 285                info->arg.seq_mode = dp->seq_mode;
 286                info->arg.private_data = info;
 287                info->is_midi = 1;
 288                info->midi_mapped = i;
 289                info->arg.event_passing = SNDRV_SEQ_OSS_PASS_EVENTS;
 290                snd_seq_oss_midi_get_addr(dp, i, &info->arg.addr);
 291                info->opened = 1;
 292                midi_synth_dev.opened++;
 293                dp->max_synthdev++;
 294                if (dp->max_synthdev >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS)
 295                        break;
 296        }
 297}
 298
 299
 300/*
 301 * clean up synth tables
 302 */
 303
 304void
 305snd_seq_oss_synth_cleanup(struct seq_oss_devinfo *dp)
 306{
 307        int i;
 308        struct seq_oss_synth *rec;
 309        struct seq_oss_synthinfo *info;
 310
 311        if (snd_BUG_ON(dp->max_synthdev > SNDRV_SEQ_OSS_MAX_SYNTH_DEVS))
 312                return;
 313        for (i = 0; i < dp->max_synthdev; i++) {
 314                info = &dp->synths[i];
 315                if (! info->opened)
 316                        continue;
 317                if (info->is_midi) {
 318                        if (midi_synth_dev.opened > 0) {
 319                                snd_seq_oss_midi_close(dp, info->midi_mapped);
 320                                midi_synth_dev.opened--;
 321                        }
 322                } else {
 323                        rec = get_sdev(i);
 324                        if (rec == NULL)
 325                                continue;
 326                        if (rec->opened > 0) {
 327                                rec->oper.close(&info->arg);
 328                                module_put(rec->oper.owner);
 329                                rec->opened = 0;
 330                        }
 331                        snd_use_lock_free(&rec->use_lock);
 332                }
 333                kfree(info->sysex);
 334                info->sysex = NULL;
 335                kfree(info->ch);
 336                info->ch = NULL;
 337        }
 338        dp->synth_opened = 0;
 339        dp->max_synthdev = 0;
 340}
 341
 342/*
 343 * check if the specified device is MIDI mapped device
 344 */
 345static int
 346is_midi_dev(struct seq_oss_devinfo *dp, int dev)
 347{
 348        if (dev < 0 || dev >= dp->max_synthdev)
 349                return 0;
 350        if (dp->synths[dev].is_midi)
 351                return 1;
 352        return 0;
 353}
 354
 355/*
 356 * return synth device information pointer
 357 */
 358static struct seq_oss_synth *
 359get_synthdev(struct seq_oss_devinfo *dp, int dev)
 360{
 361        struct seq_oss_synth *rec;
 362        if (dev < 0 || dev >= dp->max_synthdev)
 363                return NULL;
 364        if (! dp->synths[dev].opened)
 365                return NULL;
 366        if (dp->synths[dev].is_midi)
 367                return &midi_synth_dev;
 368        if ((rec = get_sdev(dev)) == NULL)
 369                return NULL;
 370        if (! rec->opened) {
 371                snd_use_lock_free(&rec->use_lock);
 372                return NULL;
 373        }
 374        return rec;
 375}
 376
 377
 378/*
 379 * reset note and velocity on each channel.
 380 */
 381static void
 382reset_channels(struct seq_oss_synthinfo *info)
 383{
 384        int i;
 385        if (info->ch == NULL || ! info->nr_voices)
 386                return;
 387        for (i = 0; i < info->nr_voices; i++) {
 388                info->ch[i].note = -1;
 389                info->ch[i].vel = 0;
 390        }
 391}
 392
 393
 394/*
 395 * reset synth device:
 396 * call reset callback.  if no callback is defined, send a heartbeat
 397 * event to the corresponding port.
 398 */
 399void
 400snd_seq_oss_synth_reset(struct seq_oss_devinfo *dp, int dev)
 401{
 402        struct seq_oss_synth *rec;
 403        struct seq_oss_synthinfo *info;
 404
 405        if (snd_BUG_ON(dev < 0 || dev >= dp->max_synthdev))
 406                return;
 407        info = &dp->synths[dev];
 408        if (! info->opened)
 409                return;
 410        if (info->sysex)
 411                info->sysex->len = 0; /* reset sysex */
 412        reset_channels(info);
 413        if (info->is_midi) {
 414                if (midi_synth_dev.opened <= 0)
 415                        return;
 416                snd_seq_oss_midi_reset(dp, info->midi_mapped);
 417                /* reopen the device */
 418                snd_seq_oss_midi_close(dp, dev);
 419                if (snd_seq_oss_midi_open(dp, info->midi_mapped,
 420                                          dp->file_mode) < 0) {
 421                        midi_synth_dev.opened--;
 422                        info->opened = 0;
 423                        kfree(info->sysex);
 424                        info->sysex = NULL;
 425                        kfree(info->ch);
 426                        info->ch = NULL;
 427                }
 428                return;
 429        }
 430
 431        rec = get_sdev(dev);
 432        if (rec == NULL)
 433                return;
 434        if (rec->oper.reset) {
 435                rec->oper.reset(&info->arg);
 436        } else {
 437                struct snd_seq_event ev;
 438                memset(&ev, 0, sizeof(ev));
 439                snd_seq_oss_fill_addr(dp, &ev, info->arg.addr.client,
 440                                      info->arg.addr.port);
 441                ev.type = SNDRV_SEQ_EVENT_RESET;
 442                snd_seq_oss_dispatch(dp, &ev, 0, 0);
 443        }
 444        snd_use_lock_free(&rec->use_lock);
 445}
 446
 447
 448/*
 449 * load a patch record:
 450 * call load_patch callback function
 451 */
 452int
 453snd_seq_oss_synth_load_patch(struct seq_oss_devinfo *dp, int dev, int fmt,
 454                            const char __user *buf, int p, int c)
 455{
 456        struct seq_oss_synth *rec;
 457        int rc;
 458
 459        if (dev < 0 || dev >= dp->max_synthdev)
 460                return -ENXIO;
 461
 462        if (is_midi_dev(dp, dev))
 463                return 0;
 464        if ((rec = get_synthdev(dp, dev)) == NULL)
 465                return -ENXIO;
 466
 467        if (rec->oper.load_patch == NULL)
 468                rc = -ENXIO;
 469        else
 470                rc = rec->oper.load_patch(&dp->synths[dev].arg, fmt, buf, p, c);
 471        snd_use_lock_free(&rec->use_lock);
 472        return rc;
 473}
 474
 475/*
 476 * check if the device is valid synth device
 477 */
 478int
 479snd_seq_oss_synth_is_valid(struct seq_oss_devinfo *dp, int dev)
 480{
 481        struct seq_oss_synth *rec;
 482        rec = get_synthdev(dp, dev);
 483        if (rec) {
 484                snd_use_lock_free(&rec->use_lock);
 485                return 1;
 486        }
 487        return 0;
 488}
 489
 490
 491/*
 492 * receive OSS 6 byte sysex packet:
 493 * the full sysex message will be sent if it reaches to the end of data
 494 * (0xff).
 495 */
 496int
 497snd_seq_oss_synth_sysex(struct seq_oss_devinfo *dp, int dev, unsigned char *buf, struct snd_seq_event *ev)
 498{
 499        int i, send;
 500        unsigned char *dest;
 501        struct seq_oss_synth_sysex *sysex;
 502
 503        if (! snd_seq_oss_synth_is_valid(dp, dev))
 504                return -ENXIO;
 505
 506        sysex = dp->synths[dev].sysex;
 507        if (sysex == NULL) {
 508                sysex = kzalloc(sizeof(*sysex), GFP_KERNEL);
 509                if (sysex == NULL)
 510                        return -ENOMEM;
 511                dp->synths[dev].sysex = sysex;
 512        }
 513
 514        send = 0;
 515        dest = sysex->buf + sysex->len;
 516        /* copy 6 byte packet to the buffer */
 517        for (i = 0; i < 6; i++) {
 518                if (buf[i] == 0xff) {
 519                        send = 1;
 520                        break;
 521                }
 522                dest[i] = buf[i];
 523                sysex->len++;
 524                if (sysex->len >= MAX_SYSEX_BUFLEN) {
 525                        sysex->len = 0;
 526                        sysex->skip = 1;
 527                        break;
 528                }
 529        }
 530
 531        if (sysex->len && send) {
 532                if (sysex->skip) {
 533                        sysex->skip = 0;
 534                        sysex->len = 0;
 535                        return -EINVAL; /* skip */
 536                }
 537                /* copy the data to event record and send it */
 538                ev->flags = SNDRV_SEQ_EVENT_LENGTH_VARIABLE;
 539                if (snd_seq_oss_synth_addr(dp, dev, ev))
 540                        return -EINVAL;
 541                ev->data.ext.len = sysex->len;
 542                ev->data.ext.ptr = sysex->buf;
 543                sysex->len = 0;
 544                return 0;
 545        }
 546
 547        return -EINVAL; /* skip */
 548}
 549
 550/*
 551 * fill the event source/destination addresses
 552 */
 553int
 554snd_seq_oss_synth_addr(struct seq_oss_devinfo *dp, int dev, struct snd_seq_event *ev)
 555{
 556        if (! snd_seq_oss_synth_is_valid(dp, dev))
 557                return -EINVAL;
 558        snd_seq_oss_fill_addr(dp, ev, dp->synths[dev].arg.addr.client,
 559                              dp->synths[dev].arg.addr.port);
 560        return 0;
 561}
 562
 563
 564/*
 565 * OSS compatible ioctl
 566 */
 567int
 568snd_seq_oss_synth_ioctl(struct seq_oss_devinfo *dp, int dev, unsigned int cmd, unsigned long addr)
 569{
 570        struct seq_oss_synth *rec;
 571        int rc;
 572
 573        if (is_midi_dev(dp, dev))
 574                return -ENXIO;
 575        if ((rec = get_synthdev(dp, dev)) == NULL)
 576                return -ENXIO;
 577        if (rec->oper.ioctl == NULL)
 578                rc = -ENXIO;
 579        else
 580                rc = rec->oper.ioctl(&dp->synths[dev].arg, cmd, addr);
 581        snd_use_lock_free(&rec->use_lock);
 582        return rc;
 583}
 584
 585
 586/*
 587 * send OSS raw events - SEQ_PRIVATE and SEQ_VOLUME
 588 */
 589int
 590snd_seq_oss_synth_raw_event(struct seq_oss_devinfo *dp, int dev, unsigned char *data, struct snd_seq_event *ev)
 591{
 592        if (! snd_seq_oss_synth_is_valid(dp, dev) || is_midi_dev(dp, dev))
 593                return -ENXIO;
 594        ev->type = SNDRV_SEQ_EVENT_OSS;
 595        memcpy(ev->data.raw8.d, data, 8);
 596        return snd_seq_oss_synth_addr(dp, dev, ev);
 597}
 598
 599
 600/*
 601 * create OSS compatible synth_info record
 602 */
 603int
 604snd_seq_oss_synth_make_info(struct seq_oss_devinfo *dp, int dev, struct synth_info *inf)
 605{
 606        struct seq_oss_synth *rec;
 607
 608        if (dev < 0 || dev >= dp->max_synthdev)
 609                return -ENXIO;
 610
 611        if (dp->synths[dev].is_midi) {
 612                struct midi_info minf;
 613                snd_seq_oss_midi_make_info(dp, dp->synths[dev].midi_mapped, &minf);
 614                inf->synth_type = SYNTH_TYPE_MIDI;
 615                inf->synth_subtype = 0;
 616                inf->nr_voices = 16;
 617                inf->device = dev;
 618                strlcpy(inf->name, minf.name, sizeof(inf->name));
 619        } else {
 620                if ((rec = get_synthdev(dp, dev)) == NULL)
 621                        return -ENXIO;
 622                inf->synth_type = rec->synth_type;
 623                inf->synth_subtype = rec->synth_subtype;
 624                inf->nr_voices = rec->nr_voices;
 625                inf->device = dev;
 626                strlcpy(inf->name, rec->name, sizeof(inf->name));
 627                snd_use_lock_free(&rec->use_lock);
 628        }
 629        return 0;
 630}
 631
 632
 633#ifdef CONFIG_SND_PROC_FS
 634/*
 635 * proc interface
 636 */
 637void
 638snd_seq_oss_synth_info_read(struct snd_info_buffer *buf)
 639{
 640        int i;
 641        struct seq_oss_synth *rec;
 642
 643        snd_iprintf(buf, "\nNumber of synth devices: %d\n", max_synth_devs);
 644        for (i = 0; i < max_synth_devs; i++) {
 645                snd_iprintf(buf, "\nsynth %d: ", i);
 646                rec = get_sdev(i);
 647                if (rec == NULL) {
 648                        snd_iprintf(buf, "*empty*\n");
 649                        continue;
 650                }
 651                snd_iprintf(buf, "[%s]\n", rec->name);
 652                snd_iprintf(buf, "  type 0x%x : subtype 0x%x : voices %d\n",
 653                            rec->synth_type, rec->synth_subtype,
 654                            rec->nr_voices);
 655                snd_iprintf(buf, "  capabilities : ioctl %s / load_patch %s\n",
 656                            enabled_str((long)rec->oper.ioctl),
 657                            enabled_str((long)rec->oper.load_patch));
 658                snd_use_lock_free(&rec->use_lock);
 659        }
 660}
 661#endif /* CONFIG_SND_PROC_FS */
 662