Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * OSS compatible sequencer driver
0004  *
0005  * Copyright (C) 1998,99 Takashi Iwai <tiwai@suse.de>
0006  */
0007 
0008 #include "seq_oss_device.h"
0009 #include "seq_oss_synth.h"
0010 #include "seq_oss_midi.h"
0011 #include "seq_oss_event.h"
0012 #include "seq_oss_timer.h"
0013 #include <sound/seq_oss_legacy.h>
0014 #include "seq_oss_readq.h"
0015 #include "seq_oss_writeq.h"
0016 #include <linux/nospec.h>
0017 
0018 
0019 /*
0020  * prototypes
0021  */
0022 static int extended_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev);
0023 static int chn_voice_event(struct seq_oss_devinfo *dp, union evrec *event_rec, struct snd_seq_event *ev);
0024 static int chn_common_event(struct seq_oss_devinfo *dp, union evrec *event_rec, struct snd_seq_event *ev);
0025 static int timing_event(struct seq_oss_devinfo *dp, union evrec *event_rec, struct snd_seq_event *ev);
0026 static int local_event(struct seq_oss_devinfo *dp, union evrec *event_rec, struct snd_seq_event *ev);
0027 static int old_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev);
0028 static int note_on_event(struct seq_oss_devinfo *dp, int dev, int ch, int note, int vel, struct snd_seq_event *ev);
0029 static int note_off_event(struct seq_oss_devinfo *dp, int dev, int ch, int note, int vel, struct snd_seq_event *ev);
0030 static int set_note_event(struct seq_oss_devinfo *dp, int dev, int type, int ch, int note, int vel, struct snd_seq_event *ev);
0031 static int set_control_event(struct seq_oss_devinfo *dp, int dev, int type, int ch, int param, int val, struct snd_seq_event *ev);
0032 static int set_echo_event(struct seq_oss_devinfo *dp, union evrec *rec, struct snd_seq_event *ev);
0033 
0034 
0035 /*
0036  * convert an OSS event to ALSA event
0037  * return 0 : enqueued
0038  *        non-zero : invalid - ignored
0039  */
0040 
0041 int
0042 snd_seq_oss_process_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev)
0043 {
0044     switch (q->s.code) {
0045     case SEQ_EXTENDED:
0046         return extended_event(dp, q, ev);
0047 
0048     case EV_CHN_VOICE:
0049         return chn_voice_event(dp, q, ev);
0050 
0051     case EV_CHN_COMMON:
0052         return chn_common_event(dp, q, ev);
0053 
0054     case EV_TIMING:
0055         return timing_event(dp, q, ev);
0056 
0057     case EV_SEQ_LOCAL:
0058         return local_event(dp, q, ev);
0059 
0060     case EV_SYSEX:
0061         return snd_seq_oss_synth_sysex(dp, q->x.dev, q->x.buf, ev);
0062 
0063     case SEQ_MIDIPUTC:
0064         if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC)
0065             return -EINVAL;
0066         /* put a midi byte */
0067         if (! is_write_mode(dp->file_mode))
0068             break;
0069         if (snd_seq_oss_midi_open(dp, q->s.dev, SNDRV_SEQ_OSS_FILE_WRITE))
0070             break;
0071         if (snd_seq_oss_midi_filemode(dp, q->s.dev) & SNDRV_SEQ_OSS_FILE_WRITE)
0072             return snd_seq_oss_midi_putc(dp, q->s.dev, q->s.parm1, ev);
0073         break;
0074 
0075     case SEQ_ECHO:
0076         if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC)
0077             return -EINVAL;
0078         return set_echo_event(dp, q, ev);
0079 
0080     case SEQ_PRIVATE:
0081         if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC)
0082             return -EINVAL;
0083         return snd_seq_oss_synth_raw_event(dp, q->c[1], q->c, ev);
0084 
0085     default:
0086         if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC)
0087             return -EINVAL;
0088         return old_event(dp, q, ev);
0089     }
0090     return -EINVAL;
0091 }
0092 
0093 /* old type events: mode1 only */
0094 static int
0095 old_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev)
0096 {
0097     switch (q->s.code) {
0098     case SEQ_NOTEOFF:
0099         return note_off_event(dp, 0, q->n.chn, q->n.note, q->n.vel, ev);
0100 
0101     case SEQ_NOTEON:
0102         return note_on_event(dp, 0, q->n.chn, q->n.note, q->n.vel, ev);
0103 
0104     case SEQ_WAIT:
0105         /* skip */
0106         break;
0107 
0108     case SEQ_PGMCHANGE:
0109         return set_control_event(dp, 0, SNDRV_SEQ_EVENT_PGMCHANGE,
0110                      q->n.chn, 0, q->n.note, ev);
0111 
0112     case SEQ_SYNCTIMER:
0113         return snd_seq_oss_timer_reset(dp->timer);
0114     }
0115 
0116     return -EINVAL;
0117 }
0118 
0119 /* 8bytes extended event: mode1 only */
0120 static int
0121 extended_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev)
0122 {
0123     int val;
0124 
0125     switch (q->e.cmd) {
0126     case SEQ_NOTEOFF:
0127         return note_off_event(dp, q->e.dev, q->e.chn, q->e.p1, q->e.p2, ev);
0128 
0129     case SEQ_NOTEON:
0130         return note_on_event(dp, q->e.dev, q->e.chn, q->e.p1, q->e.p2, ev);
0131 
0132     case SEQ_PGMCHANGE:
0133         return set_control_event(dp, q->e.dev, SNDRV_SEQ_EVENT_PGMCHANGE,
0134                      q->e.chn, 0, q->e.p1, ev);
0135 
0136     case SEQ_AFTERTOUCH:
0137         return set_control_event(dp, q->e.dev, SNDRV_SEQ_EVENT_CHANPRESS,
0138                      q->e.chn, 0, q->e.p1, ev);
0139 
0140     case SEQ_BALANCE:
0141         /* convert -128:127 to 0:127 */
0142         val = (char)q->e.p1;
0143         val = (val + 128) / 2;
0144         return set_control_event(dp, q->e.dev, SNDRV_SEQ_EVENT_CONTROLLER,
0145                      q->e.chn, CTL_PAN, val, ev);
0146 
0147     case SEQ_CONTROLLER:
0148         val = ((short)q->e.p3 << 8) | (short)q->e.p2;
0149         switch (q->e.p1) {
0150         case CTRL_PITCH_BENDER: /* SEQ1 V2 control */
0151             /* -0x2000:0x1fff */
0152             return set_control_event(dp, q->e.dev,
0153                          SNDRV_SEQ_EVENT_PITCHBEND,
0154                          q->e.chn, 0, val, ev);
0155         case CTRL_PITCH_BENDER_RANGE:
0156             /* conversion: 100/semitone -> 128/semitone */
0157             return set_control_event(dp, q->e.dev,
0158                          SNDRV_SEQ_EVENT_REGPARAM,
0159                          q->e.chn, 0, val*128/100, ev);
0160         default:
0161             return set_control_event(dp, q->e.dev,
0162                           SNDRV_SEQ_EVENT_CONTROL14,
0163                           q->e.chn, q->e.p1, val, ev);
0164         }
0165 
0166     case SEQ_VOLMODE:
0167         return snd_seq_oss_synth_raw_event(dp, q->e.dev, q->c, ev);
0168 
0169     }
0170     return -EINVAL;
0171 }
0172 
0173 /* channel voice events: mode1 and 2 */
0174 static int
0175 chn_voice_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev)
0176 {
0177     if (q->v.chn >= 32)
0178         return -EINVAL;
0179     switch (q->v.cmd) {
0180     case MIDI_NOTEON:
0181         return note_on_event(dp, q->v.dev, q->v.chn, q->v.note, q->v.parm, ev);
0182 
0183     case MIDI_NOTEOFF:
0184         return note_off_event(dp, q->v.dev, q->v.chn, q->v.note, q->v.parm, ev);
0185 
0186     case MIDI_KEY_PRESSURE:
0187         return set_note_event(dp, q->v.dev, SNDRV_SEQ_EVENT_KEYPRESS,
0188                        q->v.chn, q->v.note, q->v.parm, ev);
0189 
0190     }
0191     return -EINVAL;
0192 }
0193 
0194 /* channel common events: mode1 and 2 */
0195 static int
0196 chn_common_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev)
0197 {
0198     if (q->l.chn >= 32)
0199         return -EINVAL;
0200     switch (q->l.cmd) {
0201     case MIDI_PGM_CHANGE:
0202         return set_control_event(dp, q->l.dev, SNDRV_SEQ_EVENT_PGMCHANGE,
0203                       q->l.chn, 0, q->l.p1, ev);
0204 
0205     case MIDI_CTL_CHANGE:
0206         return set_control_event(dp, q->l.dev, SNDRV_SEQ_EVENT_CONTROLLER,
0207                       q->l.chn, q->l.p1, q->l.val, ev);
0208 
0209     case MIDI_PITCH_BEND:
0210         /* conversion: 0:0x3fff -> -0x2000:0x1fff */
0211         return set_control_event(dp, q->l.dev, SNDRV_SEQ_EVENT_PITCHBEND,
0212                       q->l.chn, 0, q->l.val - 8192, ev);
0213         
0214     case MIDI_CHN_PRESSURE:
0215         return set_control_event(dp, q->l.dev, SNDRV_SEQ_EVENT_CHANPRESS,
0216                       q->l.chn, 0, q->l.val, ev);
0217     }
0218     return -EINVAL;
0219 }
0220 
0221 /* timer events: mode1 and mode2 */
0222 static int
0223 timing_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev)
0224 {
0225     switch (q->t.cmd) {
0226     case TMR_ECHO:
0227         if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC)
0228             return set_echo_event(dp, q, ev);
0229         else {
0230             union evrec tmp;
0231             memset(&tmp, 0, sizeof(tmp));
0232             /* XXX: only for little-endian! */
0233             tmp.echo = (q->t.time << 8) | SEQ_ECHO;
0234             return set_echo_event(dp, &tmp, ev);
0235         } 
0236 
0237     case TMR_STOP:
0238         if (dp->seq_mode)
0239             return snd_seq_oss_timer_stop(dp->timer);
0240         return 0;
0241 
0242     case TMR_CONTINUE:
0243         if (dp->seq_mode)
0244             return snd_seq_oss_timer_continue(dp->timer);
0245         return 0;
0246 
0247     case TMR_TEMPO:
0248         if (dp->seq_mode)
0249             return snd_seq_oss_timer_tempo(dp->timer, q->t.time);
0250         return 0;
0251     }
0252 
0253     return -EINVAL;
0254 }
0255 
0256 /* local events: mode1 and 2 */
0257 static int
0258 local_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev)
0259 {
0260     return -EINVAL;
0261 }
0262 
0263 /*
0264  * process note-on event for OSS synth
0265  * three different modes are available:
0266  * - SNDRV_SEQ_OSS_PROCESS_EVENTS  (for one-voice per channel mode)
0267  *  Accept note 255 as volume change.
0268  * - SNDRV_SEQ_OSS_PASS_EVENTS
0269  *  Pass all events to lowlevel driver anyway
0270  * - SNDRV_SEQ_OSS_PROCESS_KEYPRESS  (mostly for Emu8000)
0271  *  Use key-pressure if note >= 128
0272  */
0273 static int
0274 note_on_event(struct seq_oss_devinfo *dp, int dev, int ch, int note, int vel, struct snd_seq_event *ev)
0275 {
0276     struct seq_oss_synthinfo *info;
0277 
0278     info = snd_seq_oss_synth_info(dp, dev);
0279     if (!info)
0280         return -ENXIO;
0281 
0282     switch (info->arg.event_passing) {
0283     case SNDRV_SEQ_OSS_PROCESS_EVENTS:
0284         if (! info->ch || ch < 0 || ch >= info->nr_voices) {
0285             /* pass directly */
0286             return set_note_event(dp, dev, SNDRV_SEQ_EVENT_NOTEON, ch, note, vel, ev);
0287         }
0288 
0289         ch = array_index_nospec(ch, info->nr_voices);
0290         if (note == 255 && info->ch[ch].note >= 0) {
0291             /* volume control */
0292             int type;
0293             //if (! vel)
0294                 /* set volume to zero -- note off */
0295             //  type = SNDRV_SEQ_EVENT_NOTEOFF;
0296             //else
0297                 if (info->ch[ch].vel)
0298                 /* sample already started -- volume change */
0299                 type = SNDRV_SEQ_EVENT_KEYPRESS;
0300             else
0301                 /* sample not started -- start now */
0302                 type = SNDRV_SEQ_EVENT_NOTEON;
0303             info->ch[ch].vel = vel;
0304             return set_note_event(dp, dev, type, ch, info->ch[ch].note, vel, ev);
0305         } else if (note >= 128)
0306             return -EINVAL; /* invalid */
0307 
0308         if (note != info->ch[ch].note && info->ch[ch].note >= 0)
0309             /* note changed - note off at beginning */
0310             set_note_event(dp, dev, SNDRV_SEQ_EVENT_NOTEOFF, ch, info->ch[ch].note, 0, ev);
0311         /* set current status */
0312         info->ch[ch].note = note;
0313         info->ch[ch].vel = vel;
0314         if (vel) /* non-zero velocity - start the note now */
0315             return set_note_event(dp, dev, SNDRV_SEQ_EVENT_NOTEON, ch, note, vel, ev);
0316         return -EINVAL;
0317         
0318     case SNDRV_SEQ_OSS_PASS_EVENTS:
0319         /* pass the event anyway */
0320         return set_note_event(dp, dev, SNDRV_SEQ_EVENT_NOTEON, ch, note, vel, ev);
0321 
0322     case SNDRV_SEQ_OSS_PROCESS_KEYPRESS:
0323         if (note >= 128) /* key pressure: shifted by 128 */
0324             return set_note_event(dp, dev, SNDRV_SEQ_EVENT_KEYPRESS, ch, note - 128, vel, ev);
0325         else /* normal note-on event */
0326             return set_note_event(dp, dev, SNDRV_SEQ_EVENT_NOTEON, ch, note, vel, ev);
0327     }
0328     return -EINVAL;
0329 }
0330 
0331 /*
0332  * process note-off event for OSS synth
0333  */
0334 static int
0335 note_off_event(struct seq_oss_devinfo *dp, int dev, int ch, int note, int vel, struct snd_seq_event *ev)
0336 {
0337     struct seq_oss_synthinfo *info;
0338 
0339     info = snd_seq_oss_synth_info(dp, dev);
0340     if (!info)
0341         return -ENXIO;
0342 
0343     switch (info->arg.event_passing) {
0344     case SNDRV_SEQ_OSS_PROCESS_EVENTS:
0345         if (! info->ch || ch < 0 || ch >= info->nr_voices) {
0346             /* pass directly */
0347             return set_note_event(dp, dev, SNDRV_SEQ_EVENT_NOTEON, ch, note, vel, ev);
0348         }
0349 
0350         ch = array_index_nospec(ch, info->nr_voices);
0351         if (info->ch[ch].note >= 0) {
0352             note = info->ch[ch].note;
0353             info->ch[ch].vel = 0;
0354             info->ch[ch].note = -1;
0355             return set_note_event(dp, dev, SNDRV_SEQ_EVENT_NOTEOFF, ch, note, vel, ev);
0356         }
0357         return -EINVAL; /* invalid */
0358 
0359     case SNDRV_SEQ_OSS_PASS_EVENTS:
0360     case SNDRV_SEQ_OSS_PROCESS_KEYPRESS:
0361         /* pass the event anyway */
0362         return set_note_event(dp, dev, SNDRV_SEQ_EVENT_NOTEOFF, ch, note, vel, ev);
0363 
0364     }
0365     return -EINVAL;
0366 }
0367 
0368 /*
0369  * create a note event
0370  */
0371 static int
0372 set_note_event(struct seq_oss_devinfo *dp, int dev, int type, int ch, int note, int vel, struct snd_seq_event *ev)
0373 {
0374     if (!snd_seq_oss_synth_info(dp, dev))
0375         return -ENXIO;
0376     
0377     ev->type = type;
0378     snd_seq_oss_synth_addr(dp, dev, ev);
0379     ev->data.note.channel = ch;
0380     ev->data.note.note = note;
0381     ev->data.note.velocity = vel;
0382 
0383     return 0;
0384 }
0385 
0386 /*
0387  * create a control event
0388  */
0389 static int
0390 set_control_event(struct seq_oss_devinfo *dp, int dev, int type, int ch, int param, int val, struct snd_seq_event *ev)
0391 {
0392     if (!snd_seq_oss_synth_info(dp, dev))
0393         return -ENXIO;
0394     
0395     ev->type = type;
0396     snd_seq_oss_synth_addr(dp, dev, ev);
0397     ev->data.control.channel = ch;
0398     ev->data.control.param = param;
0399     ev->data.control.value = val;
0400 
0401     return 0;
0402 }
0403 
0404 /*
0405  * create an echo event
0406  */
0407 static int
0408 set_echo_event(struct seq_oss_devinfo *dp, union evrec *rec, struct snd_seq_event *ev)
0409 {
0410     ev->type = SNDRV_SEQ_EVENT_ECHO;
0411     /* echo back to itself */
0412     snd_seq_oss_fill_addr(dp, ev, dp->addr.client, dp->addr.port);
0413     memcpy(&ev->data, rec, LONG_EVENT_SIZE);
0414     return 0;
0415 }
0416 
0417 /*
0418  * event input callback from ALSA sequencer:
0419  * the echo event is processed here.
0420  */
0421 int
0422 snd_seq_oss_event_input(struct snd_seq_event *ev, int direct, void *private_data,
0423             int atomic, int hop)
0424 {
0425     struct seq_oss_devinfo *dp = (struct seq_oss_devinfo *)private_data;
0426     union evrec *rec;
0427 
0428     if (ev->type != SNDRV_SEQ_EVENT_ECHO)
0429         return snd_seq_oss_midi_input(ev, direct, private_data);
0430 
0431     if (ev->source.client != dp->cseq)
0432         return 0; /* ignored */
0433 
0434     rec = (union evrec*)&ev->data;
0435     if (rec->s.code == SEQ_SYNCTIMER) {
0436         /* sync echo back */
0437         snd_seq_oss_writeq_wakeup(dp->writeq, rec->t.time);
0438         
0439     } else {
0440         /* echo back event */
0441         if (dp->readq == NULL)
0442             return 0;
0443         snd_seq_oss_readq_put_event(dp->readq, rec);
0444     }
0445     return 0;
0446 }
0447