diff options
Diffstat (limited to 'sound/oss/emu10k1/midi.c')
-rw-r--r-- | sound/oss/emu10k1/midi.c | 614 |
1 files changed, 0 insertions, 614 deletions
diff --git a/sound/oss/emu10k1/midi.c b/sound/oss/emu10k1/midi.c deleted file mode 100644 index df1e990..0000000 --- a/sound/oss/emu10k1/midi.c +++ /dev/null @@ -1,614 +0,0 @@ -/* - ********************************************************************** - * midi.c - /dev/midi interface for emu10k1 driver - * Copyright 1999, 2000 Creative Labs, Inc. - * - ********************************************************************** - * - * Date Author Summary of changes - * ---- ------ ------------------ - * October 20, 1999 Bertrand Lee base code release - * - ********************************************************************** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, - * USA. - * - ********************************************************************** - */ - -#include <linux/module.h> -#include <linux/poll.h> -#include <linux/slab.h> -#include <linux/sched.h> -#include <linux/smp_lock.h> -#include <asm/uaccess.h> - -#include "hwaccess.h" -#include "cardmo.h" -#include "cardmi.h" -#include "midi.h" - -#ifdef EMU10K1_SEQUENCER -#include "../sound_config.h" -#endif - -static DEFINE_SPINLOCK(midi_spinlock); - -static void init_midi_hdr(struct midi_hdr *midihdr) -{ - midihdr->bufferlength = MIDIIN_BUFLEN; - midihdr->bytesrecorded = 0; - midihdr->flags = 0; -} - -static int midiin_add_buffer(struct emu10k1_mididevice *midi_dev, struct midi_hdr **midihdrptr) -{ - struct midi_hdr *midihdr; - - if ((midihdr = kmalloc(sizeof(struct midi_hdr), GFP_KERNEL)) == NULL) { - ERROR(); - return -EINVAL; - } - - init_midi_hdr(midihdr); - - midihdr->data = kmalloc(MIDIIN_BUFLEN, GFP_KERNEL); - if (!midihdr->data) { - ERROR(); - kfree(midihdr); - return -1; - } - - if (emu10k1_mpuin_add_buffer(midi_dev->card->mpuin, midihdr) < 0) { - ERROR(); - kfree(midihdr->data); - kfree(midihdr); - return -1; - } - - *midihdrptr = midihdr; - list_add_tail(&midihdr->list, &midi_dev->mid_hdrs); - - return 0; -} - -static int emu10k1_midi_open(struct inode *inode, struct file *file) -{ - int minor = iminor(inode); - struct emu10k1_card *card = NULL; - struct emu10k1_mididevice *midi_dev; - struct list_head *entry; - - DPF(2, "emu10k1_midi_open()\n"); - - /* Check for correct device to open */ - list_for_each(entry, &emu10k1_devs) { - card = list_entry(entry, struct emu10k1_card, list); - - if (card->midi_dev == minor) - goto match; - } - - return -ENODEV; - -match: -#ifdef EMU10K1_SEQUENCER - if (card->seq_mididev) /* card is opened by sequencer */ - return -EBUSY; -#endif - - /* Wait for device to become free */ - mutex_lock(&card->open_sem); - while (card->open_mode & (file->f_mode << FMODE_MIDI_SHIFT)) { - if (file->f_flags & O_NONBLOCK) { - mutex_unlock(&card->open_sem); - return -EBUSY; - } - - mutex_unlock(&card->open_sem); - interruptible_sleep_on(&card->open_wait); - - if (signal_pending(current)) { - return -ERESTARTSYS; - } - - mutex_lock(&card->open_sem); - } - - if ((midi_dev = kmalloc(sizeof(*midi_dev), GFP_KERNEL)) == NULL) - return -EINVAL; - - midi_dev->card = card; - midi_dev->mistate = MIDIIN_STATE_STOPPED; - init_waitqueue_head(&midi_dev->oWait); - init_waitqueue_head(&midi_dev->iWait); - midi_dev->ird = 0; - midi_dev->iwr = 0; - midi_dev->icnt = 0; - INIT_LIST_HEAD(&midi_dev->mid_hdrs); - - if (file->f_mode & FMODE_READ) { - struct midi_openinfo dsCardMidiOpenInfo; - struct midi_hdr *midihdr1; - struct midi_hdr *midihdr2; - - dsCardMidiOpenInfo.refdata = (unsigned long) midi_dev; - - if (emu10k1_mpuin_open(card, &dsCardMidiOpenInfo) < 0) { - ERROR(); - kfree(midi_dev); - return -ENODEV; - } - - /* Add two buffers to receive sysex buffer */ - if (midiin_add_buffer(midi_dev, &midihdr1) < 0) { - kfree(midi_dev); - return -ENODEV; - } - - if (midiin_add_buffer(midi_dev, &midihdr2) < 0) { - list_del(&midihdr1->list); - kfree(midihdr1->data); - kfree(midihdr1); - kfree(midi_dev); - return -ENODEV; - } - } - - if (file->f_mode & FMODE_WRITE) { - struct midi_openinfo dsCardMidiOpenInfo; - - dsCardMidiOpenInfo.refdata = (unsigned long) midi_dev; - - if (emu10k1_mpuout_open(card, &dsCardMidiOpenInfo) < 0) { - ERROR(); - kfree(midi_dev); - return -ENODEV; - } - } - - file->private_data = (void *) midi_dev; - - card->open_mode |= (file->f_mode << FMODE_MIDI_SHIFT) & (FMODE_MIDI_READ | FMODE_MIDI_WRITE); - - mutex_unlock(&card->open_sem); - - return nonseekable_open(inode, file); -} - -static int emu10k1_midi_release(struct inode *inode, struct file *file) -{ - struct emu10k1_mididevice *midi_dev = (struct emu10k1_mididevice *) file->private_data; - struct emu10k1_card *card; - - lock_kernel(); - - card = midi_dev->card; - DPF(2, "emu10k1_midi_release()\n"); - - if (file->f_mode & FMODE_WRITE) { - if (!(file->f_flags & O_NONBLOCK)) { - - while (!signal_pending(current) && (card->mpuout->firstmidiq != NULL)) { - DPF(4, "Cannot close - buffers not empty\n"); - - interruptible_sleep_on(&midi_dev->oWait); - - } - } - - emu10k1_mpuout_close(card); - } - - if (file->f_mode & FMODE_READ) { - struct midi_hdr *midihdr; - - if (midi_dev->mistate == MIDIIN_STATE_STARTED) { - emu10k1_mpuin_stop(card); - midi_dev->mistate = MIDIIN_STATE_STOPPED; - } - - emu10k1_mpuin_reset(card); - emu10k1_mpuin_close(card); - - while (!list_empty(&midi_dev->mid_hdrs)) { - midihdr = list_entry(midi_dev->mid_hdrs.next, struct midi_hdr, list); - - list_del(midi_dev->mid_hdrs.next); - kfree(midihdr->data); - kfree(midihdr); - } - } - - kfree(midi_dev); - - mutex_lock(&card->open_sem); - card->open_mode &= ~((file->f_mode << FMODE_MIDI_SHIFT) & (FMODE_MIDI_READ | FMODE_MIDI_WRITE)); - mutex_unlock(&card->open_sem); - wake_up_interruptible(&card->open_wait); - - unlock_kernel(); - - return 0; -} - -static ssize_t emu10k1_midi_read(struct file *file, char __user *buffer, size_t count, loff_t * pos) -{ - struct emu10k1_mididevice *midi_dev = (struct emu10k1_mididevice *) file->private_data; - ssize_t ret = 0; - u16 cnt; - unsigned long flags; - - DPD(4, "emu10k1_midi_read(), count %#x\n", (u32) count); - - if (!access_ok(VERIFY_WRITE, buffer, count)) - return -EFAULT; - - if (midi_dev->mistate == MIDIIN_STATE_STOPPED) { - if (emu10k1_mpuin_start(midi_dev->card) < 0) { - ERROR(); - return -EINVAL; - } - - midi_dev->mistate = MIDIIN_STATE_STARTED; - } - - while (count > 0) { - cnt = MIDIIN_BUFLEN - midi_dev->ird; - - spin_lock_irqsave(&midi_spinlock, flags); - - if (midi_dev->icnt < cnt) - cnt = midi_dev->icnt; - - spin_unlock_irqrestore(&midi_spinlock, flags); - - if (cnt > count) - cnt = count; - - if (cnt <= 0) { - if (file->f_flags & O_NONBLOCK) - return ret ? ret : -EAGAIN; - DPF(2, " Go to sleep...\n"); - - interruptible_sleep_on(&midi_dev->iWait); - - if (signal_pending(current)) - return ret ? ret : -ERESTARTSYS; - - continue; - } - - if (copy_to_user(buffer, midi_dev->iBuf + midi_dev->ird, cnt)) { - ERROR(); - return ret ? ret : -EFAULT; - } - - midi_dev->ird += cnt; - midi_dev->ird %= MIDIIN_BUFLEN; - - spin_lock_irqsave(&midi_spinlock, flags); - - midi_dev->icnt -= cnt; - - spin_unlock_irqrestore(&midi_spinlock, flags); - - count -= cnt; - buffer += cnt; - ret += cnt; - - if (midi_dev->icnt == 0) - break; - } - - return ret; -} - -static ssize_t emu10k1_midi_write(struct file *file, const char __user *buffer, size_t count, loff_t * pos) -{ - struct emu10k1_mididevice *midi_dev = (struct emu10k1_mididevice *) file->private_data; - struct midi_hdr *midihdr; - unsigned long flags; - - DPD(4, "emu10k1_midi_write(), count=%#x\n", (u32) count); - - if (!access_ok(VERIFY_READ, buffer, count)) - return -EFAULT; - - if ((midihdr = kmalloc(sizeof(struct midi_hdr), GFP_KERNEL)) == NULL) - return -EINVAL; - - midihdr->bufferlength = count; - midihdr->bytesrecorded = 0; - midihdr->flags = 0; - - midihdr->data = kmalloc(count, GFP_KERNEL); - if (!midihdr->data) { - ERROR(); - kfree(midihdr); - return -EINVAL; - } - - if (copy_from_user(midihdr->data, buffer, count)) { - kfree(midihdr->data); - kfree(midihdr); - return -EFAULT; - } - - spin_lock_irqsave(&midi_spinlock, flags); - - if (emu10k1_mpuout_add_buffer(midi_dev->card, midihdr) < 0) { - ERROR(); - kfree(midihdr->data); - kfree(midihdr); - spin_unlock_irqrestore(&midi_spinlock, flags); - return -EINVAL; - } - - spin_unlock_irqrestore(&midi_spinlock, flags); - - return count; -} - -static unsigned int emu10k1_midi_poll(struct file *file, struct poll_table_struct *wait) -{ - struct emu10k1_mididevice *midi_dev = (struct emu10k1_mididevice *) file->private_data; - unsigned long flags; - unsigned int mask = 0; - - DPF(4, "emu10k1_midi_poll() called\n"); - - if (file->f_mode & FMODE_WRITE) - poll_wait(file, &midi_dev->oWait, wait); - - if (file->f_mode & FMODE_READ) - poll_wait(file, &midi_dev->iWait, wait); - - spin_lock_irqsave(&midi_spinlock, flags); - - if (file->f_mode & FMODE_WRITE) - mask |= POLLOUT | POLLWRNORM; - - if (file->f_mode & FMODE_READ) { - if (midi_dev->mistate == MIDIIN_STATE_STARTED) - if (midi_dev->icnt > 0) - mask |= POLLIN | POLLRDNORM; - } - - spin_unlock_irqrestore(&midi_spinlock, flags); - - return mask; -} - -int emu10k1_midi_callback(unsigned long msg, unsigned long refdata, unsigned long *pmsg) -{ - struct emu10k1_mididevice *midi_dev = (struct emu10k1_mididevice *) refdata; - struct midi_hdr *midihdr = NULL; - unsigned long flags; - int i; - - DPF(4, "emu10k1_midi_callback()\n"); - - spin_lock_irqsave(&midi_spinlock, flags); - - switch (msg) { - case ICARDMIDI_OUTLONGDATA: - midihdr = (struct midi_hdr *) pmsg[2]; - - kfree(midihdr->data); - kfree(midihdr); - wake_up_interruptible(&midi_dev->oWait); - - break; - - case ICARDMIDI_INLONGDATA: - midihdr = (struct midi_hdr *) pmsg[2]; - - for (i = 0; i < midihdr->bytesrecorded; i++) { - midi_dev->iBuf[midi_dev->iwr++] = midihdr->data[i]; - midi_dev->iwr %= MIDIIN_BUFLEN; - } - - midi_dev->icnt += midihdr->bytesrecorded; - - if (midi_dev->mistate == MIDIIN_STATE_STARTED) { - init_midi_hdr(midihdr); - emu10k1_mpuin_add_buffer(midi_dev->card->mpuin, midihdr); - wake_up_interruptible(&midi_dev->iWait); - } - break; - - case ICARDMIDI_INDATA: - { - u8 *pBuf = (u8 *) & pmsg[1]; - u16 bytesvalid = pmsg[2]; - - for (i = 0; i < bytesvalid; i++) { - midi_dev->iBuf[midi_dev->iwr++] = pBuf[i]; - midi_dev->iwr %= MIDIIN_BUFLEN; - } - - midi_dev->icnt += bytesvalid; - } - - wake_up_interruptible(&midi_dev->iWait); - break; - - default: /* Unknown message */ - spin_unlock_irqrestore(&midi_spinlock, flags); - return -1; - } - - spin_unlock_irqrestore(&midi_spinlock, flags); - - return 0; -} - -/* MIDI file operations */ -const struct file_operations emu10k1_midi_fops = { - .owner = THIS_MODULE, - .read = emu10k1_midi_read, - .write = emu10k1_midi_write, - .poll = emu10k1_midi_poll, - .open = emu10k1_midi_open, - .release = emu10k1_midi_release, -}; - - -#ifdef EMU10K1_SEQUENCER - -/* functions used for sequencer access */ - -int emu10k1_seq_midi_open(int dev, int mode, - void (*input) (int dev, unsigned char data), - void (*output) (int dev)) -{ - struct emu10k1_card *card; - struct midi_openinfo dsCardMidiOpenInfo; - struct emu10k1_mididevice *midi_dev; - - if (midi_devs[dev] == NULL || midi_devs[dev]->devc == NULL) - return -EINVAL; - - card = midi_devs[dev]->devc; - - if (card->open_mode) /* card is opened native */ - return -EBUSY; - - DPF(2, "emu10k1_seq_midi_open()\n"); - - if ((midi_dev = kmalloc(sizeof(*midi_dev), GFP_KERNEL)) == NULL) - return -EINVAL; - - midi_dev->card = card; - midi_dev->mistate = MIDIIN_STATE_STOPPED; - init_waitqueue_head(&midi_dev->oWait); - init_waitqueue_head(&midi_dev->iWait); - midi_dev->ird = 0; - midi_dev->iwr = 0; - midi_dev->icnt = 0; - INIT_LIST_HEAD(&midi_dev->mid_hdrs); - - dsCardMidiOpenInfo.refdata = (unsigned long) midi_dev; - - if (emu10k1_mpuout_open(card, &dsCardMidiOpenInfo) < 0) { - ERROR(); - return -ENODEV; - } - - card->seq_mididev = midi_dev; - - return 0; -} - -void emu10k1_seq_midi_close(int dev) -{ - struct emu10k1_card *card; - - DPF(2, "emu10k1_seq_midi_close()\n"); - if (midi_devs[dev] == NULL || midi_devs[dev]->devc == NULL) - return; - - card = midi_devs[dev]->devc; - emu10k1_mpuout_close(card); - - kfree(card->seq_mididev); - card->seq_mididev = NULL; -} - -int emu10k1_seq_midi_out(int dev, unsigned char midi_byte) -{ - struct emu10k1_card *card; - struct midi_hdr *midihdr; - unsigned long flags; - - if (midi_devs[dev] == NULL || midi_devs[dev]->devc == NULL) - return -EINVAL; - - card = midi_devs[dev]->devc; - - if ((midihdr = kmalloc(sizeof(struct midi_hdr), GFP_KERNEL)) == NULL) - return -EINVAL; - - midihdr->bufferlength = 1; - midihdr->bytesrecorded = 0; - midihdr->flags = 0; - - midihdr->data = kmalloc(1, GFP_KERNEL); - if (!midihdr->data) { - ERROR(); - kfree(midihdr); - return -EINVAL; - } - - *(midihdr->data) = midi_byte; - - spin_lock_irqsave(&midi_spinlock, flags); - - if (emu10k1_mpuout_add_buffer(card, midihdr) < 0) { - ERROR(); - kfree(midihdr->data); - kfree(midihdr); - spin_unlock_irqrestore(&midi_spinlock, flags); - return -EINVAL; - } - - spin_unlock_irqrestore(&midi_spinlock, flags); - - return 1; -} - -int emu10k1_seq_midi_start_read(int dev) -{ - return 0; -} - -int emu10k1_seq_midi_end_read(int dev) -{ - return 0; -} - -void emu10k1_seq_midi_kick(int dev) -{ -} - -int emu10k1_seq_midi_buffer_status(int dev) -{ - int count; - struct midi_queue *queue; - struct emu10k1_card *card; - - if (midi_devs[dev] == NULL || midi_devs[dev]->devc == NULL) - return -EINVAL; - - count = 0; - - card = midi_devs[dev]->devc; - queue = card->mpuout->firstmidiq; - - while (queue != NULL) { - count++; - if (queue == card->mpuout->lastmidiq) - break; - - queue = queue->next; - } - - return count; -} - -#endif - |