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