linux/sound/core/seq/oss/seq_oss_synth.c
<<
>>
Prefs
   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(&register_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(&register_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(&register_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(&register_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(&register_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(&register_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(&register_lock, flags);
 187        rec = synth_devs[dev];
 188        if (rec)
 189                snd_use_lock_use(&rec->use_lock);
 190        spin_unlock_irqrestore(&register_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 */
 667