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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * sound/midibuf.c
  3.  *
  4.  * Device file manager for /dev/midi#
  5.  */
  6. /*
  7.  * Copyright (C) by Hannu Savolainen 1993-1997
  8.  *
  9.  * OSS/Free 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.  * Thomas Sailer   : ioctl code reworked (vmalloc/vfree removed)
  15.  */
  16. #include <linux/stddef.h>
  17. #include <linux/kmod.h>
  18. #define MIDIBUF_C
  19. #include "sound_config.h"
  20. /*
  21.  * Don't make MAX_QUEUE_SIZE larger than 4000
  22.  */
  23. #define MAX_QUEUE_SIZE 4000
  24. static wait_queue_head_t midi_sleeper[MAX_MIDI_DEV];
  25. static wait_queue_head_t input_sleeper[MAX_MIDI_DEV];
  26. struct midi_buf
  27. {
  28. int len, head, tail;
  29. unsigned char queue[MAX_QUEUE_SIZE];
  30. };
  31. struct midi_parms
  32. {
  33. long prech_timeout; /*
  34.  * Timeout before the first ch
  35.  */
  36. };
  37. static struct midi_buf *midi_out_buf[MAX_MIDI_DEV] = {NULL};
  38. static struct midi_buf *midi_in_buf[MAX_MIDI_DEV] = {NULL};
  39. static struct midi_parms parms[MAX_MIDI_DEV];
  40. static void midi_poll(unsigned long dummy);
  41. static struct timer_list poll_timer = {
  42. function: midi_poll
  43. };
  44. static volatile int open_devs = 0;
  45. #define DATA_AVAIL(q) (q->len)
  46. #define SPACE_AVAIL(q) (MAX_QUEUE_SIZE - q->len)
  47. #define QUEUE_BYTE(q, data) 
  48. if (SPACE_AVAIL(q)) 
  49.   unsigned long flags; 
  50.   save_flags( flags);cli(); 
  51.   q->queue[q->tail] = (data); 
  52.   q->len++; q->tail = (q->tail+1) % MAX_QUEUE_SIZE; 
  53.   restore_flags(flags); 
  54. }
  55. #define REMOVE_BYTE(q, data) 
  56. if (DATA_AVAIL(q)) 
  57.   unsigned long flags; 
  58.   save_flags( flags);cli(); 
  59.   data = q->queue[q->head]; 
  60.   q->len--; q->head = (q->head+1) % MAX_QUEUE_SIZE; 
  61.   restore_flags(flags); 
  62. }
  63. static void drain_midi_queue(int dev)
  64. {
  65. /*
  66.  * Give the Midi driver time to drain its output queues
  67.  */
  68. if (midi_devs[dev]->buffer_status != NULL)
  69. while (!signal_pending(current) && midi_devs[dev]->buffer_status(dev)) 
  70. interruptible_sleep_on_timeout(&midi_sleeper[dev],
  71.        HZ/10);
  72. }
  73. static void midi_input_intr(int dev, unsigned char data)
  74. {
  75. if (midi_in_buf[dev] == NULL)
  76. return;
  77. if (data == 0xfe) /*
  78.  * Active sensing
  79.  */
  80. return; /*
  81.  * Ignore
  82.  */
  83. if (SPACE_AVAIL(midi_in_buf[dev])) {
  84. QUEUE_BYTE(midi_in_buf[dev], data);
  85. wake_up(&input_sleeper[dev]);
  86. }
  87. }
  88. static void midi_output_intr(int dev)
  89. {
  90. /*
  91.  * Currently NOP
  92.  */
  93. }
  94. static void midi_poll(unsigned long dummy)
  95. {
  96. unsigned long   flags;
  97. int             dev;
  98. save_flags(flags);
  99. cli();
  100. if (open_devs)
  101. {
  102. for (dev = 0; dev < num_midis; dev++)
  103. if (midi_devs[dev] != NULL && midi_out_buf[dev] != NULL)
  104. {
  105. int ok = 1;
  106. while (DATA_AVAIL(midi_out_buf[dev]) && ok)
  107. {
  108. int c = midi_out_buf[dev]->queue[midi_out_buf[dev]->head];
  109. restore_flags(flags); /* Give some time to others */
  110. ok = midi_devs[dev]->outputc(dev, c);
  111. cli();
  112. midi_out_buf[dev]->head = (midi_out_buf[dev]->head + 1) % MAX_QUEUE_SIZE;
  113. midi_out_buf[dev]->len--;
  114. }
  115. if (DATA_AVAIL(midi_out_buf[dev]) < 100)
  116. wake_up(&midi_sleeper[dev]);
  117. }
  118. poll_timer.expires = (1) + jiffies;
  119. add_timer(&poll_timer);
  120. /*
  121.  * Come back later
  122.  */
  123. }
  124. restore_flags(flags);
  125. }
  126. int MIDIbuf_open(int dev, struct file *file)
  127. {
  128. int mode, err;
  129. dev = dev >> 4;
  130. mode = translate_mode(file);
  131. if (num_midis > MAX_MIDI_DEV)
  132. {
  133. printk(KERN_ERR "midi: Too many midi interfacesn");
  134. num_midis = MAX_MIDI_DEV;
  135. }
  136. if (dev < 0 || dev >= num_midis || midi_devs[dev] == NULL)
  137.   return -ENXIO;
  138. /*
  139.  *    Interrupts disabled. Be careful
  140.  */
  141. if (midi_devs[dev]->owner)
  142. __MOD_INC_USE_COUNT (midi_devs[dev]->owner);
  143. if ((err = midi_devs[dev]->open(dev, mode,
  144.  midi_input_intr, midi_output_intr)) < 0)
  145. return err;
  146. parms[dev].prech_timeout = MAX_SCHEDULE_TIMEOUT;
  147. midi_in_buf[dev] = (struct midi_buf *) vmalloc(sizeof(struct midi_buf));
  148. if (midi_in_buf[dev] == NULL)
  149. {
  150. printk(KERN_WARNING "midi: Can't allocate buffern");
  151. midi_devs[dev]->close(dev);
  152. return -EIO;
  153. }
  154. midi_in_buf[dev]->len = midi_in_buf[dev]->head = midi_in_buf[dev]->tail = 0;
  155. midi_out_buf[dev] = (struct midi_buf *) vmalloc(sizeof(struct midi_buf));
  156. if (midi_out_buf[dev] == NULL)
  157. {
  158. printk(KERN_WARNING "midi: Can't allocate buffern");
  159. midi_devs[dev]->close(dev);
  160. vfree(midi_in_buf[dev]);
  161. midi_in_buf[dev] = NULL;
  162. return -EIO;
  163. }
  164. midi_out_buf[dev]->len = midi_out_buf[dev]->head = midi_out_buf[dev]->tail = 0;
  165. open_devs++;
  166. init_waitqueue_head(&midi_sleeper[dev]);
  167. init_waitqueue_head(&input_sleeper[dev]);
  168. if (open_devs < 2) /* This was first open */
  169. {
  170. poll_timer.expires = 1 + jiffies;
  171. add_timer(&poll_timer); /* Start polling */
  172. }
  173. return err;
  174. }
  175. void MIDIbuf_release(int dev, struct file *file)
  176. {
  177. int mode;
  178. unsigned long flags;
  179. dev = dev >> 4;
  180. mode = translate_mode(file);
  181. if (dev < 0 || dev >= num_midis || midi_devs[dev] == NULL)
  182. return;
  183. save_flags(flags);
  184. cli();
  185. /*
  186.  * Wait until the queue is empty
  187.  */
  188. if (mode != OPEN_READ)
  189. {
  190. midi_devs[dev]->outputc(dev, 0xfe); /*
  191.    * Active sensing to shut the
  192.    * devices
  193.  */
  194. while (!signal_pending(current) && DATA_AVAIL(midi_out_buf[dev]))
  195.   interruptible_sleep_on(&midi_sleeper[dev]);
  196. /*
  197.  * Sync
  198.  */
  199. drain_midi_queue(dev); /*
  200.  * Ensure the output queues are empty
  201.  */
  202. }
  203. restore_flags(flags);
  204. midi_devs[dev]->close(dev);
  205. open_devs--;
  206. if (open_devs == 0)
  207. del_timer_sync(&poll_timer);
  208. vfree(midi_in_buf[dev]);
  209. vfree(midi_out_buf[dev]);
  210. midi_in_buf[dev] = NULL;
  211. midi_out_buf[dev] = NULL;
  212. if (midi_devs[dev]->owner)
  213. __MOD_DEC_USE_COUNT (midi_devs[dev]->owner);
  214. }
  215. int MIDIbuf_write(int dev, struct file *file, const char *buf, int count)
  216. {
  217. unsigned long flags;
  218. int c, n, i;
  219. unsigned char tmp_data;
  220. dev = dev >> 4;
  221. if (!count)
  222. return 0;
  223. save_flags(flags);
  224. cli();
  225. c = 0;
  226. while (c < count)
  227. {
  228. n = SPACE_AVAIL(midi_out_buf[dev]);
  229. if (n == 0) { /*
  230.  * No space just now.
  231.  */
  232. if (file->f_flags & O_NONBLOCK) {
  233. restore_flags(flags);
  234. return -EAGAIN;
  235. }
  236. interruptible_sleep_on(&midi_sleeper[dev]);
  237. if (signal_pending(current)) 
  238. {
  239. restore_flags(flags);
  240. return -EINTR;
  241. }
  242. n = SPACE_AVAIL(midi_out_buf[dev]);
  243. }
  244. if (n > (count - c))
  245. n = count - c;
  246. for (i = 0; i < n; i++)
  247. {
  248. /* BROKE BROKE BROKE - CANT DO THIS WITH CLI !! */
  249. copy_from_user((char *) &tmp_data, &(buf)[c], 1);
  250. QUEUE_BYTE(midi_out_buf[dev], tmp_data);
  251. c++;
  252. }
  253. }
  254. restore_flags(flags);
  255. return c;
  256. }
  257. int MIDIbuf_read(int dev, struct file *file, char *buf, int count)
  258. {
  259. int n, c = 0;
  260. unsigned long flags;
  261. unsigned char tmp_data;
  262. dev = dev >> 4;
  263. save_flags(flags);
  264. cli();
  265. if (!DATA_AVAIL(midi_in_buf[dev])) { /*
  266.  * No data yet, wait
  267.  */
  268.   if (file->f_flags & O_NONBLOCK) {
  269.   restore_flags(flags);
  270.   return -EAGAIN;
  271.   }
  272. interruptible_sleep_on_timeout(&input_sleeper[dev],
  273.        parms[dev].prech_timeout);
  274. if (signal_pending(current))
  275. c = -EINTR; /* The user is getting restless */
  276. }
  277. if (c == 0 && DATA_AVAIL(midi_in_buf[dev])) /*
  278.  * Got some bytes
  279.  */
  280. {
  281. n = DATA_AVAIL(midi_in_buf[dev]);
  282. if (n > count)
  283. n = count;
  284. c = 0;
  285. while (c < n)
  286. {
  287. char *fixit;
  288. REMOVE_BYTE(midi_in_buf[dev], tmp_data);
  289. fixit = (char *) &tmp_data;
  290. /* BROKE BROKE BROKE */
  291. copy_to_user(&(buf)[c], fixit, 1);
  292. c++;
  293. }
  294. }
  295. restore_flags(flags);
  296. return c;
  297. }
  298. int MIDIbuf_ioctl(int dev, struct file *file,
  299.   unsigned int cmd, caddr_t arg)
  300. {
  301. int val;
  302. dev = dev >> 4;
  303. if (((cmd >> 8) & 0xff) == 'C') 
  304. {
  305. if (midi_devs[dev]->coproc) /* Coprocessor ioctl */
  306. return midi_devs[dev]->coproc->ioctl(midi_devs[dev]->coproc->devc, cmd, arg, 0);
  307. /* printk("/dev/midi%d: No coprocessor for this devicen", dev);*/
  308. return -ENXIO;
  309. }
  310. else
  311. {
  312. switch (cmd) 
  313. {
  314. case SNDCTL_MIDI_PRETIME:
  315. if (get_user(val, (int *)arg))
  316. return -EFAULT;
  317. if (val < 0)
  318. val = 0;
  319. val = (HZ * val) / 10;
  320. parms[dev].prech_timeout = val;
  321. return put_user(val, (int *)arg);
  322. default:
  323. if (!midi_devs[dev]->ioctl)
  324. return -EINVAL;
  325. return midi_devs[dev]->ioctl(dev, cmd, arg);
  326. }
  327. }
  328. }
  329. /* No kernel lock - fine */
  330. unsigned int MIDIbuf_poll(int dev, struct file *file, poll_table * wait)
  331. {
  332. unsigned int mask = 0;
  333. dev = dev >> 4;
  334. /* input */
  335. poll_wait(file, &input_sleeper[dev], wait);
  336. if (DATA_AVAIL(midi_in_buf[dev]))
  337. mask |= POLLIN | POLLRDNORM;
  338. /* output */
  339. poll_wait(file, &midi_sleeper[dev], wait);
  340. if (!SPACE_AVAIL(midi_out_buf[dev]))
  341. mask |= POLLOUT | POLLWRNORM;
  342. return mask;
  343. }
  344. void MIDIbuf_init(void)
  345. {
  346. /* drag in midi_syms.o */
  347. {
  348. extern char midi_syms_symbol;
  349. midi_syms_symbol = 0;
  350. }
  351. }
  352. int MIDIbuf_avail(int dev)
  353. {
  354.         if (midi_in_buf[dev])
  355. return DATA_AVAIL (midi_in_buf[dev]);
  356. return 0;
  357. }