Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
seq_oss_ioctl.c
Go to the documentation of this file.
1 /*
2  * OSS compatible sequencer driver
3  *
4  * OSS compatible i/o control
5  *
6  * Copyright (C) 1998,99 Takashi Iwai <[email protected]>
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 
31 static 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 
44 static 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 
57 static 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 
73 int
74 snd_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) {
82  case SNDCTL_TMR_TEMPO:
83  case SNDCTL_TMR_START:
84  case SNDCTL_TMR_STOP:
87  case SNDCTL_TMR_SOURCE:
88  case SNDCTL_TMR_SELECT:
90  return snd_seq_oss_timer_ioctl(dp->timer, cmd, arg);
91 
92  case SNDCTL_SEQ_PANIC:
93  debug_printk(("panic\n"));
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 
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 
125  debug_printk(("get out count\n"));
126  if (! is_write_mode(dp->file_mode) || dp->writeq == NULL)
127  return 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 
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 
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 
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 
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;
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