Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
seq_oss_midi.c
Go to the documentation of this file.
1 /*
2  * OSS compatible sequencer driver
3  *
4  * MIDI device handlers
5  *
6  * Copyright (C) 1998,99 Takashi Iwai <[email protected]>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21  */
22 
23 #include <sound/asoundef.h>
24 #include "seq_oss_midi.h"
25 #include "seq_oss_readq.h"
26 #include "seq_oss_timer.h"
27 #include "seq_oss_event.h"
28 #include <sound/seq_midi_event.h>
29 #include "../seq_lock.h"
30 #include <linux/init.h>
31 #include <linux/slab.h>
32 
33 
34 /*
35  * constants
36  */
37 #define SNDRV_SEQ_OSS_MAX_MIDI_NAME 30
38 
39 /*
40  * definition of midi device record
41  */
42 struct seq_oss_midi {
43  int seq_device; /* device number */
44  int client; /* sequencer client number */
45  int port; /* sequencer port number */
46  unsigned int flags; /* port capability */
47  int opened; /* flag for opening */
49  struct snd_midi_event *coder; /* MIDI event coder */
50  struct seq_oss_devinfo *devinfo; /* assigned OSSseq device */
52 };
53 
54 
55 /*
56  * midi device table
57  */
58 static int max_midi_devs;
59 static struct seq_oss_midi *midi_devs[SNDRV_SEQ_OSS_MAX_MIDI_DEVS];
60 
61 static DEFINE_SPINLOCK(register_lock);
62 
63 /*
64  * prototypes
65  */
66 static struct seq_oss_midi *get_mdev(int dev);
67 static struct seq_oss_midi *get_mididev(struct seq_oss_devinfo *dp, int dev);
68 static int send_synth_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, int dev);
69 static int send_midi_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, struct seq_oss_midi *mdev);
70 
71 /*
72  * look up the existing ports
73  * this looks a very exhausting job.
74  */
75 int __init
77 {
78  struct snd_seq_client_info *clinfo;
79  struct snd_seq_port_info *pinfo;
80 
81  clinfo = kzalloc(sizeof(*clinfo), GFP_KERNEL);
82  pinfo = kzalloc(sizeof(*pinfo), GFP_KERNEL);
83  if (! clinfo || ! pinfo) {
84  kfree(clinfo);
85  kfree(pinfo);
86  return -ENOMEM;
87  }
88  clinfo->client = -1;
89  while (snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT, clinfo) == 0) {
90  if (clinfo->client == client)
91  continue; /* ignore myself */
92  pinfo->addr.client = clinfo->client;
93  pinfo->addr.port = -1;
96  }
97  kfree(clinfo);
98  kfree(pinfo);
99  return 0;
100 }
101 
102 
103 /*
104  */
105 static struct seq_oss_midi *
106 get_mdev(int dev)
107 {
108  struct seq_oss_midi *mdev;
109  unsigned long flags;
110 
111  spin_lock_irqsave(&register_lock, flags);
112  mdev = midi_devs[dev];
113  if (mdev)
114  snd_use_lock_use(&mdev->use_lock);
115  spin_unlock_irqrestore(&register_lock, flags);
116  return mdev;
117 }
118 
119 /*
120  * look for the identical slot
121  */
122 static struct seq_oss_midi *
123 find_slot(int client, int port)
124 {
125  int i;
126  struct seq_oss_midi *mdev;
127  unsigned long flags;
128 
129  spin_lock_irqsave(&register_lock, flags);
130  for (i = 0; i < max_midi_devs; i++) {
131  mdev = midi_devs[i];
132  if (mdev && mdev->client == client && mdev->port == port) {
133  /* found! */
134  snd_use_lock_use(&mdev->use_lock);
135  spin_unlock_irqrestore(&register_lock, flags);
136  return mdev;
137  }
138  }
139  spin_unlock_irqrestore(&register_lock, flags);
140  return NULL;
141 }
142 
143 
144 #define PERM_WRITE (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_SUBS_WRITE)
145 #define PERM_READ (SNDRV_SEQ_PORT_CAP_READ|SNDRV_SEQ_PORT_CAP_SUBS_READ)
146 /*
147  * register a new port if it doesn't exist yet
148  */
149 int
151 {
152  int i;
153  struct seq_oss_midi *mdev;
154  unsigned long flags;
155 
156  debug_printk(("check for MIDI client %d port %d\n", pinfo->addr.client, pinfo->addr.port));
157  /* the port must include generic midi */
158  if (! (pinfo->type & SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC))
159  return 0;
160  /* either read or write subscribable */
161  if ((pinfo->capability & PERM_WRITE) != PERM_WRITE &&
162  (pinfo->capability & PERM_READ) != PERM_READ)
163  return 0;
164 
165  /*
166  * look for the identical slot
167  */
168  if ((mdev = find_slot(pinfo->addr.client, pinfo->addr.port)) != NULL) {
169  /* already exists */
170  snd_use_lock_free(&mdev->use_lock);
171  return 0;
172  }
173 
174  /*
175  * allocate midi info record
176  */
177  if ((mdev = kzalloc(sizeof(*mdev), GFP_KERNEL)) == NULL) {
178  snd_printk(KERN_ERR "can't malloc midi info\n");
179  return -ENOMEM;
180  }
181 
182  /* copy the port information */
183  mdev->client = pinfo->addr.client;
184  mdev->port = pinfo->addr.port;
185  mdev->flags = pinfo->capability;
186  mdev->opened = 0;
187  snd_use_lock_init(&mdev->use_lock);
188 
189  /* copy and truncate the name of synth device */
190  strlcpy(mdev->name, pinfo->name, sizeof(mdev->name));
191 
192  /* create MIDI coder */
193  if (snd_midi_event_new(MAX_MIDI_EVENT_BUF, &mdev->coder) < 0) {
194  snd_printk(KERN_ERR "can't malloc midi coder\n");
195  kfree(mdev);
196  return -ENOMEM;
197  }
198  /* OSS sequencer adds running status to all sequences */
200 
201  /*
202  * look for en empty slot
203  */
204  spin_lock_irqsave(&register_lock, flags);
205  for (i = 0; i < max_midi_devs; i++) {
206  if (midi_devs[i] == NULL)
207  break;
208  }
209  if (i >= max_midi_devs) {
210  if (max_midi_devs >= SNDRV_SEQ_OSS_MAX_MIDI_DEVS) {
211  spin_unlock_irqrestore(&register_lock, flags);
212  snd_midi_event_free(mdev->coder);
213  kfree(mdev);
214  return -ENOMEM;
215  }
216  max_midi_devs++;
217  }
218  mdev->seq_device = i;
219  midi_devs[mdev->seq_device] = mdev;
220  spin_unlock_irqrestore(&register_lock, flags);
221 
222  return 0;
223 }
224 
225 /*
226  * release the midi device if it was registered
227  */
228 int
229 snd_seq_oss_midi_check_exit_port(int client, int port)
230 {
231  struct seq_oss_midi *mdev;
232  unsigned long flags;
233  int index;
234 
235  if ((mdev = find_slot(client, port)) != NULL) {
236  spin_lock_irqsave(&register_lock, flags);
237  midi_devs[mdev->seq_device] = NULL;
238  spin_unlock_irqrestore(&register_lock, flags);
239  snd_use_lock_free(&mdev->use_lock);
240  snd_use_lock_sync(&mdev->use_lock);
241  if (mdev->coder)
242  snd_midi_event_free(mdev->coder);
243  kfree(mdev);
244  }
245  spin_lock_irqsave(&register_lock, flags);
246  for (index = max_midi_devs - 1; index >= 0; index--) {
247  if (midi_devs[index])
248  break;
249  }
250  max_midi_devs = index + 1;
251  spin_unlock_irqrestore(&register_lock, flags);
252  return 0;
253 }
254 
255 
256 /*
257  * release the midi device if it was registered
258  */
259 void
261 {
262  int i;
263  struct seq_oss_midi *mdev;
264  unsigned long flags;
265 
266  spin_lock_irqsave(&register_lock, flags);
267  for (i = 0; i < max_midi_devs; i++) {
268  if ((mdev = midi_devs[i]) != NULL) {
269  if (mdev->coder)
270  snd_midi_event_free(mdev->coder);
271  kfree(mdev);
272  midi_devs[i] = NULL;
273  }
274  }
275  max_midi_devs = 0;
276  spin_unlock_irqrestore(&register_lock, flags);
277 }
278 
279 
280 /*
281  * set up midi tables
282  */
283 void
285 {
286  dp->max_mididev = max_midi_devs;
287 }
288 
289 /*
290  * clean up midi tables
291  */
292 void
294 {
295  int i;
296  for (i = 0; i < dp->max_mididev; i++)
297  snd_seq_oss_midi_close(dp, i);
298  dp->max_mididev = 0;
299 }
300 
301 
302 /*
303  * open all midi devices. ignore errors.
304  */
305 void
307 {
308  int i;
309  for (i = 0; i < dp->max_mididev; i++)
310  snd_seq_oss_midi_open(dp, i, file_mode);
311 }
312 
313 
314 /*
315  * get the midi device information
316  */
317 static struct seq_oss_midi *
318 get_mididev(struct seq_oss_devinfo *dp, int dev)
319 {
320  if (dev < 0 || dev >= dp->max_mididev)
321  return NULL;
322  return get_mdev(dev);
323 }
324 
325 
326 /*
327  * open the midi device if not opened yet
328  */
329 int
330 snd_seq_oss_midi_open(struct seq_oss_devinfo *dp, int dev, int fmode)
331 {
332  int perm;
333  struct seq_oss_midi *mdev;
334  struct snd_seq_port_subscribe subs;
335 
336  if ((mdev = get_mididev(dp, dev)) == NULL)
337  return -ENODEV;
338 
339  /* already used? */
340  if (mdev->opened && mdev->devinfo != dp) {
341  snd_use_lock_free(&mdev->use_lock);
342  return -EBUSY;
343  }
344 
345  perm = 0;
346  if (is_write_mode(fmode))
347  perm |= PERM_WRITE;
348  if (is_read_mode(fmode))
349  perm |= PERM_READ;
350  perm &= mdev->flags;
351  if (perm == 0) {
352  snd_use_lock_free(&mdev->use_lock);
353  return -ENXIO;
354  }
355 
356  /* already opened? */
357  if ((mdev->opened & perm) == perm) {
358  snd_use_lock_free(&mdev->use_lock);
359  return 0;
360  }
361 
362  perm &= ~mdev->opened;
363 
364  memset(&subs, 0, sizeof(subs));
365 
366  if (perm & PERM_WRITE) {
367  subs.sender = dp->addr;
368  subs.dest.client = mdev->client;
369  subs.dest.port = mdev->port;
371  mdev->opened |= PERM_WRITE;
372  }
373  if (perm & PERM_READ) {
374  subs.sender.client = mdev->client;
375  subs.sender.port = mdev->port;
376  subs.dest = dp->addr;
378  subs.queue = dp->queue; /* queue for timestamps */
380  mdev->opened |= PERM_READ;
381  }
382 
383  if (! mdev->opened) {
384  snd_use_lock_free(&mdev->use_lock);
385  return -ENXIO;
386  }
387 
388  mdev->devinfo = dp;
389  snd_use_lock_free(&mdev->use_lock);
390  return 0;
391 }
392 
393 /*
394  * close the midi device if already opened
395  */
396 int
398 {
399  struct seq_oss_midi *mdev;
400  struct snd_seq_port_subscribe subs;
401 
402  if ((mdev = get_mididev(dp, dev)) == NULL)
403  return -ENODEV;
404  if (! mdev->opened || mdev->devinfo != dp) {
405  snd_use_lock_free(&mdev->use_lock);
406  return 0;
407  }
408 
409  debug_printk(("closing client %d port %d mode %d\n", mdev->client, mdev->port, mdev->opened));
410  memset(&subs, 0, sizeof(subs));
411  if (mdev->opened & PERM_WRITE) {
412  subs.sender = dp->addr;
413  subs.dest.client = mdev->client;
414  subs.dest.port = mdev->port;
416  }
417  if (mdev->opened & PERM_READ) {
418  subs.sender.client = mdev->client;
419  subs.sender.port = mdev->port;
420  subs.dest = dp->addr;
422  }
423 
424  mdev->opened = 0;
425  mdev->devinfo = NULL;
426 
427  snd_use_lock_free(&mdev->use_lock);
428  return 0;
429 }
430 
431 /*
432  * change seq capability flags to file mode flags
433  */
434 int
436 {
437  struct seq_oss_midi *mdev;
438  int mode;
439 
440  if ((mdev = get_mididev(dp, dev)) == NULL)
441  return 0;
442 
443  mode = 0;
444  if (mdev->opened & PERM_WRITE)
445  mode |= SNDRV_SEQ_OSS_FILE_WRITE;
446  if (mdev->opened & PERM_READ)
447  mode |= SNDRV_SEQ_OSS_FILE_READ;
448 
449  snd_use_lock_free(&mdev->use_lock);
450  return mode;
451 }
452 
453 /*
454  * reset the midi device and close it:
455  * so far, only close the device.
456  */
457 void
459 {
460  struct seq_oss_midi *mdev;
461 
462  if ((mdev = get_mididev(dp, dev)) == NULL)
463  return;
464  if (! mdev->opened) {
465  snd_use_lock_free(&mdev->use_lock);
466  return;
467  }
468 
469  if (mdev->opened & PERM_WRITE) {
470  struct snd_seq_event ev;
471  int c;
472 
473  debug_printk(("resetting client %d port %d\n", mdev->client, mdev->port));
474  memset(&ev, 0, sizeof(ev));
475  ev.dest.client = mdev->client;
476  ev.dest.port = mdev->port;
477  ev.queue = dp->queue;
478  ev.source.port = dp->port;
479  if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_SYNTH) {
481  snd_seq_oss_dispatch(dp, &ev, 0, 0);
482  }
483  for (c = 0; c < 16; c++) {
485  ev.data.control.channel = c;
487  snd_seq_oss_dispatch(dp, &ev, 0, 0);
488  if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC) {
489  ev.data.control.param =
491  snd_seq_oss_dispatch(dp, &ev, 0, 0);
493  ev.data.control.value = 0;
494  snd_seq_oss_dispatch(dp, &ev, 0, 0);
495  }
496  }
497  }
498  // snd_seq_oss_midi_close(dp, dev);
499  snd_use_lock_free(&mdev->use_lock);
500 }
501 
502 
503 /*
504  * get client/port of the specified MIDI device
505  */
506 void
508 {
509  struct seq_oss_midi *mdev;
510 
511  if ((mdev = get_mididev(dp, dev)) == NULL)
512  return;
513  addr->client = mdev->client;
514  addr->port = mdev->port;
515  snd_use_lock_free(&mdev->use_lock);
516 }
517 
518 
519 /*
520  * input callback - this can be atomic
521  */
522 int
524 {
525  struct seq_oss_devinfo *dp = (struct seq_oss_devinfo *)private_data;
526  struct seq_oss_midi *mdev;
527  int rc;
528 
529  if (dp->readq == NULL)
530  return 0;
531  if ((mdev = find_slot(ev->source.client, ev->source.port)) == NULL)
532  return 0;
533  if (! (mdev->opened & PERM_READ)) {
534  snd_use_lock_free(&mdev->use_lock);
535  return 0;
536  }
537 
539  rc = send_synth_event(dp, ev, mdev->seq_device);
540  else
541  rc = send_midi_event(dp, ev, mdev);
542 
543  snd_use_lock_free(&mdev->use_lock);
544  return rc;
545 }
546 
547 /*
548  * convert ALSA sequencer event to OSS synth event
549  */
550 static int
551 send_synth_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, int dev)
552 {
553  union evrec ossev;
554 
555  memset(&ossev, 0, sizeof(ossev));
556 
557  switch (ev->type) {
559  ossev.v.cmd = MIDI_NOTEON; break;
561  ossev.v.cmd = MIDI_NOTEOFF; break;
563  ossev.v.cmd = MIDI_KEY_PRESSURE; break;
565  ossev.l.cmd = MIDI_CTL_CHANGE; break;
567  ossev.l.cmd = MIDI_PGM_CHANGE; break;
569  ossev.l.cmd = MIDI_CHN_PRESSURE; break;
571  ossev.l.cmd = MIDI_PITCH_BEND; break;
572  default:
573  return 0; /* not supported */
574  }
575 
576  ossev.v.dev = dev;
577 
578  switch (ev->type) {
582  ossev.v.code = EV_CHN_VOICE;
583  ossev.v.note = ev->data.note.note;
584  ossev.v.parm = ev->data.note.velocity;
585  ossev.v.chn = ev->data.note.channel;
586  break;
590  ossev.l.code = EV_CHN_COMMON;
591  ossev.l.p1 = ev->data.control.param;
592  ossev.l.val = ev->data.control.value;
593  ossev.l.chn = ev->data.control.channel;
594  break;
596  ossev.l.code = EV_CHN_COMMON;
597  ossev.l.val = ev->data.control.value + 8192;
598  ossev.l.chn = ev->data.control.channel;
599  break;
600  }
601 
603  snd_seq_oss_readq_put_event(dp->readq, &ossev);
604 
605  return 0;
606 }
607 
608 /*
609  * decode event and send MIDI bytes to read queue
610  */
611 static int
612 send_midi_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, struct seq_oss_midi *mdev)
613 {
614  char msg[32];
615  int len;
616 
618  if (!dp->timer->running)
619  len = snd_seq_oss_timer_start(dp->timer);
620  if (ev->type == SNDRV_SEQ_EVENT_SYSEX) {
623  ev->data.ext.ptr, ev->data.ext.len);
624  } else {
625  len = snd_midi_event_decode(mdev->coder, msg, sizeof(msg), ev);
626  if (len > 0)
627  snd_seq_oss_readq_puts(dp->readq, mdev->seq_device, msg, len);
628  }
629 
630  return 0;
631 }
632 
633 
634 /*
635  * dump midi data
636  * return 0 : enqueued
637  * non-zero : invalid - ignored
638  */
639 int
640 snd_seq_oss_midi_putc(struct seq_oss_devinfo *dp, int dev, unsigned char c, struct snd_seq_event *ev)
641 {
642  struct seq_oss_midi *mdev;
643 
644  if ((mdev = get_mididev(dp, dev)) == NULL)
645  return -ENODEV;
646  if (snd_midi_event_encode_byte(mdev->coder, c, ev) > 0) {
647  snd_seq_oss_fill_addr(dp, ev, mdev->client, mdev->port);
648  snd_use_lock_free(&mdev->use_lock);
649  return 0;
650  }
651  snd_use_lock_free(&mdev->use_lock);
652  return -EINVAL;
653 }
654 
655 /*
656  * create OSS compatible midi_info record
657  */
658 int
659 snd_seq_oss_midi_make_info(struct seq_oss_devinfo *dp, int dev, struct midi_info *inf)
660 {
661  struct seq_oss_midi *mdev;
662 
663  if ((mdev = get_mididev(dp, dev)) == NULL)
664  return -ENXIO;
665  inf->device = dev;
666  inf->dev_type = 0; /* FIXME: ?? */
667  inf->capabilities = 0; /* FIXME: ?? */
668  strlcpy(inf->name, mdev->name, sizeof(inf->name));
669  snd_use_lock_free(&mdev->use_lock);
670  return 0;
671 }
672 
673 
674 #ifdef CONFIG_PROC_FS
675 /*
676  * proc interface
677  */
678 static char *
679 capmode_str(int val)
680 {
681  val &= PERM_READ|PERM_WRITE;
682  if (val == (PERM_READ|PERM_WRITE))
683  return "read/write";
684  else if (val == PERM_READ)
685  return "read";
686  else if (val == PERM_WRITE)
687  return "write";
688  else
689  return "none";
690 }
691 
692 void
694 {
695  int i;
696  struct seq_oss_midi *mdev;
697 
698  snd_iprintf(buf, "\nNumber of MIDI devices: %d\n", max_midi_devs);
699  for (i = 0; i < max_midi_devs; i++) {
700  snd_iprintf(buf, "\nmidi %d: ", i);
701  mdev = get_mdev(i);
702  if (mdev == NULL) {
703  snd_iprintf(buf, "*empty*\n");
704  continue;
705  }
706  snd_iprintf(buf, "[%s] ALSA port %d:%d\n", mdev->name,
707  mdev->client, mdev->port);
708  snd_iprintf(buf, " capability %s / opened %s\n",
709  capmode_str(mdev->flags),
710  capmode_str(mdev->opened));
711  snd_use_lock_free(&mdev->use_lock);
712  }
713 }
714 #endif /* CONFIG_PROC_FS */