1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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