]> pilppa.org Git - linux-2.6-omap-h63xx.git/blob - sound/oss/emu10k1/midi.c
Merge branch 'audit.b3' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/audit...
[linux-2.6-omap-h63xx.git] / sound / oss / emu10k1 / midi.c
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         mutex_lock(&card->open_sem);
114         while (card->open_mode & (file->f_mode << FMODE_MIDI_SHIFT)) {
115                 if (file->f_flags & O_NONBLOCK) {
116                         mutex_unlock(&card->open_sem);
117                         return -EBUSY;
118                 }
119
120                 mutex_unlock(&card->open_sem);
121                 interruptible_sleep_on(&card->open_wait);
122
123                 if (signal_pending(current)) {
124                         return -ERESTARTSYS;
125                 }
126
127                 mutex_lock(&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         mutex_unlock(&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         mutex_lock(&card->open_sem);
238         card->open_mode &= ~((file->f_mode << FMODE_MIDI_SHIFT) & (FMODE_MIDI_READ | FMODE_MIDI_WRITE));
239         mutex_unlock(&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         kfree(card->seq_mididev);
527         card->seq_mididev = NULL;
528 }
529
530 int emu10k1_seq_midi_out(int dev, unsigned char midi_byte)
531 {
532         struct emu10k1_card *card;
533         struct midi_hdr *midihdr;
534         unsigned long flags;
535
536         if (midi_devs[dev] == NULL || midi_devs[dev]->devc == NULL)
537                 return -EINVAL;
538
539         card = midi_devs[dev]->devc;
540
541         if ((midihdr = (struct midi_hdr *) kmalloc(sizeof(struct midi_hdr), GFP_KERNEL)) == NULL)
542                 return -EINVAL;
543
544         midihdr->bufferlength = 1;
545         midihdr->bytesrecorded = 0;
546         midihdr->flags = 0;
547
548         if ((midihdr->data = (u8 *) kmalloc(1, GFP_KERNEL)) == NULL) {
549                 ERROR();
550                 kfree(midihdr);
551                 return -EINVAL;
552         }
553
554         *(midihdr->data) = midi_byte;
555         
556         spin_lock_irqsave(&midi_spinlock, flags);
557
558         if (emu10k1_mpuout_add_buffer(card, midihdr) < 0) {
559                 ERROR();
560                 kfree(midihdr->data);
561                 kfree(midihdr);
562                 spin_unlock_irqrestore(&midi_spinlock, flags);
563                 return -EINVAL;
564         }
565
566         spin_unlock_irqrestore(&midi_spinlock, flags);
567
568         return 1;
569 }
570
571 int emu10k1_seq_midi_start_read(int dev)
572 {
573         return 0;
574 }
575
576 int emu10k1_seq_midi_end_read(int dev)
577 {
578         return 0;
579 }
580
581 void emu10k1_seq_midi_kick(int dev)
582 {
583 }
584
585 int emu10k1_seq_midi_buffer_status(int dev)
586 {
587         int count;
588         struct midi_queue *queue;
589         struct emu10k1_card *card;
590
591         if (midi_devs[dev] == NULL || midi_devs[dev]->devc == NULL)
592                 return -EINVAL;
593
594         count = 0;
595
596         card = midi_devs[dev]->devc;
597         queue = card->mpuout->firstmidiq;
598
599         while (queue != NULL) {
600                 count++;
601                 if (queue == card->mpuout->lastmidiq)
602                         break;
603
604                 queue = queue->next;
605         }
606
607         return count;
608 }
609
610 #endif
611