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/oss/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 static int v_midi_open (int dev, int mode,
 43               void            (*input) (int dev, unsigned char data),
 44               void            (*output) (int dev)
 45 )
 46 {
 47         vmidi_devc *devc = midi_devs[dev]->devc;
 48         unsigned long flags;
 49 
 50         if (devc == NULL)
 51                 return -(ENXIO);
 52 
 53         spin_lock_irqsave(&devc->lock,flags);
 54         if (devc->opened)
 55         {
 56                 spin_unlock_irqrestore(&devc->lock,flags);
 57                 return -(EBUSY);
 58         }
 59         devc->opened = 1;
 60         spin_unlock_irqrestore(&devc->lock,flags);
 61 
 62         devc->intr_active = 1;
 63 
 64         if (mode & OPEN_READ)
 65         {
 66                 devc->input_opened = 1;
 67                 devc->midi_input_intr = input;
 68         }
 69 
 70         return 0;
 71 }
 72 
 73 static void v_midi_close (int dev)
 74 {
 75         vmidi_devc *devc = midi_devs[dev]->devc;
 76         unsigned long flags;
 77 
 78         if (devc == NULL)
 79                 return;
 80 
 81         spin_lock_irqsave(&devc->lock,flags);
 82         devc->intr_active = 0;
 83         devc->input_opened = 0;
 84         devc->opened = 0;
 85         spin_unlock_irqrestore(&devc->lock,flags);
 86 }
 87 
 88 static int v_midi_out (int dev, unsigned char midi_byte)
 89 {
 90         vmidi_devc *devc = midi_devs[dev]->devc;
 91         vmidi_devc *pdevc;
 92 
 93         if (devc == NULL)
 94                 return -ENXIO;
 95 
 96         pdevc = midi_devs[devc->pair_mididev]->devc;
 97         if (pdevc->input_opened > 0){
 98                 if (MIDIbuf_avail(pdevc->my_mididev) > 500)
 99                         return 0;
100                 pdevc->midi_input_intr (pdevc->my_mididev, midi_byte);
101         }
102         return 1;
103 }
104 
105 static inline int v_midi_start_read (int dev)
106 {
107         return 0;
108 }
109 
110 static int v_midi_end_read (int dev)
111 {
112         vmidi_devc *devc = midi_devs[dev]->devc;
113         if (devc == NULL)
114                 return -ENXIO;
115 
116         devc->intr_active = 0;
117         return 0;
118 }
119 
120 /* why -EPERM and not -EINVAL?? */
121 
122 static inline int v_midi_ioctl (int dev, unsigned cmd, void __user *arg)
123 {
124         return -EPERM;
125 }
126 
127 
128 #define MIDI_SYNTH_NAME "Loopback MIDI"
129 #define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT
130 
131 #include "midi_synth.h"
132 
133 static struct midi_operations v_midi_operations =
134 {
135         .owner          = THIS_MODULE,
136         .info           = {"Loopback MIDI Port 1", 0, 0, SNDCARD_VMIDI},
137         .converter      = &std_midi_synth,
138         .in_info        = {0},
139         .open           = v_midi_open,
140         .close          = v_midi_close,
141         .ioctl          = v_midi_ioctl,
142         .outputc        = v_midi_out,
143         .start_read     = v_midi_start_read,
144         .end_read       = v_midi_end_read,
145 };
146 
147 static struct midi_operations v_midi_operations2 =
148 {
149         .owner          = THIS_MODULE,
150         .info           = {"Loopback MIDI Port 2", 0, 0, SNDCARD_VMIDI},
151         .converter      = &std_midi_synth,
152         .in_info        = {0},
153         .open           = v_midi_open,
154         .close          = v_midi_close,
155         .ioctl          = v_midi_ioctl,
156         .outputc        = v_midi_out,
157         .start_read     = v_midi_start_read,
158         .end_read       = v_midi_end_read,
159 };
160 
161 /*
162  *      We kmalloc just one of these - it makes life simpler and the code
163  *      cleaner and the memory handling far more efficient
164  */
165  
166 struct vmidi_memory
167 {
168         /* Must be first */
169         struct midi_operations m_ops[2];
170         struct synth_operations s_ops[2];
171         struct vmidi_devc v_ops[2];
172 };
173 
174 static void __init attach_v_midi (struct address_info *hw_config)
175 {
176         struct vmidi_memory *m;
177         /* printk("Attaching v_midi device.....\n"); */
178 
179         midi1 = sound_alloc_mididev();
180         if (midi1 == -1)
181         {
182                 printk(KERN_ERR "v_midi: Too many midi devices detected\n");
183                 return;
184         }
185         
186         m = kmalloc(sizeof(struct vmidi_memory), GFP_KERNEL);
187         if (m == NULL)
188         {
189                 printk(KERN_WARNING "Loopback MIDI: Failed to allocate memory\n");
190                 sound_unload_mididev(midi1);
191                 return;
192         }
193         
194         midi_mem = m;
195         
196         midi_devs[midi1] = &m->m_ops[0];
197         
198 
199         midi2 = sound_alloc_mididev();
200         if (midi2 == -1)
201         {
202                 printk (KERN_ERR "v_midi: Too many midi devices detected\n");
203                 kfree(m);
204                 sound_unload_mididev(midi1);
205                 return;
206         }
207 
208         midi_devs[midi2] = &m->m_ops[1];
209 
210         /* printk("VMIDI1: %d   VMIDI2: %d\n",midi1,midi2); */
211 
212         /* for MIDI-1 */
213         v_devc[0] = &m->v_ops[0];
214         memcpy ((char *) midi_devs[midi1], (char *) &v_midi_operations,
215                 sizeof (struct midi_operations));
216 
217         v_devc[0]->my_mididev = midi1;
218         v_devc[0]->pair_mididev = midi2;
219         v_devc[0]->opened = v_devc[0]->input_opened = 0;
220         v_devc[0]->intr_active = 0;
221         v_devc[0]->midi_input_intr = NULL;
222         spin_lock_init(&v_devc[0]->lock);
223 
224         midi_devs[midi1]->devc = v_devc[0];
225 
226         midi_devs[midi1]->converter = &m->s_ops[0];
227         std_midi_synth.midi_dev = midi1;
228         memcpy ((char *) midi_devs[midi1]->converter, (char *) &std_midi_synth,
229                 sizeof (struct synth_operations));
230         midi_devs[midi1]->converter->id = "V_MIDI 1";
231 
232         /* for MIDI-2 */
233         v_devc[1] = &m->v_ops[1];
234 
235         memcpy ((char *) midi_devs[midi2], (char *) &v_midi_operations2,
236                 sizeof (struct midi_operations));
237 
238         v_devc[1]->my_mididev = midi2;
239         v_devc[1]->pair_mididev = midi1;
240         v_devc[1]->opened = v_devc[1]->input_opened = 0;
241         v_devc[1]->intr_active = 0;
242         v_devc[1]->midi_input_intr = NULL;
243         spin_lock_init(&v_devc[1]->lock);
244 
245         midi_devs[midi2]->devc = v_devc[1];
246         midi_devs[midi2]->converter = &m->s_ops[1];
247 
248         std_midi_synth.midi_dev = midi2;
249         memcpy ((char *) midi_devs[midi2]->converter, (char *) &std_midi_synth,
250                 sizeof (struct synth_operations));
251         midi_devs[midi2]->converter->id = "V_MIDI 2";
252 
253         sequencer_init();
254         /* printk("Attached v_midi device\n"); */
255 }
256 
257 static inline int __init probe_v_midi(struct address_info *hw_config)
258 {
259         return(1);      /* always OK */
260 }
261 
262 
263 static void __exit unload_v_midi(struct address_info *hw_config)
264 {
265         sound_unload_mididev(midi1);
266         sound_unload_mididev(midi2);
267         kfree(midi_mem);
268 }
269 
270 static struct address_info cfg; /* dummy */
271 
272 static int __init init_vmidi(void)
273 {
274         printk("MIDI Loopback device driver\n");
275         if (!probe_v_midi(&cfg))
276                 return -ENODEV;
277         attach_v_midi(&cfg);
278 
279         return 0;
280 }
281 
282 static void __exit cleanup_vmidi(void)
283 {
284         unload_v_midi(&cfg);
285 }
286 
287 module_init(init_vmidi);
288 module_exit(cleanup_vmidi);
289 MODULE_LICENSE("GPL");
290 
  This page was automatically generated by the LXR engine.