• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, 0, 0);
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 
drain_midi_queue(int dev)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 
midi_input_intr(int dev,unsigned char data)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 
midi_output_intr(int dev)113 static void midi_output_intr(int dev)
114 {
115 	/*
116 	 * Currently NOP
117 	 */
118 }
119 
midi_poll(unsigned long dummy)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 
MIDIbuf_open(int dev,struct file * file)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 
MIDIbuf_release(int dev,struct file * file)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 
MIDIbuf_write(int dev,struct file * file,const char __user * buf,int count)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 
MIDIbuf_read(int dev,struct file * file,char __user * buf,int count)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 
MIDIbuf_ioctl(int dev,struct file * file,unsigned int cmd,void __user * arg)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 */
MIDIbuf_poll(int dev,struct file * file,poll_table * wait)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 
MIDIbuf_avail(int dev)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 
428