Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * OSS compatible sequencer driver
0004  *
0005  * OSS compatible i/o control
0006  *
0007  * Copyright (C) 1998,99 Takashi Iwai <tiwai@suse.de>
0008  */
0009 
0010 #include "seq_oss_device.h"
0011 #include "seq_oss_readq.h"
0012 #include "seq_oss_writeq.h"
0013 #include "seq_oss_timer.h"
0014 #include "seq_oss_synth.h"
0015 #include "seq_oss_midi.h"
0016 #include "seq_oss_event.h"
0017 
0018 static int snd_seq_oss_synth_info_user(struct seq_oss_devinfo *dp, void __user *arg)
0019 {
0020     struct synth_info info;
0021 
0022     if (copy_from_user(&info, arg, sizeof(info)))
0023         return -EFAULT;
0024     if (snd_seq_oss_synth_make_info(dp, info.device, &info) < 0)
0025         return -EINVAL;
0026     if (copy_to_user(arg, &info, sizeof(info)))
0027         return -EFAULT;
0028     return 0;
0029 }
0030 
0031 static int snd_seq_oss_midi_info_user(struct seq_oss_devinfo *dp, void __user *arg)
0032 {
0033     struct midi_info info;
0034 
0035     if (copy_from_user(&info, arg, sizeof(info)))
0036         return -EFAULT;
0037     if (snd_seq_oss_midi_make_info(dp, info.device, &info) < 0)
0038         return -EINVAL;
0039     if (copy_to_user(arg, &info, sizeof(info)))
0040         return -EFAULT;
0041     return 0;
0042 }
0043 
0044 static int snd_seq_oss_oob_user(struct seq_oss_devinfo *dp, void __user *arg)
0045 {
0046     unsigned char ev[8];
0047     struct snd_seq_event tmpev;
0048 
0049     if (copy_from_user(ev, arg, 8))
0050         return -EFAULT;
0051     memset(&tmpev, 0, sizeof(tmpev));
0052     snd_seq_oss_fill_addr(dp, &tmpev, dp->addr.client, dp->addr.port);
0053     tmpev.time.tick = 0;
0054     if (! snd_seq_oss_process_event(dp, (union evrec *)ev, &tmpev)) {
0055         snd_seq_oss_dispatch(dp, &tmpev, 0, 0);
0056     }
0057     return 0;
0058 }
0059 
0060 int
0061 snd_seq_oss_ioctl(struct seq_oss_devinfo *dp, unsigned int cmd, unsigned long carg)
0062 {
0063     int dev, val;
0064     void __user *arg = (void __user *)carg;
0065     int __user *p = arg;
0066 
0067     switch (cmd) {
0068     case SNDCTL_TMR_TIMEBASE:
0069     case SNDCTL_TMR_TEMPO:
0070     case SNDCTL_TMR_START:
0071     case SNDCTL_TMR_STOP:
0072     case SNDCTL_TMR_CONTINUE:
0073     case SNDCTL_TMR_METRONOME:
0074     case SNDCTL_TMR_SOURCE:
0075     case SNDCTL_TMR_SELECT:
0076     case SNDCTL_SEQ_CTRLRATE:
0077         return snd_seq_oss_timer_ioctl(dp->timer, cmd, arg);
0078 
0079     case SNDCTL_SEQ_PANIC:
0080         snd_seq_oss_reset(dp);
0081         return -EINVAL;
0082 
0083     case SNDCTL_SEQ_SYNC:
0084         if (! is_write_mode(dp->file_mode) || dp->writeq == NULL)
0085             return 0;
0086         while (snd_seq_oss_writeq_sync(dp->writeq))
0087             ;
0088         if (signal_pending(current))
0089             return -ERESTARTSYS;
0090         return 0;
0091 
0092     case SNDCTL_SEQ_RESET:
0093         snd_seq_oss_reset(dp);
0094         return 0;
0095 
0096     case SNDCTL_SEQ_TESTMIDI:
0097         if (get_user(dev, p))
0098             return -EFAULT;
0099         return snd_seq_oss_midi_open(dp, dev, dp->file_mode);
0100 
0101     case SNDCTL_SEQ_GETINCOUNT:
0102         if (dp->readq == NULL || ! is_read_mode(dp->file_mode))
0103             return 0;
0104         return put_user(dp->readq->qlen, p) ? -EFAULT : 0;
0105 
0106     case SNDCTL_SEQ_GETOUTCOUNT:
0107         if (! is_write_mode(dp->file_mode) || dp->writeq == NULL)
0108             return 0;
0109         return put_user(snd_seq_oss_writeq_get_free_size(dp->writeq), p) ? -EFAULT : 0;
0110 
0111     case SNDCTL_SEQ_GETTIME:
0112         return put_user(snd_seq_oss_timer_cur_tick(dp->timer), p) ? -EFAULT : 0;
0113 
0114     case SNDCTL_SEQ_RESETSAMPLES:
0115         if (get_user(dev, p))
0116             return -EFAULT;
0117         return snd_seq_oss_synth_ioctl(dp, dev, cmd, carg);
0118 
0119     case SNDCTL_SEQ_NRSYNTHS:
0120         return put_user(dp->max_synthdev, p) ? -EFAULT : 0;
0121 
0122     case SNDCTL_SEQ_NRMIDIS:
0123         return put_user(dp->max_mididev, p) ? -EFAULT : 0;
0124 
0125     case SNDCTL_SYNTH_MEMAVL:
0126         if (get_user(dev, p))
0127             return -EFAULT;
0128         val = snd_seq_oss_synth_ioctl(dp, dev, cmd, carg);
0129         return put_user(val, p) ? -EFAULT : 0;
0130 
0131     case SNDCTL_FM_4OP_ENABLE:
0132         if (get_user(dev, p))
0133             return -EFAULT;
0134         snd_seq_oss_synth_ioctl(dp, dev, cmd, carg);
0135         return 0;
0136 
0137     case SNDCTL_SYNTH_INFO:
0138     case SNDCTL_SYNTH_ID:
0139         return snd_seq_oss_synth_info_user(dp, arg);
0140 
0141     case SNDCTL_SEQ_OUTOFBAND:
0142         return snd_seq_oss_oob_user(dp, arg);
0143 
0144     case SNDCTL_MIDI_INFO:
0145         return snd_seq_oss_midi_info_user(dp, arg);
0146 
0147     case SNDCTL_SEQ_THRESHOLD:
0148         if (! is_write_mode(dp->file_mode))
0149             return 0;
0150         if (get_user(val, p))
0151             return -EFAULT;
0152         if (val < 1)
0153             val = 1;
0154         if (val >= dp->writeq->maxlen)
0155             val = dp->writeq->maxlen - 1;
0156         snd_seq_oss_writeq_set_output(dp->writeq, val);
0157         return 0;
0158 
0159     case SNDCTL_MIDI_PRETIME:
0160         if (dp->readq == NULL || !is_read_mode(dp->file_mode))
0161             return 0;
0162         if (get_user(val, p))
0163             return -EFAULT;
0164         if (val <= 0)
0165             val = -1;
0166         else
0167             val = (HZ * val) / 10;
0168         dp->readq->pre_event_timeout = val;
0169         return put_user(val, p) ? -EFAULT : 0;
0170 
0171     default:
0172         if (! is_write_mode(dp->file_mode))
0173             return -EIO;
0174         return snd_seq_oss_synth_ioctl(dp, 0, cmd, carg);
0175     }
0176     return 0;
0177 }
0178