v_midi.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:6k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

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