[funini.com] -> [kei@sodan] -> Kernel Reading

root/sound/oss/v_midi.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. v_midi_open
  2. v_midi_close
  3. v_midi_out
  4. v_midi_start_read
  5. v_midi_end_read
  6. v_midi_ioctl
  7. attach_v_midi
  8. probe_v_midi
  9. unload_v_midi
  10. init_vmidi
  11. cleanup_vmidi

/*
 * sound/oss/v_midi.c
 *
 * The low level driver for the Sound Blaster DS chips.
 *
 *
 * Copyright (C) by Hannu Savolainen 1993-1996
 *
 * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
 * Version 2 (June 1991). See the "COPYING" file distributed with this software
 * for more info.
 * ??
 *
 * Changes
 *      Alan Cox                Modularisation, changed memory allocations
 *      Christoph Hellwig       Adapted to module_init/module_exit
 *
 * Status
 *      Untested
 */

#include <linux/init.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include "sound_config.h"

#include "v_midi.h"

static vmidi_devc *v_devc[2] = { NULL, NULL};
static int midi1,midi2;
static void *midi_mem = NULL;

/*
 * The DSP channel can be used either for input or output. Variable
 * 'sb_irq_mode' will be set when the program calls read or write first time
 * after open. Current version doesn't support mode changes without closing
 * and reopening the device. Support for this feature may be implemented in a
 * future version of this driver.
 */


static int v_midi_open (int dev, int mode,
              void            (*input) (int dev, unsigned char data),
              void            (*output) (int dev)
)
{
        vmidi_devc *devc = midi_devs[dev]->devc;
        unsigned long flags;

        if (devc == NULL)
                return -(ENXIO);

        spin_lock_irqsave(&devc->lock,flags);
        if (devc->opened)
        {
                spin_unlock_irqrestore(&devc->lock,flags);
                return -(EBUSY);
        }
        devc->opened = 1;
        spin_unlock_irqrestore(&devc->lock,flags);

        devc->intr_active = 1;

        if (mode & OPEN_READ)
        {
                devc->input_opened = 1;
                devc->midi_input_intr = input;
        }

        return 0;
}

static void v_midi_close (int dev)
{
        vmidi_devc *devc = midi_devs[dev]->devc;
        unsigned long flags;

        if (devc == NULL)
                return;

        spin_lock_irqsave(&devc->lock,flags);
        devc->intr_active = 0;
        devc->input_opened = 0;
        devc->opened = 0;
        spin_unlock_irqrestore(&devc->lock,flags);
}

static int v_midi_out (int dev, unsigned char midi_byte)
{
        vmidi_devc *devc = midi_devs[dev]->devc;
        vmidi_devc *pdevc;

        if (devc == NULL)
                return -ENXIO;

        pdevc = midi_devs[devc->pair_mididev]->devc;
        if (pdevc->input_opened > 0){
                if (MIDIbuf_avail(pdevc->my_mididev) > 500)
                        return 0;
                pdevc->midi_input_intr (pdevc->my_mididev, midi_byte);
        }
        return 1;
}

static inline int v_midi_start_read (int dev)
{
        return 0;
}

static int v_midi_end_read (int dev)
{
        vmidi_devc *devc = midi_devs[dev]->devc;
        if (devc == NULL)
                return -ENXIO;

        devc->intr_active = 0;
        return 0;
}

/* why -EPERM and not -EINVAL?? */

static inline int v_midi_ioctl (int dev, unsigned cmd, void __user *arg)
{
        return -EPERM;
}


#define MIDI_SYNTH_NAME "Loopback MIDI"
#define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT

#include "midi_synth.h"

static struct midi_operations v_midi_operations =
{
        .owner          = THIS_MODULE,
        .info           = {"Loopback MIDI Port 1", 0, 0, SNDCARD_VMIDI},
        .converter      = &std_midi_synth,
        .in_info        = {0},
        .open           = v_midi_open,
        .close          = v_midi_close,
        .ioctl          = v_midi_ioctl,
        .outputc        = v_midi_out,
        .start_read     = v_midi_start_read,
        .end_read       = v_midi_end_read,
};

static struct midi_operations v_midi_operations2 =
{
        .owner          = THIS_MODULE,
        .info           = {"Loopback MIDI Port 2", 0, 0, SNDCARD_VMIDI},
        .converter      = &std_midi_synth,
        .in_info        = {0},
        .open           = v_midi_open,
        .close          = v_midi_close,
        .ioctl          = v_midi_ioctl,
        .outputc        = v_midi_out,
        .start_read     = v_midi_start_read,
        .end_read       = v_midi_end_read,
};

/*
 *      We kmalloc just one of these - it makes life simpler and the code
 *      cleaner and the memory handling far more efficient
 */
 
struct vmidi_memory
{
        /* Must be first */
        struct midi_operations m_ops[2];
        struct synth_operations s_ops[2];
        struct vmidi_devc v_ops[2];
};

static void __init attach_v_midi (struct address_info *hw_config)
{
        struct vmidi_memory *m;
        /* printk("Attaching v_midi device.....\n"); */

        midi1 = sound_alloc_mididev();
        if (midi1 == -1)
        {
                printk(KERN_ERR "v_midi: Too many midi devices detected\n");
                return;
        }
        
        m = kmalloc(sizeof(struct vmidi_memory), GFP_KERNEL);
        if (m == NULL)
        {
                printk(KERN_WARNING "Loopback MIDI: Failed to allocate memory\n");
                sound_unload_mididev(midi1);
                return;
        }
        
        midi_mem = m;
        
        midi_devs[midi1] = &m->m_ops[0];
        

        midi2 = sound_alloc_mididev();
        if (midi2 == -1)
        {
                printk (KERN_ERR "v_midi: Too many midi devices detected\n");
                kfree(m);
                sound_unload_mididev(midi1);
                return;
        }

        midi_devs[midi2] = &m->m_ops[1];

        /* printk("VMIDI1: %d   VMIDI2: %d\n",midi1,midi2); */

        /* for MIDI-1 */
        v_devc[0] = &m->v_ops[0];
        memcpy ((char *) midi_devs[midi1], (char *) &v_midi_operations,
                sizeof (struct midi_operations));

        v_devc[0]->my_mididev = midi1;
        v_devc[0]->pair_mididev = midi2;
        v_devc[0]->opened = v_devc[0]->input_opened = 0;
        v_devc[0]->intr_active = 0;
        v_devc[0]->midi_input_intr = NULL;
        spin_lock_init(&v_devc[0]->lock);

        midi_devs[midi1]->devc = v_devc[0];

        midi_devs[midi1]->converter = &m->s_ops[0];
        std_midi_synth.midi_dev = midi1;
        memcpy ((char *) midi_devs[midi1]->converter, (char *) &std_midi_synth,
                sizeof (struct synth_operations));
        midi_devs[midi1]->converter->id = "V_MIDI 1";

        /* for MIDI-2 */
        v_devc[1] = &m->v_ops[1];

        memcpy ((char *) midi_devs[midi2], (char *) &v_midi_operations2,
                sizeof (struct midi_operations));

        v_devc[1]->my_mididev = midi2;
        v_devc[1]->pair_mididev = midi1;
        v_devc[1]->opened = v_devc[1]->input_opened = 0;
        v_devc[1]->intr_active = 0;
        v_devc[1]->midi_input_intr = NULL;
        spin_lock_init(&v_devc[1]->lock);

        midi_devs[midi2]->devc = v_devc[1];
        midi_devs[midi2]->converter = &m->s_ops[1];

        std_midi_synth.midi_dev = midi2;
        memcpy ((char *) midi_devs[midi2]->converter, (char *) &std_midi_synth,
                sizeof (struct synth_operations));
        midi_devs[midi2]->converter->id = "V_MIDI 2";

        sequencer_init();
        /* printk("Attached v_midi device\n"); */
}

static inline int __init probe_v_midi(struct address_info *hw_config)
{
        return(1);      /* always OK */
}


static void __exit unload_v_midi(struct address_info *hw_config)
{
        sound_unload_mididev(midi1);
        sound_unload_mididev(midi2);
        kfree(midi_mem);
}

static struct address_info cfg; /* dummy */

static int __init init_vmidi(void)
{
        printk("MIDI Loopback device driver\n");
        if (!probe_v_midi(&cfg))
                return -ENODEV;
        attach_v_midi(&cfg);

        return 0;
}

static void __exit cleanup_vmidi(void)
{
        unload_v_midi(&cfg);
}

module_init(init_vmidi);
module_exit(cleanup_vmidi);
MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */

[funini.com] -> [kei@sodan] -> Kernel Reading