linux/sound/core/seq/oss/seq_oss_ioctl.c
<<
>>
Prefs
   1/*
   2 * OSS compatible sequencer driver
   3 *
   4 * OSS compatible i/o control
   5 *
   6 * Copyright (C) 1998,99 Takashi Iwai <tiwai@suse.de>
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License as published by
  10 * the Free Software Foundation; either version 2 of the License, or
  11 * (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  21 */
  22
  23#include "seq_oss_device.h"
  24#include "seq_oss_readq.h"
  25#include "seq_oss_writeq.h"
  26#include "seq_oss_timer.h"
  27#include "seq_oss_synth.h"
  28#include "seq_oss_midi.h"
  29#include "seq_oss_event.h"
  30
  31static int snd_seq_oss_synth_info_user(struct seq_oss_devinfo *dp, void __user *arg)
  32{
  33        struct synth_info info;
  34
  35        if (copy_from_user(&info, arg, sizeof(info)))
  36                return -EFAULT;
  37        if (snd_seq_oss_synth_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_midi_info_user(struct seq_oss_devinfo *dp, void __user *arg)
  45{
  46        struct midi_info info;
  47
  48        if (copy_from_user(&info, arg, sizeof(info)))
  49                return -EFAULT;
  50        if (snd_seq_oss_midi_make_info(dp, info.device, &info) < 0)
  51                return -EINVAL;
  52        if (copy_to_user(arg, &info, sizeof(info)))
  53                return -EFAULT;
  54        return 0;
  55}
  56
  57static int snd_seq_oss_oob_user(struct seq_oss_devinfo *dp, void __user *arg)
  58{
  59        unsigned char ev[8];
  60        struct snd_seq_event tmpev;
  61
  62        if (copy_from_user(ev, arg, 8))
  63                return -EFAULT;
  64        memset(&tmpev, 0, sizeof(tmpev));
  65        snd_seq_oss_fill_addr(dp, &tmpev, dp->addr.port, dp->addr.client);
  66        tmpev.time.tick = 0;
  67        if (! snd_seq_oss_process_event(dp, (union evrec *)ev, &tmpev)) {
  68                snd_seq_oss_dispatch(dp, &tmpev, 0, 0);
  69        }
  70        return 0;
  71}
  72
  73int
  74snd_seq_oss_ioctl(struct seq_oss_devinfo *dp, unsigned int cmd, unsigned long carg)
  75{
  76        int dev, val;
  77        void __user *arg = (void __user *)carg;
  78        int __user *p = arg;
  79
  80        switch (cmd) {
  81        case SNDCTL_TMR_TIMEBASE:
  82        case SNDCTL_TMR_TEMPO:
  83        case SNDCTL_TMR_START:
  84        case SNDCTL_TMR_STOP:
  85        case SNDCTL_TMR_CONTINUE:
  86        case SNDCTL_TMR_METRONOME:
  87        case SNDCTL_TMR_SOURCE:
  88        case SNDCTL_TMR_SELECT:
  89        case SNDCTL_SEQ_CTRLRATE:
  90                return snd_seq_oss_timer_ioctl(dp->timer, cmd, arg);
  91
  92        case SNDCTL_SEQ_PANIC:
  93                snd_seq_oss_reset(dp);
  94                return -EINVAL;
  95
  96        case SNDCTL_SEQ_SYNC:
  97                if (! is_write_mode(dp->file_mode) || dp->writeq == NULL)
  98                        return 0;
  99                while (snd_seq_oss_writeq_sync(dp->writeq))
 100                        ;
 101                if (signal_pending(current))
 102                        return -ERESTARTSYS;
 103                return 0;
 104
 105        case SNDCTL_SEQ_RESET:
 106                snd_seq_oss_reset(dp);
 107                return 0;
 108
 109        case SNDCTL_SEQ_TESTMIDI:
 110                if (get_user(dev, p))
 111                        return -EFAULT;
 112                return snd_seq_oss_midi_open(dp, dev, dp->file_mode);
 113
 114        case SNDCTL_SEQ_GETINCOUNT:
 115                if (dp->readq == NULL || ! is_read_mode(dp->file_mode))
 116                        return 0;
 117                return put_user(dp->readq->qlen, p) ? -EFAULT : 0;
 118
 119        case SNDCTL_SEQ_GETOUTCOUNT:
 120                if (! is_write_mode(dp->file_mode) || dp->writeq == NULL)
 121                        return 0;
 122                return put_user(snd_seq_oss_writeq_get_free_size(dp->writeq), p) ? -EFAULT : 0;
 123
 124        case SNDCTL_SEQ_GETTIME:
 125                return put_user(snd_seq_oss_timer_cur_tick(dp->timer), p) ? -EFAULT : 0;
 126
 127        case SNDCTL_SEQ_RESETSAMPLES:
 128                if (get_user(dev, p))
 129                        return -EFAULT;
 130                return snd_seq_oss_synth_ioctl(dp, dev, cmd, carg);
 131
 132        case SNDCTL_SEQ_NRSYNTHS:
 133                return put_user(dp->max_synthdev, p) ? -EFAULT : 0;
 134
 135        case SNDCTL_SEQ_NRMIDIS:
 136                return put_user(dp->max_mididev, p) ? -EFAULT : 0;
 137
 138        case SNDCTL_SYNTH_MEMAVL:
 139                if (get_user(dev, p))
 140                        return -EFAULT;
 141                val = snd_seq_oss_synth_ioctl(dp, dev, cmd, carg);
 142                return put_user(val, p) ? -EFAULT : 0;
 143
 144        case SNDCTL_FM_4OP_ENABLE:
 145                if (get_user(dev, p))
 146                        return -EFAULT;
 147                snd_seq_oss_synth_ioctl(dp, dev, cmd, carg);
 148                return 0;
 149
 150        case SNDCTL_SYNTH_INFO:
 151        case SNDCTL_SYNTH_ID:
 152                return snd_seq_oss_synth_info_user(dp, arg);
 153
 154        case SNDCTL_SEQ_OUTOFBAND:
 155                return snd_seq_oss_oob_user(dp, arg);
 156
 157        case SNDCTL_MIDI_INFO:
 158                return snd_seq_oss_midi_info_user(dp, arg);
 159
 160        case SNDCTL_SEQ_THRESHOLD:
 161                if (! is_write_mode(dp->file_mode))
 162                        return 0;
 163                if (get_user(val, p))
 164                        return -EFAULT;
 165                if (val < 1)
 166                        val = 1;
 167                if (val >= dp->writeq->maxlen)
 168                        val = dp->writeq->maxlen - 1;
 169                snd_seq_oss_writeq_set_output(dp->writeq, val);
 170                return 0;
 171
 172        case SNDCTL_MIDI_PRETIME:
 173                if (dp->readq == NULL || !is_read_mode(dp->file_mode))
 174                        return 0;
 175                if (get_user(val, p))
 176                        return -EFAULT;
 177                if (val <= 0)
 178                        val = -1;
 179                else
 180                        val = (HZ * val) / 10;
 181                dp->readq->pre_event_timeout = val;
 182                return put_user(val, p) ? -EFAULT : 0;
 183
 184        default:
 185                if (! is_write_mode(dp->file_mode))
 186                        return -EIO;
 187                return snd_seq_oss_synth_ioctl(dp, 0, cmd, carg);
 188        }
 189        return 0;
 190}
 191
 192