Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /*
  2  * sound/v_midi.c
  3  *
  4  * The low level driver for the Sound Blaster DS chips.
  5  *
  6  *
  7  * Copyright (C) by Hannu Savolainen 1993-1996
  8  *
  9  * USS/Lite 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  * Changes
 15  *      Alan Cox                Modularisation, changed memory allocations
 16  *      Christoph Hellwig       Adapted to module_init/module_exit
 17  *
 18  * Status
 19  *      Untested
 20  */
 21 
 22 #include <linux/init.h>
 23 #include <linux/module.h>
 24 #include <linux/spinlock.h>
 25 #include "sound_config.h"
 26 
 27 #include "v_midi.h"
 28 
 29 static vmidi_devc *v_devc[2] = { NULL, NULL};
 30 static int midi1,midi2;
 31 static void *midi_mem = NULL;
 32 
 33 /*
 34  * The DSP channel can be used either for input or output. Variable
 35  * 'sb_irq_mode' will be set when the program calls read or write first time
 36  * after open. Current version doesn't support mode changes without closing
 37  * and reopening the device. Support for this feature may be implemented in a
 38  * future version of this driver.
 39  */
 40 
 41 
 42 void            (*midi_input_intr) (int dev, unsigned char data);
 43 
 44 static int v_midi_open (int dev, int mode,
 45               void            (*input) (int dev, unsigned char data),
 46               void            (*output) (int dev)
 47 )
 48 {
 49         vmidi_devc *devc = midi_devs[dev]->devc;
 50         unsigned long flags;
 51 
 52         if (devc == NULL)
 53                 return -(ENXIO);
 54 
 55         spin_lock_irqsave(&devc->lock,flags);
 56         if (devc->opened)
 57         {
 58                 spin_unlock_irqrestore(&devc->lock,flags);
 59                 return -(EBUSY);
 60         }
 61         devc->opened = 1;
 62         spin_unlock_irqrestore(&devc->lock,flags);
 63 
 64         devc->intr_active = 1;
 65 
 66         if (mode & OPEN_READ)
 67         {
 68                 devc->input_opened = 1;
 69                 devc->midi_input_intr = input;
 70         }
 71 
 72         return 0;
 73 }
 74 
 75 static void v_midi_close (int dev)
 76 {
 77         vmidi_devc *devc = midi_devs[dev]->devc;
 78         unsigned long flags;
 79 
 80         if (devc == NULL)
 81                 return;
 82 
 83         spin_lock_irqsave(&devc->lock,flags);
 84         devc->intr_active = 0;
 85         devc->input_opened = 0;
 86         devc->opened = 0;
 87         spin_unlock_irqrestore(&devc->lock,flags);
 88 }
 89 
 90 static int v_midi_out (int dev, unsigned char midi_byte)
 91 {
 92         vmidi_devc *devc = midi_devs[dev]->devc;
 93         vmidi_devc *pdevc;
 94 
 95         if (devc == NULL)
 96                 return -ENXIO;
 97 
 98         pdevc = midi_devs[devc->pair_mididev]->devc;
 99         if (pdevc->input_opened > 0){
100                 if (MIDIbuf_avail(pdevc->my_mididev) > 500)
101                         return 0;
102                 pdevc->midi_input_intr (pdevc->my_mididev, midi_byte);
103         }
104         return 1;
105 }
106 
107 static inline int v_midi_start_read (int dev)
108 {
109         return 0;
110 }
111 
112 static int v_midi_end_read (int dev)
113 {
114         vmidi_devc *devc = midi_devs[dev]->devc;
115         if (devc == NULL)
116                 return -ENXIO;
117 
118         devc->intr_active = 0;
119         return 0;
120 }
121 
122 /* why -EPERM and not -EINVAL?? */
123 
124 static inline int v_midi_ioctl (int dev, unsigned cmd, void __user *arg)
125 {
126         return -EPERM;
127 }
128 
129 
130 #define MIDI_SYNTH_NAME "Loopback MIDI"
131 #define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT
132 
133 #include "midi_synth.h"
134 
135 static struct midi_operations v_midi_operations =
136 {
137         .owner          = THIS_MODULE,
138         .info           = {"Loopback MIDI Port 1", 0, 0, SNDCARD_VMIDI},
139         .converter      = &std_midi_synth,
140         .in_info        = {0},
141         .open           = v_midi_open,
142         .close          = v_midi_close,
143         .ioctl          = v_midi_ioctl,
144         .outputc        = v_midi_out,
145         .start_read     = v_midi_start_read,
146         .end_read       = v_midi_end_read,
147 };
148 
149 static struct midi_operations v_midi_operations2 =
150 {
151         .owner          = THIS_MODULE,
152         .info           = {"Loopback MIDI Port 2", 0, 0, SNDCARD_VMIDI},
153         .converter      = &std_midi_synth,
154         .in_info        = {0},
155         .open           = v_midi_open,
156         .close          = v_midi_close,
157         .ioctl          = v_midi_ioctl,
158         .outputc        = v_midi_out,
159         .start_read     = v_midi_start_read,
160         .end_read       = v_midi_end_read,
161 };
162 
163 /*
164  *      We kmalloc just one of these - it makes life simpler and the code
165  *      cleaner and the memory handling far more efficient
166  */
167  
168 struct vmidi_memory
169 {
170         /* Must be first */
171         struct midi_operations m_ops[2];
172         struct synth_operations s_ops[2];
173         struct vmidi_devc v_ops[2];
174 };
175 
176 static void __init attach_v_midi (struct address_info *hw_config)
177 {
178         struct vmidi_memory *m;
179         /* printk("Attaching v_midi device.....\n"); */
180 
181         midi1 = sound_alloc_mididev();
182         if (midi1 == -1)
183         {
184                 printk(KERN_ERR "v_midi: Too many midi devices detected\n");
185                 return;
186         }
187         
188         m=(struct vmidi_memory *)kmalloc(sizeof(struct vmidi_memory), GFP_KERNEL);
189         if (m == NULL)
190         {
191                 printk(KERN_WARNING "Loopback MIDI: Failed to allocate memory\n");
192                 sound_unload_mididev(midi1);
193                 return;
194         }
195         
196         midi_mem = m;
197         
198         midi_devs[midi1] = &m->m_ops[0];
199         
200 
201         midi2 = sound_alloc_mididev();
202         if (midi2 == -1)
203         {
204                 printk (KERN_ERR "v_midi: Too many midi devices detected\n");
205                 kfree(m);
206                 sound_unload_mididev(midi1);
207                 return;
208         }
209 
210         midi_devs[midi2] = &m->m_ops[1];
211 
212         /* printk("VMIDI1: %d   VMIDI2: %d\n",midi1,midi2); */
213 
214         /* for MIDI-1 */
215         v_devc[0] = &m->v_ops[0];
216         memcpy ((char *) midi_devs[midi1], (char *) &v_midi_operations,
217                 sizeof (struct midi_operations));
218 
219         v_devc[0]->my_mididev = midi1;
220         v_devc[0]->pair_mididev = midi2;
221         v_devc[0]->opened = v_devc[0]->input_opened = 0;
222         v_devc[0]->intr_active = 0;
223         v_devc[0]->midi_input_intr = NULL;
224         spin_lock_init(&v_devc[0]->lock);
225 
226         midi_devs[midi1]->devc = v_devc[0];
227 
228         midi_devs[midi1]->converter = &m->s_ops[0];
229         std_midi_synth.midi_dev = midi1;
230         memcpy ((char *) midi_devs[midi1]->converter, (char *) &std_midi_synth,
231                 sizeof (struct synth_operations));
232         midi_devs[midi1]->converter->id = "V_MIDI 1";
233 
234         /* for MIDI-2 */
235         v_devc[1] = &m->v_ops[1];
236 
237         memcpy ((char *) midi_devs[midi2], (char *) &v_midi_operations2,
238                 sizeof (struct midi_operations));
239 
240         v_devc[1]->my_mididev = midi2;
241         v_devc[1]->pair_mididev = midi1;
242         v_devc[1]->opened = v_devc[1]->input_opened = 0;
243         v_devc[1]->intr_active = 0;
244         v_devc[1]->midi_input_intr = NULL;
245         spin_lock_init(&v_devc[1]->lock);
246 
247         midi_devs[midi2]->devc = v_devc[1];
248         midi_devs[midi2]->converter = &m->s_ops[1];
249 
250         std_midi_synth.midi_dev = midi2;
251         memcpy ((char *) midi_devs[midi2]->converter, (char *) &std_midi_synth,
252                 sizeof (struct synth_operations));
253         midi_devs[midi2]->converter->id = "V_MIDI 2";
254 
255         sequencer_init();
256         /* printk("Attached v_midi device\n"); */
257 }
258 
259 static inline int __init probe_v_midi(struct address_info *hw_config)
260 {
261         return(1);      /* always OK */
262 }
263 
264 
265 static void __exit unload_v_midi(struct address_info *hw_config)
266 {
267         sound_unload_mididev(midi1);
268         sound_unload_mididev(midi2);
269         kfree(midi_mem);
270 }
271 
272 static struct address_info cfg; /* dummy */
273 
274 static int __init init_vmidi(void)
275 {
276         printk("MIDI Loopback device driver\n");
277         if (!probe_v_midi(&cfg))
278                 return -ENODEV;
279         attach_v_midi(&cfg);
280 
281         return 0;
282 }
283 
284 static void __exit cleanup_vmidi(void)
285 {
286         unload_v_midi(&cfg);
287 }
288 
289 module_init(init_vmidi);
290 module_exit(cleanup_vmidi);
291 MODULE_LICENSE("GPL");
292 
  This page was automatically generated by the LXR engine.