diff options
Diffstat (limited to 'sound/oss/emu10k1/midi.c')
-rw-r--r-- | sound/oss/emu10k1/midi.c | 613 |
1 files changed, 613 insertions, 0 deletions
diff --git a/sound/oss/emu10k1/midi.c b/sound/oss/emu10k1/midi.c new file mode 100644 index 000000000000..33dea3d56c1e --- /dev/null +++ b/sound/oss/emu10k1/midi.c | |||
@@ -0,0 +1,613 @@ | |||
1 | /* | ||
2 | ********************************************************************** | ||
3 | * midi.c - /dev/midi interface for emu10k1 driver | ||
4 | * Copyright 1999, 2000 Creative Labs, Inc. | ||
5 | * | ||
6 | ********************************************************************** | ||
7 | * | ||
8 | * Date Author Summary of changes | ||
9 | * ---- ------ ------------------ | ||
10 | * October 20, 1999 Bertrand Lee base code release | ||
11 | * | ||
12 | ********************************************************************** | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or | ||
15 | * modify it under the terms of the GNU General Public License as | ||
16 | * published by the Free Software Foundation; either version 2 of | ||
17 | * the License, or (at your option) any later version. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, | ||
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
22 | * GNU General Public License for more details. | ||
23 | * | ||
24 | * You should have received a copy of the GNU General Public | ||
25 | * License along with this program; if not, write to the Free | ||
26 | * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, | ||
27 | * USA. | ||
28 | * | ||
29 | ********************************************************************** | ||
30 | */ | ||
31 | |||
32 | #include <linux/module.h> | ||
33 | #include <linux/poll.h> | ||
34 | #include <linux/slab.h> | ||
35 | #include <linux/sched.h> | ||
36 | #include <linux/smp_lock.h> | ||
37 | #include <asm/uaccess.h> | ||
38 | |||
39 | #include "hwaccess.h" | ||
40 | #include "cardmo.h" | ||
41 | #include "cardmi.h" | ||
42 | #include "midi.h" | ||
43 | |||
44 | #ifdef EMU10K1_SEQUENCER | ||
45 | #include "../sound_config.h" | ||
46 | #endif | ||
47 | |||
48 | static DEFINE_SPINLOCK(midi_spinlock __attribute((unused))); | ||
49 | |||
50 | static void init_midi_hdr(struct midi_hdr *midihdr) | ||
51 | { | ||
52 | midihdr->bufferlength = MIDIIN_BUFLEN; | ||
53 | midihdr->bytesrecorded = 0; | ||
54 | midihdr->flags = 0; | ||
55 | } | ||
56 | |||
57 | static int midiin_add_buffer(struct emu10k1_mididevice *midi_dev, struct midi_hdr **midihdrptr) | ||
58 | { | ||
59 | struct midi_hdr *midihdr; | ||
60 | |||
61 | if ((midihdr = (struct midi_hdr *) kmalloc(sizeof(struct midi_hdr), GFP_KERNEL)) == NULL) { | ||
62 | ERROR(); | ||
63 | return -EINVAL; | ||
64 | } | ||
65 | |||
66 | init_midi_hdr(midihdr); | ||
67 | |||
68 | if ((midihdr->data = (u8 *) kmalloc(MIDIIN_BUFLEN, GFP_KERNEL)) == NULL) { | ||
69 | ERROR(); | ||
70 | kfree(midihdr); | ||
71 | return -1; | ||
72 | } | ||
73 | |||
74 | if (emu10k1_mpuin_add_buffer(midi_dev->card->mpuin, midihdr) < 0) { | ||
75 | ERROR(); | ||
76 | kfree(midihdr->data); | ||
77 | kfree(midihdr); | ||
78 | return -1; | ||
79 | } | ||
80 | |||
81 | *midihdrptr = midihdr; | ||
82 | list_add_tail(&midihdr->list, &midi_dev->mid_hdrs); | ||
83 | |||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | static int emu10k1_midi_open(struct inode *inode, struct file *file) | ||
88 | { | ||
89 | int minor = iminor(inode); | ||
90 | struct emu10k1_card *card = NULL; | ||
91 | struct emu10k1_mididevice *midi_dev; | ||
92 | struct list_head *entry; | ||
93 | |||
94 | DPF(2, "emu10k1_midi_open()\n"); | ||
95 | |||
96 | /* Check for correct device to open */ | ||
97 | list_for_each(entry, &emu10k1_devs) { | ||
98 | card = list_entry(entry, struct emu10k1_card, list); | ||
99 | |||
100 | if (card->midi_dev == minor) | ||
101 | goto match; | ||
102 | } | ||
103 | |||
104 | return -ENODEV; | ||
105 | |||
106 | match: | ||
107 | #ifdef EMU10K1_SEQUENCER | ||
108 | if (card->seq_mididev) /* card is opened by sequencer */ | ||
109 | return -EBUSY; | ||
110 | #endif | ||
111 | |||
112 | /* Wait for device to become free */ | ||
113 | down(&card->open_sem); | ||
114 | while (card->open_mode & (file->f_mode << FMODE_MIDI_SHIFT)) { | ||
115 | if (file->f_flags & O_NONBLOCK) { | ||
116 | up(&card->open_sem); | ||
117 | return -EBUSY; | ||
118 | } | ||
119 | |||
120 | up(&card->open_sem); | ||
121 | interruptible_sleep_on(&card->open_wait); | ||
122 | |||
123 | if (signal_pending(current)) { | ||
124 | return -ERESTARTSYS; | ||
125 | } | ||
126 | |||
127 | down(&card->open_sem); | ||
128 | } | ||
129 | |||
130 | if ((midi_dev = (struct emu10k1_mididevice *) kmalloc(sizeof(*midi_dev), GFP_KERNEL)) == NULL) | ||
131 | return -EINVAL; | ||
132 | |||
133 | midi_dev->card = card; | ||
134 | midi_dev->mistate = MIDIIN_STATE_STOPPED; | ||
135 | init_waitqueue_head(&midi_dev->oWait); | ||
136 | init_waitqueue_head(&midi_dev->iWait); | ||
137 | midi_dev->ird = 0; | ||
138 | midi_dev->iwr = 0; | ||
139 | midi_dev->icnt = 0; | ||
140 | INIT_LIST_HEAD(&midi_dev->mid_hdrs); | ||
141 | |||
142 | if (file->f_mode & FMODE_READ) { | ||
143 | struct midi_openinfo dsCardMidiOpenInfo; | ||
144 | struct midi_hdr *midihdr1; | ||
145 | struct midi_hdr *midihdr2; | ||
146 | |||
147 | dsCardMidiOpenInfo.refdata = (unsigned long) midi_dev; | ||
148 | |||
149 | if (emu10k1_mpuin_open(card, &dsCardMidiOpenInfo) < 0) { | ||
150 | ERROR(); | ||
151 | kfree(midi_dev); | ||
152 | return -ENODEV; | ||
153 | } | ||
154 | |||
155 | /* Add two buffers to receive sysex buffer */ | ||
156 | if (midiin_add_buffer(midi_dev, &midihdr1) < 0) { | ||
157 | kfree(midi_dev); | ||
158 | return -ENODEV; | ||
159 | } | ||
160 | |||
161 | if (midiin_add_buffer(midi_dev, &midihdr2) < 0) { | ||
162 | list_del(&midihdr1->list); | ||
163 | kfree(midihdr1->data); | ||
164 | kfree(midihdr1); | ||
165 | kfree(midi_dev); | ||
166 | return -ENODEV; | ||
167 | } | ||
168 | } | ||
169 | |||
170 | if (file->f_mode & FMODE_WRITE) { | ||
171 | struct midi_openinfo dsCardMidiOpenInfo; | ||
172 | |||
173 | dsCardMidiOpenInfo.refdata = (unsigned long) midi_dev; | ||
174 | |||
175 | if (emu10k1_mpuout_open(card, &dsCardMidiOpenInfo) < 0) { | ||
176 | ERROR(); | ||
177 | kfree(midi_dev); | ||
178 | return -ENODEV; | ||
179 | } | ||
180 | } | ||
181 | |||
182 | file->private_data = (void *) midi_dev; | ||
183 | |||
184 | card->open_mode |= (file->f_mode << FMODE_MIDI_SHIFT) & (FMODE_MIDI_READ | FMODE_MIDI_WRITE); | ||
185 | |||
186 | up(&card->open_sem); | ||
187 | |||
188 | return nonseekable_open(inode, file); | ||
189 | } | ||
190 | |||
191 | static int emu10k1_midi_release(struct inode *inode, struct file *file) | ||
192 | { | ||
193 | struct emu10k1_mididevice *midi_dev = (struct emu10k1_mididevice *) file->private_data; | ||
194 | struct emu10k1_card *card; | ||
195 | |||
196 | lock_kernel(); | ||
197 | |||
198 | card = midi_dev->card; | ||
199 | DPF(2, "emu10k1_midi_release()\n"); | ||
200 | |||
201 | if (file->f_mode & FMODE_WRITE) { | ||
202 | if (!(file->f_flags & O_NONBLOCK)) { | ||
203 | |||
204 | while (!signal_pending(current) && (card->mpuout->firstmidiq != NULL)) { | ||
205 | DPF(4, "Cannot close - buffers not empty\n"); | ||
206 | |||
207 | interruptible_sleep_on(&midi_dev->oWait); | ||
208 | |||
209 | } | ||
210 | } | ||
211 | |||
212 | emu10k1_mpuout_close(card); | ||
213 | } | ||
214 | |||
215 | if (file->f_mode & FMODE_READ) { | ||
216 | struct midi_hdr *midihdr; | ||
217 | |||
218 | if (midi_dev->mistate == MIDIIN_STATE_STARTED) { | ||
219 | emu10k1_mpuin_stop(card); | ||
220 | midi_dev->mistate = MIDIIN_STATE_STOPPED; | ||
221 | } | ||
222 | |||
223 | emu10k1_mpuin_reset(card); | ||
224 | emu10k1_mpuin_close(card); | ||
225 | |||
226 | while (!list_empty(&midi_dev->mid_hdrs)) { | ||
227 | midihdr = list_entry(midi_dev->mid_hdrs.next, struct midi_hdr, list); | ||
228 | |||
229 | list_del(midi_dev->mid_hdrs.next); | ||
230 | kfree(midihdr->data); | ||
231 | kfree(midihdr); | ||
232 | } | ||
233 | } | ||
234 | |||
235 | kfree(midi_dev); | ||
236 | |||
237 | down(&card->open_sem); | ||
238 | card->open_mode &= ~((file->f_mode << FMODE_MIDI_SHIFT) & (FMODE_MIDI_READ | FMODE_MIDI_WRITE)); | ||
239 | up(&card->open_sem); | ||
240 | wake_up_interruptible(&card->open_wait); | ||
241 | |||
242 | unlock_kernel(); | ||
243 | |||
244 | return 0; | ||
245 | } | ||
246 | |||
247 | static ssize_t emu10k1_midi_read(struct file *file, char __user *buffer, size_t count, loff_t * pos) | ||
248 | { | ||
249 | struct emu10k1_mididevice *midi_dev = (struct emu10k1_mididevice *) file->private_data; | ||
250 | ssize_t ret = 0; | ||
251 | u16 cnt; | ||
252 | unsigned long flags; | ||
253 | |||
254 | DPD(4, "emu10k1_midi_read(), count %#x\n", (u32) count); | ||
255 | |||
256 | if (!access_ok(VERIFY_WRITE, buffer, count)) | ||
257 | return -EFAULT; | ||
258 | |||
259 | if (midi_dev->mistate == MIDIIN_STATE_STOPPED) { | ||
260 | if (emu10k1_mpuin_start(midi_dev->card) < 0) { | ||
261 | ERROR(); | ||
262 | return -EINVAL; | ||
263 | } | ||
264 | |||
265 | midi_dev->mistate = MIDIIN_STATE_STARTED; | ||
266 | } | ||
267 | |||
268 | while (count > 0) { | ||
269 | cnt = MIDIIN_BUFLEN - midi_dev->ird; | ||
270 | |||
271 | spin_lock_irqsave(&midi_spinlock, flags); | ||
272 | |||
273 | if (midi_dev->icnt < cnt) | ||
274 | cnt = midi_dev->icnt; | ||
275 | |||
276 | spin_unlock_irqrestore(&midi_spinlock, flags); | ||
277 | |||
278 | if (cnt > count) | ||
279 | cnt = count; | ||
280 | |||
281 | if (cnt <= 0) { | ||
282 | if (file->f_flags & O_NONBLOCK) | ||
283 | return ret ? ret : -EAGAIN; | ||
284 | DPF(2, " Go to sleep...\n"); | ||
285 | |||
286 | interruptible_sleep_on(&midi_dev->iWait); | ||
287 | |||
288 | if (signal_pending(current)) | ||
289 | return ret ? ret : -ERESTARTSYS; | ||
290 | |||
291 | continue; | ||
292 | } | ||
293 | |||
294 | if (copy_to_user(buffer, midi_dev->iBuf + midi_dev->ird, cnt)) { | ||
295 | ERROR(); | ||
296 | return ret ? ret : -EFAULT; | ||
297 | } | ||
298 | |||
299 | midi_dev->ird += cnt; | ||
300 | midi_dev->ird %= MIDIIN_BUFLEN; | ||
301 | |||
302 | spin_lock_irqsave(&midi_spinlock, flags); | ||
303 | |||
304 | midi_dev->icnt -= cnt; | ||
305 | |||
306 | spin_unlock_irqrestore(&midi_spinlock, flags); | ||
307 | |||
308 | count -= cnt; | ||
309 | buffer += cnt; | ||
310 | ret += cnt; | ||
311 | |||
312 | if (midi_dev->icnt == 0) | ||
313 | break; | ||
314 | } | ||
315 | |||
316 | return ret; | ||
317 | } | ||
318 | |||
319 | static ssize_t emu10k1_midi_write(struct file *file, const char __user *buffer, size_t count, loff_t * pos) | ||
320 | { | ||
321 | struct emu10k1_mididevice *midi_dev = (struct emu10k1_mididevice *) file->private_data; | ||
322 | struct midi_hdr *midihdr; | ||
323 | unsigned long flags; | ||
324 | |||
325 | DPD(4, "emu10k1_midi_write(), count=%#x\n", (u32) count); | ||
326 | |||
327 | if (!access_ok(VERIFY_READ, buffer, count)) | ||
328 | return -EFAULT; | ||
329 | |||
330 | if ((midihdr = (struct midi_hdr *) kmalloc(sizeof(struct midi_hdr), GFP_KERNEL)) == NULL) | ||
331 | return -EINVAL; | ||
332 | |||
333 | midihdr->bufferlength = count; | ||
334 | midihdr->bytesrecorded = 0; | ||
335 | midihdr->flags = 0; | ||
336 | |||
337 | if ((midihdr->data = (u8 *) kmalloc(count, GFP_KERNEL)) == NULL) { | ||
338 | ERROR(); | ||
339 | kfree(midihdr); | ||
340 | return -EINVAL; | ||
341 | } | ||
342 | |||
343 | if (copy_from_user(midihdr->data, buffer, count)) { | ||
344 | kfree(midihdr->data); | ||
345 | kfree(midihdr); | ||
346 | return -EFAULT; | ||
347 | } | ||
348 | |||
349 | spin_lock_irqsave(&midi_spinlock, flags); | ||
350 | |||
351 | if (emu10k1_mpuout_add_buffer(midi_dev->card, midihdr) < 0) { | ||
352 | ERROR(); | ||
353 | kfree(midihdr->data); | ||
354 | kfree(midihdr); | ||
355 | spin_unlock_irqrestore(&midi_spinlock, flags); | ||
356 | return -EINVAL; | ||
357 | } | ||
358 | |||
359 | spin_unlock_irqrestore(&midi_spinlock, flags); | ||
360 | |||
361 | return count; | ||
362 | } | ||
363 | |||
364 | static unsigned int emu10k1_midi_poll(struct file *file, struct poll_table_struct *wait) | ||
365 | { | ||
366 | struct emu10k1_mididevice *midi_dev = (struct emu10k1_mididevice *) file->private_data; | ||
367 | unsigned long flags; | ||
368 | unsigned int mask = 0; | ||
369 | |||
370 | DPF(4, "emu10k1_midi_poll() called\n"); | ||
371 | |||
372 | if (file->f_mode & FMODE_WRITE) | ||
373 | poll_wait(file, &midi_dev->oWait, wait); | ||
374 | |||
375 | if (file->f_mode & FMODE_READ) | ||
376 | poll_wait(file, &midi_dev->iWait, wait); | ||
377 | |||
378 | spin_lock_irqsave(&midi_spinlock, flags); | ||
379 | |||
380 | if (file->f_mode & FMODE_WRITE) | ||
381 | mask |= POLLOUT | POLLWRNORM; | ||
382 | |||
383 | if (file->f_mode & FMODE_READ) { | ||
384 | if (midi_dev->mistate == MIDIIN_STATE_STARTED) | ||
385 | if (midi_dev->icnt > 0) | ||
386 | mask |= POLLIN | POLLRDNORM; | ||
387 | } | ||
388 | |||
389 | spin_unlock_irqrestore(&midi_spinlock, flags); | ||
390 | |||
391 | return mask; | ||
392 | } | ||
393 | |||
394 | int emu10k1_midi_callback(unsigned long msg, unsigned long refdata, unsigned long *pmsg) | ||
395 | { | ||
396 | struct emu10k1_mididevice *midi_dev = (struct emu10k1_mididevice *) refdata; | ||
397 | struct midi_hdr *midihdr = NULL; | ||
398 | unsigned long flags; | ||
399 | int i; | ||
400 | |||
401 | DPF(4, "emu10k1_midi_callback()\n"); | ||
402 | |||
403 | spin_lock_irqsave(&midi_spinlock, flags); | ||
404 | |||
405 | switch (msg) { | ||
406 | case ICARDMIDI_OUTLONGDATA: | ||
407 | midihdr = (struct midi_hdr *) pmsg[2]; | ||
408 | |||
409 | kfree(midihdr->data); | ||
410 | kfree(midihdr); | ||
411 | wake_up_interruptible(&midi_dev->oWait); | ||
412 | |||
413 | break; | ||
414 | |||
415 | case ICARDMIDI_INLONGDATA: | ||
416 | midihdr = (struct midi_hdr *) pmsg[2]; | ||
417 | |||
418 | for (i = 0; i < midihdr->bytesrecorded; i++) { | ||
419 | midi_dev->iBuf[midi_dev->iwr++] = midihdr->data[i]; | ||
420 | midi_dev->iwr %= MIDIIN_BUFLEN; | ||
421 | } | ||
422 | |||
423 | midi_dev->icnt += midihdr->bytesrecorded; | ||
424 | |||
425 | if (midi_dev->mistate == MIDIIN_STATE_STARTED) { | ||
426 | init_midi_hdr(midihdr); | ||
427 | emu10k1_mpuin_add_buffer(midi_dev->card->mpuin, midihdr); | ||
428 | wake_up_interruptible(&midi_dev->iWait); | ||
429 | } | ||
430 | break; | ||
431 | |||
432 | case ICARDMIDI_INDATA: | ||
433 | { | ||
434 | u8 *pBuf = (u8 *) & pmsg[1]; | ||
435 | u16 bytesvalid = pmsg[2]; | ||
436 | |||
437 | for (i = 0; i < bytesvalid; i++) { | ||
438 | midi_dev->iBuf[midi_dev->iwr++] = pBuf[i]; | ||
439 | midi_dev->iwr %= MIDIIN_BUFLEN; | ||
440 | } | ||
441 | |||
442 | midi_dev->icnt += bytesvalid; | ||
443 | } | ||
444 | |||
445 | wake_up_interruptible(&midi_dev->iWait); | ||
446 | break; | ||
447 | |||
448 | default: /* Unknown message */ | ||
449 | spin_unlock_irqrestore(&midi_spinlock, flags); | ||
450 | return -1; | ||
451 | } | ||
452 | |||
453 | spin_unlock_irqrestore(&midi_spinlock, flags); | ||
454 | |||
455 | return 0; | ||
456 | } | ||
457 | |||
458 | /* MIDI file operations */ | ||
459 | struct file_operations emu10k1_midi_fops = { | ||
460 | .owner = THIS_MODULE, | ||
461 | .read = emu10k1_midi_read, | ||
462 | .write = emu10k1_midi_write, | ||
463 | .poll = emu10k1_midi_poll, | ||
464 | .open = emu10k1_midi_open, | ||
465 | .release = emu10k1_midi_release, | ||
466 | }; | ||
467 | |||
468 | |||
469 | #ifdef EMU10K1_SEQUENCER | ||
470 | |||
471 | /* functions used for sequencer access */ | ||
472 | |||
473 | int emu10k1_seq_midi_open(int dev, int mode, | ||
474 | void (*input) (int dev, unsigned char data), | ||
475 | void (*output) (int dev)) | ||
476 | { | ||
477 | struct emu10k1_card *card; | ||
478 | struct midi_openinfo dsCardMidiOpenInfo; | ||
479 | struct emu10k1_mididevice *midi_dev; | ||
480 | |||
481 | if (midi_devs[dev] == NULL || midi_devs[dev]->devc == NULL) | ||
482 | return -EINVAL; | ||
483 | |||
484 | card = midi_devs[dev]->devc; | ||
485 | |||
486 | if (card->open_mode) /* card is opened native */ | ||
487 | return -EBUSY; | ||
488 | |||
489 | DPF(2, "emu10k1_seq_midi_open()\n"); | ||
490 | |||
491 | if ((midi_dev = (struct emu10k1_mididevice *) kmalloc(sizeof(*midi_dev), GFP_KERNEL)) == NULL) | ||
492 | return -EINVAL; | ||
493 | |||
494 | midi_dev->card = card; | ||
495 | midi_dev->mistate = MIDIIN_STATE_STOPPED; | ||
496 | init_waitqueue_head(&midi_dev->oWait); | ||
497 | init_waitqueue_head(&midi_dev->iWait); | ||
498 | midi_dev->ird = 0; | ||
499 | midi_dev->iwr = 0; | ||
500 | midi_dev->icnt = 0; | ||
501 | INIT_LIST_HEAD(&midi_dev->mid_hdrs); | ||
502 | |||
503 | dsCardMidiOpenInfo.refdata = (unsigned long) midi_dev; | ||
504 | |||
505 | if (emu10k1_mpuout_open(card, &dsCardMidiOpenInfo) < 0) { | ||
506 | ERROR(); | ||
507 | return -ENODEV; | ||
508 | } | ||
509 | |||
510 | card->seq_mididev = midi_dev; | ||
511 | |||
512 | return 0; | ||
513 | } | ||
514 | |||
515 | void emu10k1_seq_midi_close(int dev) | ||
516 | { | ||
517 | struct emu10k1_card *card; | ||
518 | |||
519 | DPF(2, "emu10k1_seq_midi_close()\n"); | ||
520 | if (midi_devs[dev] == NULL || midi_devs[dev]->devc == NULL) | ||
521 | return; | ||
522 | |||
523 | card = midi_devs[dev]->devc; | ||
524 | emu10k1_mpuout_close(card); | ||
525 | |||
526 | if (card->seq_mididev) { | ||
527 | kfree(card->seq_mididev); | ||
528 | card->seq_mididev = NULL; | ||
529 | } | ||
530 | } | ||
531 | |||
532 | int emu10k1_seq_midi_out(int dev, unsigned char midi_byte) | ||
533 | { | ||
534 | struct emu10k1_card *card; | ||
535 | struct midi_hdr *midihdr; | ||
536 | unsigned long flags; | ||
537 | |||
538 | if (midi_devs[dev] == NULL || midi_devs[dev]->devc == NULL) | ||
539 | return -EINVAL; | ||
540 | |||
541 | card = midi_devs[dev]->devc; | ||
542 | |||
543 | if ((midihdr = (struct midi_hdr *) kmalloc(sizeof(struct midi_hdr), GFP_KERNEL)) == NULL) | ||
544 | return -EINVAL; | ||
545 | |||
546 | midihdr->bufferlength = 1; | ||
547 | midihdr->bytesrecorded = 0; | ||
548 | midihdr->flags = 0; | ||
549 | |||
550 | if ((midihdr->data = (u8 *) kmalloc(1, GFP_KERNEL)) == NULL) { | ||
551 | ERROR(); | ||
552 | kfree(midihdr); | ||
553 | return -EINVAL; | ||
554 | } | ||
555 | |||
556 | *(midihdr->data) = midi_byte; | ||
557 | |||
558 | spin_lock_irqsave(&midi_spinlock, flags); | ||
559 | |||
560 | if (emu10k1_mpuout_add_buffer(card, midihdr) < 0) { | ||
561 | ERROR(); | ||
562 | kfree(midihdr->data); | ||
563 | kfree(midihdr); | ||
564 | spin_unlock_irqrestore(&midi_spinlock, flags); | ||
565 | return -EINVAL; | ||
566 | } | ||
567 | |||
568 | spin_unlock_irqrestore(&midi_spinlock, flags); | ||
569 | |||
570 | return 1; | ||
571 | } | ||
572 | |||
573 | int emu10k1_seq_midi_start_read(int dev) | ||
574 | { | ||
575 | return 0; | ||
576 | } | ||
577 | |||
578 | int emu10k1_seq_midi_end_read(int dev) | ||
579 | { | ||
580 | return 0; | ||
581 | } | ||
582 | |||
583 | void emu10k1_seq_midi_kick(int dev) | ||
584 | { | ||
585 | } | ||
586 | |||
587 | int emu10k1_seq_midi_buffer_status(int dev) | ||
588 | { | ||
589 | int count; | ||
590 | struct midi_queue *queue; | ||
591 | struct emu10k1_card *card; | ||
592 | |||
593 | if (midi_devs[dev] == NULL || midi_devs[dev]->devc == NULL) | ||
594 | return -EINVAL; | ||
595 | |||
596 | count = 0; | ||
597 | |||
598 | card = midi_devs[dev]->devc; | ||
599 | queue = card->mpuout->firstmidiq; | ||
600 | |||
601 | while (queue != NULL) { | ||
602 | count++; | ||
603 | if (queue == card->mpuout->lastmidiq) | ||
604 | break; | ||
605 | |||
606 | queue = queue->next; | ||
607 | } | ||
608 | |||
609 | return count; | ||
610 | } | ||
611 | |||
612 | #endif | ||
613 | |||