Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * OSS compatible sequencer driver
0004  *
0005  * synth device handlers
0006  *
0007  * Copyright (C) 1998,99 Takashi Iwai <tiwai@suse.de>
0008  */
0009 
0010 #include "seq_oss_synth.h"
0011 #include "seq_oss_midi.h"
0012 #include "../seq_lock.h"
0013 #include <linux/init.h>
0014 #include <linux/module.h>
0015 #include <linux/slab.h>
0016 #include <linux/nospec.h>
0017 
0018 /*
0019  * constants
0020  */
0021 #define SNDRV_SEQ_OSS_MAX_SYNTH_NAME    30
0022 #define MAX_SYSEX_BUFLEN        128
0023 
0024 
0025 /*
0026  * definition of synth info records
0027  */
0028 
0029 /* sysex buffer */
0030 struct seq_oss_synth_sysex {
0031     int len;
0032     int skip;
0033     unsigned char buf[MAX_SYSEX_BUFLEN];
0034 };
0035 
0036 /* synth info */
0037 struct seq_oss_synth {
0038     int seq_device;
0039 
0040     /* for synth_info */
0041     int synth_type;
0042     int synth_subtype;
0043     int nr_voices;
0044 
0045     char name[SNDRV_SEQ_OSS_MAX_SYNTH_NAME];
0046     struct snd_seq_oss_callback oper;
0047 
0048     int opened;
0049 
0050     void *private_data;
0051     snd_use_lock_t use_lock;
0052 };
0053 
0054 
0055 /*
0056  * device table
0057  */
0058 static int max_synth_devs;
0059 static struct seq_oss_synth *synth_devs[SNDRV_SEQ_OSS_MAX_SYNTH_DEVS];
0060 static struct seq_oss_synth midi_synth_dev = {
0061     .seq_device = -1,
0062     .synth_type = SYNTH_TYPE_MIDI,
0063     .synth_subtype = 0,
0064     .nr_voices = 16,
0065     .name = "MIDI",
0066 };
0067 
0068 static DEFINE_SPINLOCK(register_lock);
0069 
0070 /*
0071  * prototypes
0072  */
0073 static struct seq_oss_synth *get_synthdev(struct seq_oss_devinfo *dp, int dev);
0074 static void reset_channels(struct seq_oss_synthinfo *info);
0075 
0076 /*
0077  * global initialization
0078  */
0079 void __init
0080 snd_seq_oss_synth_init(void)
0081 {
0082     snd_use_lock_init(&midi_synth_dev.use_lock);
0083 }
0084 
0085 /*
0086  * registration of the synth device
0087  */
0088 int
0089 snd_seq_oss_synth_probe(struct device *_dev)
0090 {
0091     struct snd_seq_device *dev = to_seq_dev(_dev);
0092     int i;
0093     struct seq_oss_synth *rec;
0094     struct snd_seq_oss_reg *reg = SNDRV_SEQ_DEVICE_ARGPTR(dev);
0095     unsigned long flags;
0096 
0097     rec = kzalloc(sizeof(*rec), GFP_KERNEL);
0098     if (!rec)
0099         return -ENOMEM;
0100     rec->seq_device = -1;
0101     rec->synth_type = reg->type;
0102     rec->synth_subtype = reg->subtype;
0103     rec->nr_voices = reg->nvoices;
0104     rec->oper = reg->oper;
0105     rec->private_data = reg->private_data;
0106     rec->opened = 0;
0107     snd_use_lock_init(&rec->use_lock);
0108 
0109     /* copy and truncate the name of synth device */
0110     strscpy(rec->name, dev->name, sizeof(rec->name));
0111 
0112     /* registration */
0113     spin_lock_irqsave(&register_lock, flags);
0114     for (i = 0; i < max_synth_devs; i++) {
0115         if (synth_devs[i] == NULL)
0116             break;
0117     }
0118     if (i >= max_synth_devs) {
0119         if (max_synth_devs >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS) {
0120             spin_unlock_irqrestore(&register_lock, flags);
0121             pr_err("ALSA: seq_oss: no more synth slot\n");
0122             kfree(rec);
0123             return -ENOMEM;
0124         }
0125         max_synth_devs++;
0126     }
0127     rec->seq_device = i;
0128     synth_devs[i] = rec;
0129     spin_unlock_irqrestore(&register_lock, flags);
0130     dev->driver_data = rec;
0131 #ifdef SNDRV_OSS_INFO_DEV_SYNTH
0132     if (i < SNDRV_CARDS)
0133         snd_oss_info_register(SNDRV_OSS_INFO_DEV_SYNTH, i, rec->name);
0134 #endif
0135     return 0;
0136 }
0137 
0138 
0139 int
0140 snd_seq_oss_synth_remove(struct device *_dev)
0141 {
0142     struct snd_seq_device *dev = to_seq_dev(_dev);
0143     int index;
0144     struct seq_oss_synth *rec = dev->driver_data;
0145     unsigned long flags;
0146 
0147     spin_lock_irqsave(&register_lock, flags);
0148     for (index = 0; index < max_synth_devs; index++) {
0149         if (synth_devs[index] == rec)
0150             break;
0151     }
0152     if (index >= max_synth_devs) {
0153         spin_unlock_irqrestore(&register_lock, flags);
0154         pr_err("ALSA: seq_oss: can't unregister synth\n");
0155         return -EINVAL;
0156     }
0157     synth_devs[index] = NULL;
0158     if (index == max_synth_devs - 1) {
0159         for (index--; index >= 0; index--) {
0160             if (synth_devs[index])
0161                 break;
0162         }
0163         max_synth_devs = index + 1;
0164     }
0165     spin_unlock_irqrestore(&register_lock, flags);
0166 #ifdef SNDRV_OSS_INFO_DEV_SYNTH
0167     if (rec->seq_device < SNDRV_CARDS)
0168         snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_SYNTH, rec->seq_device);
0169 #endif
0170 
0171     snd_use_lock_sync(&rec->use_lock);
0172     kfree(rec);
0173 
0174     return 0;
0175 }
0176 
0177 
0178 /*
0179  */
0180 static struct seq_oss_synth *
0181 get_sdev(int dev)
0182 {
0183     struct seq_oss_synth *rec;
0184     unsigned long flags;
0185 
0186     spin_lock_irqsave(&register_lock, flags);
0187     rec = synth_devs[dev];
0188     if (rec)
0189         snd_use_lock_use(&rec->use_lock);
0190     spin_unlock_irqrestore(&register_lock, flags);
0191     return rec;
0192 }
0193 
0194 
0195 /*
0196  * set up synth tables
0197  */
0198 
0199 void
0200 snd_seq_oss_synth_setup(struct seq_oss_devinfo *dp)
0201 {
0202     int i;
0203     struct seq_oss_synth *rec;
0204     struct seq_oss_synthinfo *info;
0205 
0206     dp->max_synthdev = max_synth_devs;
0207     dp->synth_opened = 0;
0208     memset(dp->synths, 0, sizeof(dp->synths));
0209     for (i = 0; i < dp->max_synthdev; i++) {
0210         rec = get_sdev(i);
0211         if (rec == NULL)
0212             continue;
0213         if (rec->oper.open == NULL || rec->oper.close == NULL) {
0214             snd_use_lock_free(&rec->use_lock);
0215             continue;
0216         }
0217         info = &dp->synths[i];
0218         info->arg.app_index = dp->port;
0219         info->arg.file_mode = dp->file_mode;
0220         info->arg.seq_mode = dp->seq_mode;
0221         if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_SYNTH)
0222             info->arg.event_passing = SNDRV_SEQ_OSS_PROCESS_EVENTS;
0223         else
0224             info->arg.event_passing = SNDRV_SEQ_OSS_PASS_EVENTS;
0225         info->opened = 0;
0226         if (!try_module_get(rec->oper.owner)) {
0227             snd_use_lock_free(&rec->use_lock);
0228             continue;
0229         }
0230         if (rec->oper.open(&info->arg, rec->private_data) < 0) {
0231             module_put(rec->oper.owner);
0232             snd_use_lock_free(&rec->use_lock);
0233             continue;
0234         }
0235         info->nr_voices = rec->nr_voices;
0236         if (info->nr_voices > 0) {
0237             info->ch = kcalloc(info->nr_voices, sizeof(struct seq_oss_chinfo), GFP_KERNEL);
0238             if (!info->ch) {
0239                 rec->oper.close(&info->arg);
0240                 module_put(rec->oper.owner);
0241                 snd_use_lock_free(&rec->use_lock);
0242                 continue;
0243             }
0244             reset_channels(info);
0245         }
0246         info->opened++;
0247         rec->opened++;
0248         dp->synth_opened++;
0249         snd_use_lock_free(&rec->use_lock);
0250     }
0251 }
0252 
0253 
0254 /*
0255  * set up synth tables for MIDI emulation - /dev/music mode only
0256  */
0257 
0258 void
0259 snd_seq_oss_synth_setup_midi(struct seq_oss_devinfo *dp)
0260 {
0261     int i;
0262 
0263     if (dp->max_synthdev >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS)
0264         return;
0265 
0266     for (i = 0; i < dp->max_mididev; i++) {
0267         struct seq_oss_synthinfo *info;
0268         info = &dp->synths[dp->max_synthdev];
0269         if (snd_seq_oss_midi_open(dp, i, dp->file_mode) < 0)
0270             continue;
0271         info->arg.app_index = dp->port;
0272         info->arg.file_mode = dp->file_mode;
0273         info->arg.seq_mode = dp->seq_mode;
0274         info->arg.private_data = info;
0275         info->is_midi = 1;
0276         info->midi_mapped = i;
0277         info->arg.event_passing = SNDRV_SEQ_OSS_PASS_EVENTS;
0278         snd_seq_oss_midi_get_addr(dp, i, &info->arg.addr);
0279         info->opened = 1;
0280         midi_synth_dev.opened++;
0281         dp->max_synthdev++;
0282         if (dp->max_synthdev >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS)
0283             break;
0284     }
0285 }
0286 
0287 
0288 /*
0289  * clean up synth tables
0290  */
0291 
0292 void
0293 snd_seq_oss_synth_cleanup(struct seq_oss_devinfo *dp)
0294 {
0295     int i;
0296     struct seq_oss_synth *rec;
0297     struct seq_oss_synthinfo *info;
0298 
0299     if (snd_BUG_ON(dp->max_synthdev > SNDRV_SEQ_OSS_MAX_SYNTH_DEVS))
0300         return;
0301     for (i = 0; i < dp->max_synthdev; i++) {
0302         info = &dp->synths[i];
0303         if (! info->opened)
0304             continue;
0305         if (info->is_midi) {
0306             if (midi_synth_dev.opened > 0) {
0307                 snd_seq_oss_midi_close(dp, info->midi_mapped);
0308                 midi_synth_dev.opened--;
0309             }
0310         } else {
0311             rec = get_sdev(i);
0312             if (rec == NULL)
0313                 continue;
0314             if (rec->opened > 0) {
0315                 rec->oper.close(&info->arg);
0316                 module_put(rec->oper.owner);
0317                 rec->opened = 0;
0318             }
0319             snd_use_lock_free(&rec->use_lock);
0320         }
0321         kfree(info->sysex);
0322         info->sysex = NULL;
0323         kfree(info->ch);
0324         info->ch = NULL;
0325     }
0326     dp->synth_opened = 0;
0327     dp->max_synthdev = 0;
0328 }
0329 
0330 static struct seq_oss_synthinfo *
0331 get_synthinfo_nospec(struct seq_oss_devinfo *dp, int dev)
0332 {
0333     if (dev < 0 || dev >= dp->max_synthdev)
0334         return NULL;
0335     dev = array_index_nospec(dev, SNDRV_SEQ_OSS_MAX_SYNTH_DEVS);
0336     return &dp->synths[dev];
0337 }
0338 
0339 /*
0340  * return synth device information pointer
0341  */
0342 static struct seq_oss_synth *
0343 get_synthdev(struct seq_oss_devinfo *dp, int dev)
0344 {
0345     struct seq_oss_synth *rec;
0346     struct seq_oss_synthinfo *info = get_synthinfo_nospec(dp, dev);
0347 
0348     if (!info)
0349         return NULL;
0350     if (!info->opened)
0351         return NULL;
0352     if (info->is_midi) {
0353         rec = &midi_synth_dev;
0354         snd_use_lock_use(&rec->use_lock);
0355     } else {
0356         rec = get_sdev(dev);
0357         if (!rec)
0358             return NULL;
0359     }
0360     if (! rec->opened) {
0361         snd_use_lock_free(&rec->use_lock);
0362         return NULL;
0363     }
0364     return rec;
0365 }
0366 
0367 
0368 /*
0369  * reset note and velocity on each channel.
0370  */
0371 static void
0372 reset_channels(struct seq_oss_synthinfo *info)
0373 {
0374     int i;
0375     if (info->ch == NULL || ! info->nr_voices)
0376         return;
0377     for (i = 0; i < info->nr_voices; i++) {
0378         info->ch[i].note = -1;
0379         info->ch[i].vel = 0;
0380     }
0381 }
0382 
0383 
0384 /*
0385  * reset synth device:
0386  * call reset callback.  if no callback is defined, send a heartbeat
0387  * event to the corresponding port.
0388  */
0389 void
0390 snd_seq_oss_synth_reset(struct seq_oss_devinfo *dp, int dev)
0391 {
0392     struct seq_oss_synth *rec;
0393     struct seq_oss_synthinfo *info;
0394 
0395     info = get_synthinfo_nospec(dp, dev);
0396     if (!info || !info->opened)
0397         return;
0398     if (info->sysex)
0399         info->sysex->len = 0; /* reset sysex */
0400     reset_channels(info);
0401     if (info->is_midi) {
0402         if (midi_synth_dev.opened <= 0)
0403             return;
0404         snd_seq_oss_midi_reset(dp, info->midi_mapped);
0405         /* reopen the device */
0406         snd_seq_oss_midi_close(dp, dev);
0407         if (snd_seq_oss_midi_open(dp, info->midi_mapped,
0408                       dp->file_mode) < 0) {
0409             midi_synth_dev.opened--;
0410             info->opened = 0;
0411             kfree(info->sysex);
0412             info->sysex = NULL;
0413             kfree(info->ch);
0414             info->ch = NULL;
0415         }
0416         return;
0417     }
0418 
0419     rec = get_sdev(dev);
0420     if (rec == NULL)
0421         return;
0422     if (rec->oper.reset) {
0423         rec->oper.reset(&info->arg);
0424     } else {
0425         struct snd_seq_event ev;
0426         memset(&ev, 0, sizeof(ev));
0427         snd_seq_oss_fill_addr(dp, &ev, info->arg.addr.client,
0428                       info->arg.addr.port);
0429         ev.type = SNDRV_SEQ_EVENT_RESET;
0430         snd_seq_oss_dispatch(dp, &ev, 0, 0);
0431     }
0432     snd_use_lock_free(&rec->use_lock);
0433 }
0434 
0435 
0436 /*
0437  * load a patch record:
0438  * call load_patch callback function
0439  */
0440 int
0441 snd_seq_oss_synth_load_patch(struct seq_oss_devinfo *dp, int dev, int fmt,
0442                 const char __user *buf, int p, int c)
0443 {
0444     struct seq_oss_synth *rec;
0445     struct seq_oss_synthinfo *info;
0446     int rc;
0447 
0448     info = get_synthinfo_nospec(dp, dev);
0449     if (!info)
0450         return -ENXIO;
0451 
0452     if (info->is_midi)
0453         return 0;
0454     rec = get_synthdev(dp, dev);
0455     if (!rec)
0456         return -ENXIO;
0457 
0458     if (rec->oper.load_patch == NULL)
0459         rc = -ENXIO;
0460     else
0461         rc = rec->oper.load_patch(&info->arg, fmt, buf, p, c);
0462     snd_use_lock_free(&rec->use_lock);
0463     return rc;
0464 }
0465 
0466 /*
0467  * check if the device is valid synth device and return the synth info
0468  */
0469 struct seq_oss_synthinfo *
0470 snd_seq_oss_synth_info(struct seq_oss_devinfo *dp, int dev)
0471 {
0472     struct seq_oss_synth *rec;
0473 
0474     rec = get_synthdev(dp, dev);
0475     if (rec) {
0476         snd_use_lock_free(&rec->use_lock);
0477         return get_synthinfo_nospec(dp, dev);
0478     }
0479     return NULL;
0480 }
0481 
0482 
0483 /*
0484  * receive OSS 6 byte sysex packet:
0485  * the full sysex message will be sent if it reaches to the end of data
0486  * (0xff).
0487  */
0488 int
0489 snd_seq_oss_synth_sysex(struct seq_oss_devinfo *dp, int dev, unsigned char *buf, struct snd_seq_event *ev)
0490 {
0491     int i, send;
0492     unsigned char *dest;
0493     struct seq_oss_synth_sysex *sysex;
0494     struct seq_oss_synthinfo *info;
0495 
0496     info = snd_seq_oss_synth_info(dp, dev);
0497     if (!info)
0498         return -ENXIO;
0499 
0500     sysex = info->sysex;
0501     if (sysex == NULL) {
0502         sysex = kzalloc(sizeof(*sysex), GFP_KERNEL);
0503         if (sysex == NULL)
0504             return -ENOMEM;
0505         info->sysex = sysex;
0506     }
0507 
0508     send = 0;
0509     dest = sysex->buf + sysex->len;
0510     /* copy 6 byte packet to the buffer */
0511     for (i = 0; i < 6; i++) {
0512         if (buf[i] == 0xff) {
0513             send = 1;
0514             break;
0515         }
0516         dest[i] = buf[i];
0517         sysex->len++;
0518         if (sysex->len >= MAX_SYSEX_BUFLEN) {
0519             sysex->len = 0;
0520             sysex->skip = 1;
0521             break;
0522         }
0523     }
0524 
0525     if (sysex->len && send) {
0526         if (sysex->skip) {
0527             sysex->skip = 0;
0528             sysex->len = 0;
0529             return -EINVAL; /* skip */
0530         }
0531         /* copy the data to event record and send it */
0532         ev->flags = SNDRV_SEQ_EVENT_LENGTH_VARIABLE;
0533         if (snd_seq_oss_synth_addr(dp, dev, ev))
0534             return -EINVAL;
0535         ev->data.ext.len = sysex->len;
0536         ev->data.ext.ptr = sysex->buf;
0537         sysex->len = 0;
0538         return 0;
0539     }
0540 
0541     return -EINVAL; /* skip */
0542 }
0543 
0544 /*
0545  * fill the event source/destination addresses
0546  */
0547 int
0548 snd_seq_oss_synth_addr(struct seq_oss_devinfo *dp, int dev, struct snd_seq_event *ev)
0549 {
0550     struct seq_oss_synthinfo *info = snd_seq_oss_synth_info(dp, dev);
0551 
0552     if (!info)
0553         return -EINVAL;
0554     snd_seq_oss_fill_addr(dp, ev, info->arg.addr.client,
0555                   info->arg.addr.port);
0556     return 0;
0557 }
0558 
0559 
0560 /*
0561  * OSS compatible ioctl
0562  */
0563 int
0564 snd_seq_oss_synth_ioctl(struct seq_oss_devinfo *dp, int dev, unsigned int cmd, unsigned long addr)
0565 {
0566     struct seq_oss_synth *rec;
0567     struct seq_oss_synthinfo *info;
0568     int rc;
0569 
0570     info = get_synthinfo_nospec(dp, dev);
0571     if (!info || info->is_midi)
0572         return -ENXIO;
0573     rec = get_synthdev(dp, dev);
0574     if (!rec)
0575         return -ENXIO;
0576     if (rec->oper.ioctl == NULL)
0577         rc = -ENXIO;
0578     else
0579         rc = rec->oper.ioctl(&info->arg, cmd, addr);
0580     snd_use_lock_free(&rec->use_lock);
0581     return rc;
0582 }
0583 
0584 
0585 /*
0586  * send OSS raw events - SEQ_PRIVATE and SEQ_VOLUME
0587  */
0588 int
0589 snd_seq_oss_synth_raw_event(struct seq_oss_devinfo *dp, int dev, unsigned char *data, struct snd_seq_event *ev)
0590 {
0591     struct seq_oss_synthinfo *info;
0592 
0593     info = snd_seq_oss_synth_info(dp, dev);
0594     if (!info || info->is_midi)
0595         return -ENXIO;
0596     ev->type = SNDRV_SEQ_EVENT_OSS;
0597     memcpy(ev->data.raw8.d, data, 8);
0598     return snd_seq_oss_synth_addr(dp, dev, ev);
0599 }
0600 
0601 
0602 /*
0603  * create OSS compatible synth_info record
0604  */
0605 int
0606 snd_seq_oss_synth_make_info(struct seq_oss_devinfo *dp, int dev, struct synth_info *inf)
0607 {
0608     struct seq_oss_synth *rec;
0609     struct seq_oss_synthinfo *info = get_synthinfo_nospec(dp, dev);
0610 
0611     if (!info)
0612         return -ENXIO;
0613 
0614     if (info->is_midi) {
0615         struct midi_info minf;
0616         if (snd_seq_oss_midi_make_info(dp, info->midi_mapped, &minf))
0617             return -ENXIO;
0618         inf->synth_type = SYNTH_TYPE_MIDI;
0619         inf->synth_subtype = 0;
0620         inf->nr_voices = 16;
0621         inf->device = dev;
0622         strscpy(inf->name, minf.name, sizeof(inf->name));
0623     } else {
0624         rec = get_synthdev(dp, dev);
0625         if (!rec)
0626             return -ENXIO;
0627         inf->synth_type = rec->synth_type;
0628         inf->synth_subtype = rec->synth_subtype;
0629         inf->nr_voices = rec->nr_voices;
0630         inf->device = dev;
0631         strscpy(inf->name, rec->name, sizeof(inf->name));
0632         snd_use_lock_free(&rec->use_lock);
0633     }
0634     return 0;
0635 }
0636 
0637 
0638 #ifdef CONFIG_SND_PROC_FS
0639 /*
0640  * proc interface
0641  */
0642 void
0643 snd_seq_oss_synth_info_read(struct snd_info_buffer *buf)
0644 {
0645     int i;
0646     struct seq_oss_synth *rec;
0647 
0648     snd_iprintf(buf, "\nNumber of synth devices: %d\n", max_synth_devs);
0649     for (i = 0; i < max_synth_devs; i++) {
0650         snd_iprintf(buf, "\nsynth %d: ", i);
0651         rec = get_sdev(i);
0652         if (rec == NULL) {
0653             snd_iprintf(buf, "*empty*\n");
0654             continue;
0655         }
0656         snd_iprintf(buf, "[%s]\n", rec->name);
0657         snd_iprintf(buf, "  type 0x%x : subtype 0x%x : voices %d\n",
0658                 rec->synth_type, rec->synth_subtype,
0659                 rec->nr_voices);
0660         snd_iprintf(buf, "  capabilities : ioctl %s / load_patch %s\n",
0661                 enabled_str((long)rec->oper.ioctl),
0662                 enabled_str((long)rec->oper.load_patch));
0663         snd_use_lock_free(&rec->use_lock);
0664     }
0665 }
0666 #endif /* CONFIG_SND_PROC_FS */