0001
0002
0003
0004
0005
0006
0007
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