Merge tag 'v3.3.7' into 3.3/master
[zen-stable.git] / sound / core / seq / oss / seq_oss_ioctl.c
blob5ac701c903c1f394f99776b9ff987c11f374c8ef
1 /*
2 * OSS compatible sequencer driver
4 * OSS compatible i/o control
6 * Copyright (C) 1998,99 Takashi Iwai <tiwai@suse.de>
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.
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.
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
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"
31 static int snd_seq_oss_synth_info_user(struct seq_oss_devinfo *dp, void __user *arg)
33 struct synth_info info;
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;
44 static int snd_seq_oss_midi_info_user(struct seq_oss_devinfo *dp, void __user *arg)
46 struct midi_info info;
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;
57 static int snd_seq_oss_oob_user(struct seq_oss_devinfo *dp, void __user *arg)
59 unsigned char ev[8];
60 struct snd_seq_event tmpev;
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);
70 return 0;
73 int
74 snd_seq_oss_ioctl(struct seq_oss_devinfo *dp, unsigned int cmd, unsigned long carg)
76 int dev, val;
77 void __user *arg = (void __user *)carg;
78 int __user *p = arg;
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);
92 case SNDCTL_SEQ_PANIC:
93 debug_printk(("panic\n"));
94 snd_seq_oss_reset(dp);
95 return -EINVAL;
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))
103 if (signal_pending(current))
104 return -ERESTARTSYS;
105 return 0;
107 case SNDCTL_SEQ_RESET:
108 debug_printk(("reset\n"));
109 snd_seq_oss_reset(dp);
110 return 0;
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);
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;
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;
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;
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);
140 case SNDCTL_SEQ_NRSYNTHS:
141 debug_printk(("nr synths\n"));
142 return put_user(dp->max_synthdev, p) ? -EFAULT : 0;
144 case SNDCTL_SEQ_NRMIDIS:
145 debug_printk(("nr midis\n"));
146 return put_user(dp->max_mididev, p) ? -EFAULT : 0;
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;
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;
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);
167 case SNDCTL_SEQ_OUTOFBAND:
168 debug_printk(("out of band\n"));
169 return snd_seq_oss_oob_user(dp, arg);
171 case SNDCTL_MIDI_INFO:
172 debug_printk(("midi info\n"));
173 return snd_seq_oss_midi_info_user(dp, arg);
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;
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;
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);
207 return 0;