Merge tag 'devprop-4.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael...
[sfrench/cifs-2.6.git] / sound / oss / midibuf.c
1 /*
2  * sound/oss/midibuf.c
3  *
4  * Device file manager for /dev/midi#
5  */
6 /*
7  * Copyright (C) by Hannu Savolainen 1993-1997
8  *
9  * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
10  * Version 2 (June 1991). See the "COPYING" file distributed with this software
11  * for more info.
12  */
13 /*
14  * Thomas Sailer   : ioctl code reworked (vmalloc/vfree removed)
15  */
16 #include <linux/stddef.h>
17 #include <linux/kmod.h>
18 #include <linux/spinlock.h>
19 #include <linux/sched/signal.h>
20
21 #define MIDIBUF_C
22
23 #include "sound_config.h"
24
25
26 /*
27  * Don't make MAX_QUEUE_SIZE larger than 4000
28  */
29
30 #define MAX_QUEUE_SIZE  4000
31
32 static wait_queue_head_t midi_sleeper[MAX_MIDI_DEV];
33 static wait_queue_head_t input_sleeper[MAX_MIDI_DEV];
34
35 struct midi_buf
36 {
37         int len, head, tail;
38         unsigned char queue[MAX_QUEUE_SIZE];
39 };
40
41 struct midi_parms
42 {
43         long prech_timeout;     /*
44                                  * Timeout before the first ch
45                                  */
46 };
47
48 static struct midi_buf *midi_out_buf[MAX_MIDI_DEV] = {NULL};
49 static struct midi_buf *midi_in_buf[MAX_MIDI_DEV] = {NULL};
50 static struct midi_parms parms[MAX_MIDI_DEV];
51
52 static void midi_poll(unsigned long dummy);
53
54
55 static DEFINE_TIMER(poll_timer, midi_poll);
56
57 static volatile int open_devs;
58 static DEFINE_SPINLOCK(lock);
59
60 #define DATA_AVAIL(q) (q->len)
61 #define SPACE_AVAIL(q) (MAX_QUEUE_SIZE - q->len)
62
63 #define QUEUE_BYTE(q, data) \
64         if (SPACE_AVAIL(q)) \
65         { \
66           unsigned long flags; \
67           spin_lock_irqsave(&lock, flags); \
68           q->queue[q->tail] = (data); \
69           q->len++; q->tail = (q->tail+1) % MAX_QUEUE_SIZE; \
70           spin_unlock_irqrestore(&lock, flags); \
71         }
72
73 #define REMOVE_BYTE(q, data) \
74         if (DATA_AVAIL(q)) \
75         { \
76           unsigned long flags; \
77           spin_lock_irqsave(&lock, flags); \
78           data = q->queue[q->head]; \
79           q->len--; q->head = (q->head+1) % MAX_QUEUE_SIZE; \
80           spin_unlock_irqrestore(&lock, flags); \
81         }
82
83 static void drain_midi_queue(int dev)
84 {
85
86         /*
87          * Give the Midi driver time to drain its output queues
88          */
89
90         if (midi_devs[dev]->buffer_status != NULL)
91                 wait_event_interruptible_timeout(midi_sleeper[dev],
92                                 !midi_devs[dev]->buffer_status(dev), HZ/10);
93 }
94
95 static void midi_input_intr(int dev, unsigned char data)
96 {
97         if (midi_in_buf[dev] == NULL)
98                 return;
99
100         if (data == 0xfe)       /*
101                                  * Active sensing
102                                  */
103                 return;         /*
104                                  * Ignore
105                                  */
106
107         if (SPACE_AVAIL(midi_in_buf[dev])) {
108                 QUEUE_BYTE(midi_in_buf[dev], data);
109                 wake_up(&input_sleeper[dev]);
110         }
111 }
112
113 static void midi_output_intr(int dev)
114 {
115         /*
116          * Currently NOP
117          */
118 }
119
120 static void midi_poll(unsigned long dummy)
121 {
122         unsigned long   flags;
123         int             dev;
124
125         spin_lock_irqsave(&lock, flags);
126         if (open_devs)
127         {
128                 for (dev = 0; dev < num_midis; dev++)
129                         if (midi_devs[dev] != NULL && midi_out_buf[dev] != NULL)
130                         {
131                                 while (DATA_AVAIL(midi_out_buf[dev]))
132                                 {
133                                         int ok;
134                                         int c = midi_out_buf[dev]->queue[midi_out_buf[dev]->head];
135
136                                         spin_unlock_irqrestore(&lock,flags);/* Give some time to others */
137                                         ok = midi_devs[dev]->outputc(dev, c);
138                                         spin_lock_irqsave(&lock, flags);
139                                         if (!ok)
140                                                 break;
141                                         midi_out_buf[dev]->head = (midi_out_buf[dev]->head + 1) % MAX_QUEUE_SIZE;
142                                         midi_out_buf[dev]->len--;
143                                 }
144
145                                 if (DATA_AVAIL(midi_out_buf[dev]) < 100)
146                                         wake_up(&midi_sleeper[dev]);
147                         }
148                 poll_timer.expires = (1) + jiffies;
149                 add_timer(&poll_timer);
150                 /*
151                  * Come back later
152                  */
153         }
154         spin_unlock_irqrestore(&lock, flags);
155 }
156
157 int MIDIbuf_open(int dev, struct file *file)
158 {
159         int mode, err;
160
161         dev = dev >> 4;
162         mode = translate_mode(file);
163
164         if (num_midis > MAX_MIDI_DEV)
165         {
166                 printk(KERN_ERR "midi: Too many midi interfaces\n");
167                 num_midis = MAX_MIDI_DEV;
168         }
169         if (dev < 0 || dev >= num_midis || midi_devs[dev] == NULL)
170                   return -ENXIO;
171         /*
172          *    Interrupts disabled. Be careful
173          */
174
175         module_put(midi_devs[dev]->owner);
176
177         if ((err = midi_devs[dev]->open(dev, mode,
178                                  midi_input_intr, midi_output_intr)) < 0)
179                 return err;
180
181         parms[dev].prech_timeout = MAX_SCHEDULE_TIMEOUT;
182         midi_in_buf[dev] = vmalloc(sizeof(struct midi_buf));
183
184         if (midi_in_buf[dev] == NULL)
185         {
186                 printk(KERN_WARNING "midi: Can't allocate buffer\n");
187                 midi_devs[dev]->close(dev);
188                 return -EIO;
189         }
190         midi_in_buf[dev]->len = midi_in_buf[dev]->head = midi_in_buf[dev]->tail = 0;
191
192         midi_out_buf[dev] = vmalloc(sizeof(struct midi_buf));
193
194         if (midi_out_buf[dev] == NULL)
195         {
196                 printk(KERN_WARNING "midi: Can't allocate buffer\n");
197                 midi_devs[dev]->close(dev);
198                 vfree(midi_in_buf[dev]);
199                 midi_in_buf[dev] = NULL;
200                 return -EIO;
201         }
202         midi_out_buf[dev]->len = midi_out_buf[dev]->head = midi_out_buf[dev]->tail = 0;
203         open_devs++;
204
205         init_waitqueue_head(&midi_sleeper[dev]);
206         init_waitqueue_head(&input_sleeper[dev]);
207
208         if (open_devs < 2)      /* This was first open */
209         {
210                 poll_timer.expires = 1 + jiffies;
211                 add_timer(&poll_timer); /* Start polling */
212         }
213         return err;
214 }
215
216 void MIDIbuf_release(int dev, struct file *file)
217 {
218         int mode;
219
220         dev = dev >> 4;
221         mode = translate_mode(file);
222
223         if (dev < 0 || dev >= num_midis || midi_devs[dev] == NULL)
224                 return;
225
226         /*
227          * Wait until the queue is empty
228          */
229
230         if (mode != OPEN_READ)
231         {
232                 midi_devs[dev]->outputc(dev, 0xfe);     /*
233                                                            * Active sensing to shut the
234                                                            * devices
235                                                          */
236
237                 wait_event_interruptible(midi_sleeper[dev],
238                                          !DATA_AVAIL(midi_out_buf[dev]));
239                 /*
240                  *      Sync
241                  */
242
243                 drain_midi_queue(dev);  /*
244                                          * Ensure the output queues are empty
245                                          */
246         }
247
248         midi_devs[dev]->close(dev);
249
250         open_devs--;
251         if (open_devs == 0)
252                 del_timer_sync(&poll_timer);
253         vfree(midi_in_buf[dev]);
254         vfree(midi_out_buf[dev]);
255         midi_in_buf[dev] = NULL;
256         midi_out_buf[dev] = NULL;
257
258         module_put(midi_devs[dev]->owner);
259 }
260
261 int MIDIbuf_write(int dev, struct file *file, const char __user *buf, int count)
262 {
263         int c, n, i;
264         unsigned char tmp_data;
265
266         dev = dev >> 4;
267
268         if (!count)
269                 return 0;
270
271         c = 0;
272
273         while (c < count)
274         {
275                 n = SPACE_AVAIL(midi_out_buf[dev]);
276
277                 if (n == 0) {   /*
278                                  * No space just now.
279                                  */
280
281                         if (file->f_flags & O_NONBLOCK) {
282                                 c = -EAGAIN;
283                                 goto out;
284                         }
285
286                         if (wait_event_interruptible(midi_sleeper[dev],
287                                                 SPACE_AVAIL(midi_out_buf[dev])))
288                         {
289                                 c = -EINTR;
290                                 goto out;
291                         }
292                         n = SPACE_AVAIL(midi_out_buf[dev]);
293                 }
294                 if (n > (count - c))
295                         n = count - c;
296
297                 for (i = 0; i < n; i++)
298                 {
299                         /* BROKE BROKE BROKE - CAN'T DO THIS WITH CLI !! */
300                         /* yes, think the same, so I removed the cli() brackets 
301                                 QUEUE_BYTE is protected against interrupts */
302                         if (copy_from_user((char *) &tmp_data, &(buf)[c], 1)) {
303                                 c = -EFAULT;
304                                 goto out;
305                         }
306                         QUEUE_BYTE(midi_out_buf[dev], tmp_data);
307                         c++;
308                 }
309         }
310 out:
311         return c;
312 }
313
314
315 int MIDIbuf_read(int dev, struct file *file, char __user *buf, int count)
316 {
317         int n, c = 0;
318         unsigned char tmp_data;
319
320         dev = dev >> 4;
321
322         if (!DATA_AVAIL(midi_in_buf[dev])) {    /*
323                                                  * No data yet, wait
324                                                  */
325                 if (file->f_flags & O_NONBLOCK) {
326                         c = -EAGAIN;
327                         goto out;
328                 }
329                 wait_event_interruptible_timeout(input_sleeper[dev],
330                                                  DATA_AVAIL(midi_in_buf[dev]),
331                                                  parms[dev].prech_timeout);
332
333                 if (signal_pending(current))
334                         c = -EINTR;     /* The user is getting restless */
335         }
336         if (c == 0 && DATA_AVAIL(midi_in_buf[dev]))     /*
337                                                          * Got some bytes
338                                                          */
339         {
340                 n = DATA_AVAIL(midi_in_buf[dev]);
341                 if (n > count)
342                         n = count;
343                 c = 0;
344
345                 while (c < n)
346                 {
347                         char *fixit;
348                         REMOVE_BYTE(midi_in_buf[dev], tmp_data);
349                         fixit = (char *) &tmp_data;
350                         /* BROKE BROKE BROKE */
351                         /* yes removed the cli() brackets again
352                          should q->len,tail&head be atomic_t? */
353                         if (copy_to_user(&(buf)[c], fixit, 1)) {
354                                 c = -EFAULT;
355                                 goto out;
356                         }
357                         c++;
358                 }
359         }
360 out:
361         return c;
362 }
363
364 int MIDIbuf_ioctl(int dev, struct file *file,
365                   unsigned int cmd, void __user *arg)
366 {
367         int val;
368
369         dev = dev >> 4;
370         
371         if (((cmd >> 8) & 0xff) == 'C') 
372         {
373                 if (midi_devs[dev]->coproc)     /* Coprocessor ioctl */
374                         return midi_devs[dev]->coproc->ioctl(midi_devs[dev]->coproc->devc, cmd, arg, 0);
375 /*              printk("/dev/midi%d: No coprocessor for this device\n", dev);*/
376                 return -ENXIO;
377         }
378         else
379         {
380                 switch (cmd) 
381                 {
382                         case SNDCTL_MIDI_PRETIME:
383                                 if (get_user(val, (int __user *)arg))
384                                         return -EFAULT;
385                                 if (val < 0)
386                                         val = 0;
387                                 val = (HZ * val) / 10;
388                                 parms[dev].prech_timeout = val;
389                                 return put_user(val, (int __user *)arg);
390                         
391                         default:
392                                 if (!midi_devs[dev]->ioctl)
393                                         return -EINVAL;
394                                 return midi_devs[dev]->ioctl(dev, cmd, arg);
395                 }
396         }
397 }
398
399 /* No kernel lock - fine */
400 unsigned int MIDIbuf_poll(int dev, struct file *file, poll_table * wait)
401 {
402         unsigned int mask = 0;
403
404         dev = dev >> 4;
405
406         /* input */
407         poll_wait(file, &input_sleeper[dev], wait);
408         if (DATA_AVAIL(midi_in_buf[dev]))
409                 mask |= POLLIN | POLLRDNORM;
410
411         /* output */
412         poll_wait(file, &midi_sleeper[dev], wait);
413         if (!SPACE_AVAIL(midi_out_buf[dev]))
414                 mask |= POLLOUT | POLLWRNORM;
415         
416         return mask;
417 }
418
419
420 int MIDIbuf_avail(int dev)
421 {
422         if (midi_in_buf[dev])
423                 return DATA_AVAIL (midi_in_buf[dev]);
424         return 0;
425 }
426 EXPORT_SYMBOL(MIDIbuf_avail);
427