linux/sound/core/seq/oss/seq_oss_ioctl.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * OSS compatible sequencer driver
   4 *
   5 * OSS compatible i/o control
   6 *
   7 * Copyright (C) 1998,99 Takashi Iwai <tiwai@suse.de>
   8 */
   9
  10#include "seq_oss_device.h"
  11#include "seq_oss_readq.h"
  12#include "seq_oss_writeq.h"
  13#include "seq_oss_timer.h"
  14#include "seq_oss_synth.h"
  15#include "seq_oss_midi.h"
  16#include "seq_oss_event.h"
  17
  18static int snd_seq_oss_synth_info_user(struct seq_oss_devinfo *dp, void __user *arg)
  19{
  20        struct synth_info info;
  21
  22        if (copy_from_user(&info, arg, sizeof(info)))
  23                return -EFAULT;
  24        if (snd_seq_oss_synth_make_info(dp, info.device, &info) < 0)
  25                return -EINVAL;
  26        if (copy_to_user(arg, &info, sizeof(info)))
  27                return -EFAULT;
  28        return 0;
  29}
  30
  31static int snd_seq_oss_midi_info_user(struct seq_oss_devinfo *dp, void __user *arg)
  32{
  33        struct midi_info info;
  34
  35        if (copy_from_user(&info, arg, sizeof(info)))
  36                return -EFAULT;
  37        if (snd_seq_oss_midi_make_info(dp, info.device, &info) < 0)
  38                return -EINVAL;
  39        if (copy_to_user(arg, &info, sizeof(info)))
  40                return -EFAULT;
  41        return 0;
  42}
  43
  44static int snd_seq_oss_oob_user(struct seq_oss_devinfo *dp, void __user *arg)
  45{
  46        unsigned char ev[8];
  47        struct snd_seq_event tmpev;
  48
  49        if (copy_from_user(ev, arg, 8))
  50                return -EFAULT;
  51        memset(&tmpev, 0, sizeof(tmpev));
  52        snd_seq_oss_fill_addr(dp, &tmpev, dp->addr.client, dp->addr.port);
  53        tmpev.time.tick = 0;
  54        if (! snd_seq_oss_process_event(dp, (union evrec *)ev, &tmpev)) {
  55                snd_seq_oss_dispatch(dp, &tmpev, 0, 0);
  56        }
  57        return 0;
  58}
  59
  60int
  61snd_seq_oss_ioctl(struct seq_oss_devinfo *dp, unsigned int cmd, unsigned long carg)
  62{
  63        int dev, val;
  64        void __user *arg = (void __user *)carg;
  65        int __user *p = arg;
  66
  67        switch (cmd) {
  68        case SNDCTL_TMR_TIMEBASE:
  69        case SNDCTL_TMR_TEMPO:
  70        case SNDCTL_TMR_START:
  71        case SNDCTL_TMR_STOP:
  72        case SNDCTL_TMR_CONTINUE:
  73        case SNDCTL_TMR_METRONOME:
  74        case SNDCTL_TMR_SOURCE:
  75        case SNDCTL_TMR_SELECT:
  76        case SNDCTL_SEQ_CTRLRATE:
  77                return snd_seq_oss_timer_ioctl(dp->timer, cmd, arg);
  78
  79        case SNDCTL_SEQ_PANIC:
  80                snd_seq_oss_reset(dp);
  81                return -EINVAL;
  82
  83        case SNDCTL_SEQ_SYNC:
  84                if (! is_write_mode(dp->file_mode) || dp->writeq == NULL)
  85                        return 0;
  86                while (snd_seq_oss_writeq_sync(dp->writeq))
  87                        ;
  88                if (signal_pending(current))
  89                        return -ERESTARTSYS;
  90                return 0;
  91
  92        case SNDCTL_SEQ_RESET:
  93                snd_seq_oss_reset(dp);
  94                return 0;
  95
  96        case SNDCTL_SEQ_TESTMIDI:
  97                if (get_user(dev, p))
  98                        return -EFAULT;
  99                return snd_seq_oss_midi_open(dp, dev, dp->file_mode);
 100
 101        case SNDCTL_SEQ_GETINCOUNT:
 102                if (dp->readq == NULL || ! is_read_mode(dp->file_mode))
 103                        return 0;
 104                return put_user(dp->readq->qlen, p) ? -EFAULT : 0;
 105
 106        case SNDCTL_SEQ_GETOUTCOUNT:
 107                if (! is_write_mode(dp->file_mode) || dp->writeq == NULL)
 108                        return 0;
 109                return put_user(snd_seq_oss_writeq_get_free_size(dp->writeq), p) ? -EFAULT : 0;
 110
 111        case SNDCTL_SEQ_GETTIME:
 112                return put_user(snd_seq_oss_timer_cur_tick(dp->timer), p) ? -EFAULT : 0;
 113
 114        case SNDCTL_SEQ_RESETSAMPLES:
 115                if (get_user(dev, p))
 116                        return -EFAULT;
 117                return snd_seq_oss_synth_ioctl(dp, dev, cmd, carg);
 118
 119        case SNDCTL_SEQ_NRSYNTHS:
 120                return put_user(dp->max_synthdev, p) ? -EFAULT : 0;
 121
 122        case SNDCTL_SEQ_NRMIDIS:
 123                return put_user(dp->max_mididev, p) ? -EFAULT : 0;
 124
 125        case SNDCTL_SYNTH_MEMAVL:
 126                if (get_user(dev, p))
 127                        return -EFAULT;
 128                val = snd_seq_oss_synth_ioctl(dp, dev, cmd, carg);
 129                return put_user(val, p) ? -EFAULT : 0;
 130
 131        case SNDCTL_FM_4OP_ENABLE:
 132                if (get_user(dev, p))
 133                        return -EFAULT;
 134                snd_seq_oss_synth_ioctl(dp, dev, cmd, carg);
 135                return 0;
 136
 137        case SNDCTL_SYNTH_INFO:
 138        case SNDCTL_SYNTH_ID:
 139                return snd_seq_oss_synth_info_user(dp, arg);
 140
 141        case SNDCTL_SEQ_OUTOFBAND:
 142                return snd_seq_oss_oob_user(dp, arg);
 143
 144        case SNDCTL_MIDI_INFO:
 145                return snd_seq_oss_midi_info_user(dp, arg);
 146
 147        case SNDCTL_SEQ_THRESHOLD:
 148                if (! is_write_mode(dp->file_mode))
 149                        return 0;
 150                if (get_user(val, p))
 151                        return -EFAULT;
 152                if (val < 1)
 153                        val = 1;
 154                if (val >= dp->writeq->maxlen)
 155                        val = dp->writeq->maxlen - 1;
 156                snd_seq_oss_writeq_set_output(dp->writeq, val);
 157                return 0;
 158
 159        case SNDCTL_MIDI_PRETIME:
 160                if (dp->readq == NULL || !is_read_mode(dp->file_mode))
 161                        return 0;
 162                if (get_user(val, p))
 163                        return -EFAULT;
 164                if (val <= 0)
 165                        val = -1;
 166                else
 167                        val = (HZ * val) / 10;
 168                dp->readq->pre_event_timeout = val;
 169                return put_user(val, p) ? -EFAULT : 0;
 170
 171        default:
 172                if (! is_write_mode(dp->file_mode))
 173                        return -EIO;
 174                return snd_seq_oss_synth_ioctl(dp, 0, cmd, carg);
 175        }
 176        return 0;
 177}
 178
 179