~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/oss/v_midi.c

Version: ~ [ linux-5.9-rc6 ] ~ [ linux-5.8.10 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.66 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.146 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.198 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.236 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.236 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp