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                debug_printk(("panic\n"));
  94                snd_seq_oss_reset(dp);
  95                return -EINVAL;
  96
  97        case SNDCTL_SEQ_SYNC:
  98                debug_printk(("sync\n"));
  99                if (! is_write_mode(dp->file_mode) || dp->writeq == NULL)
 100                        return 0;
 101                while (snd_seq_oss_writeq_sync(dp->writeq))
 102                        ;
 103                if (signal_pending(current))
 104                        return -ERESTARTSYS;
 105                return 0;
 106
 107        case SNDCTL_SEQ_RESET:
 108                debug_printk(("reset\n"));
 109                snd_seq_oss_reset(dp);
 110                return 0;
 111
 112        case SNDCTL_SEQ_TESTMIDI:
 113                debug_printk(("test midi\n"));
 114                if (get_user(dev, p))
 115                        return -EFAULT;
 116                return snd_seq_oss_midi_open(dp, dev, dp->file_mode);
 117
 118        case SNDCTL_SEQ_GETINCOUNT:
 119                debug_printk(("get in count\n"));
 120                if (dp->readq == NULL || ! is_read_mode(dp->file_mode))
 121                        return 0;
 122                return put_user(dp->readq->qlen, p) ? -EFAULT : 0;
 123
 124        case SNDCTL_SEQ_GETOUTCOUNT:
 125                debug_printk(("get out count\n"));
 126                if (! is_write_mode(dp->file_mode) || dp->writeq == NULL)
 127                        return 0;
 128                return put_user(snd_seq_oss_writeq_get_free_size(dp->writeq), p) ? -EFAULT : 0;
 129
 130        case SNDCTL_SEQ_GETTIME:
 131                debug_printk(("get time\n"));
 132                return put_user(snd_seq_oss_timer_cur_tick(dp->timer), p) ? -EFAULT : 0;
 133
 134        case SNDCTL_SEQ_RESETSAMPLES:
 135                debug_printk(("reset samples\n"));
 136                if (get_user(dev, p))
 137                        return -EFAULT;
 138                return snd_seq_oss_synth_ioctl(dp, dev, cmd, carg);
 139
 140        case SNDCTL_SEQ_NRSYNTHS:
 141                debug_printk(("nr synths\n"));
 142                return put_user(dp->max_synthdev, p) ? -EFAULT : 0;
 143
 144        case SNDCTL_SEQ_NRMIDIS:
 145                debug_printk(("nr midis\n"));
 146                return put_user(dp->max_mididev, p) ? -EFAULT : 0;
 147
 148        case SNDCTL_SYNTH_MEMAVL:
 149                debug_printk(("mem avail\n"));
 150                if (get_user(dev, p))
 151                        return -EFAULT;
 152                val = snd_seq_oss_synth_ioctl(dp, dev, cmd, carg);
 153                return put_user(val, p) ? -EFAULT : 0;
 154
 155        case SNDCTL_FM_4OP_ENABLE:
 156                debug_printk(("4op\n"));
 157                if (get_user(dev, p))
 158                        return -EFAULT;
 159                snd_seq_oss_synth_ioctl(dp, dev, cmd, carg);
 160                return 0;
 161
 162        case SNDCTL_SYNTH_INFO:
 163        case SNDCTL_SYNTH_ID:
 164                debug_printk(("synth info\n"));
 165                return snd_seq_oss_synth_info_user(dp, arg);
 166
 167        case SNDCTL_SEQ_OUTOFBAND:
 168                debug_printk(("out of band\n"));
 169                return snd_seq_oss_oob_user(dp, arg);
 170
 171        case SNDCTL_MIDI_INFO:
 172                debug_printk(("midi info\n"));
 173                return snd_seq_oss_midi_info_user(dp, arg);
 174
 175        case SNDCTL_SEQ_THRESHOLD:
 176                debug_printk(("threshold\n"));
 177                if (! is_write_mode(dp->file_mode))
 178                        return 0;
 179                if (get_user(val, p))
 180                        return -EFAULT;
 181                if (val < 1)
 182                        val = 1;
 183                if (val >= dp->writeq->maxlen)
 184                        val = dp->writeq->maxlen - 1;
 185                snd_seq_oss_writeq_set_output(dp->writeq, val);
 186                return 0;
 187
 188        case SNDCTL_MIDI_PRETIME:
 189                debug_printk(("pretime\n"));
 190                if (dp->readq == NULL || !is_read_mode(dp->file_mode))
 191                        return 0;
 192                if (get_user(val, p))
 193                        return -EFAULT;
 194                if (val <= 0)
 195                        val = -1;
 196                else
 197                        val = (HZ * val) / 10;
 198                dp->readq->pre_event_timeout = val;
 199                return put_user(val, p) ? -EFAULT : 0;
 200
 201        default:
 202                debug_printk(("others\n"));
 203                if (! is_write_mode(dp->file_mode))
 204                        return -EIO;
 205                return snd_seq_oss_synth_ioctl(dp, 0, cmd, carg);
 206        }
 207        return 0;
 208}
 209
 210