linux/sound/firewire/tascam/tascam-midi.c
<<
>>
Prefs
   1/*
   2 * tascam-midi.c - a part of driver for TASCAM FireWire series
   3 *
   4 * Copyright (c) 2015 Takashi Sakamoto
   5 *
   6 * Licensed under the terms of the GNU General Public License, version 2.
   7 */
   8
   9#include "tascam.h"
  10
  11static int midi_capture_open(struct snd_rawmidi_substream *substream)
  12{
  13        /* Do nothing. */
  14        return 0;
  15}
  16
  17static int midi_playback_open(struct snd_rawmidi_substream *substream)
  18{
  19        struct snd_tscm *tscm = substream->rmidi->private_data;
  20
  21        snd_fw_async_midi_port_init(&tscm->out_ports[substream->number]);
  22
  23        return 0;
  24}
  25
  26static int midi_capture_close(struct snd_rawmidi_substream *substream)
  27{
  28        /* Do nothing. */
  29        return 0;
  30}
  31
  32static int midi_playback_close(struct snd_rawmidi_substream *substream)
  33{
  34        return 0;
  35}
  36
  37static void midi_playback_drain(struct snd_rawmidi_substream *substream)
  38{
  39        struct snd_tscm *tscm = substream->rmidi->private_data;
  40
  41        snd_fw_async_midi_port_finish(&tscm->out_ports[substream->number]);
  42}
  43
  44static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up)
  45{
  46        struct snd_tscm *tscm = substrm->rmidi->private_data;
  47        unsigned long flags;
  48
  49        spin_lock_irqsave(&tscm->lock, flags);
  50
  51        if (up)
  52                tscm->tx_midi_substreams[substrm->number] = substrm;
  53        else
  54                tscm->tx_midi_substreams[substrm->number] = NULL;
  55
  56        spin_unlock_irqrestore(&tscm->lock, flags);
  57}
  58
  59static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)
  60{
  61        struct snd_tscm *tscm = substrm->rmidi->private_data;
  62        unsigned long flags;
  63
  64        spin_lock_irqsave(&tscm->lock, flags);
  65
  66        if (up)
  67                snd_fw_async_midi_port_run(&tscm->out_ports[substrm->number],
  68                                           substrm);
  69
  70        spin_unlock_irqrestore(&tscm->lock, flags);
  71}
  72
  73int snd_tscm_create_midi_devices(struct snd_tscm *tscm)
  74{
  75        static const struct snd_rawmidi_ops capture_ops = {
  76                .open           = midi_capture_open,
  77                .close          = midi_capture_close,
  78                .trigger        = midi_capture_trigger,
  79        };
  80        static const struct snd_rawmidi_ops playback_ops = {
  81                .open           = midi_playback_open,
  82                .close          = midi_playback_close,
  83                .drain          = midi_playback_drain,
  84                .trigger        = midi_playback_trigger,
  85        };
  86        struct snd_rawmidi *rmidi;
  87        struct snd_rawmidi_str *stream;
  88        struct snd_rawmidi_substream *subs;
  89        int err;
  90
  91        err = snd_rawmidi_new(tscm->card, tscm->card->driver, 0,
  92                              tscm->spec->midi_playback_ports,
  93                              tscm->spec->midi_capture_ports,
  94                              &rmidi);
  95        if (err < 0)
  96                return err;
  97
  98        snprintf(rmidi->name, sizeof(rmidi->name),
  99                 "%s MIDI", tscm->card->shortname);
 100        rmidi->private_data = tscm;
 101
 102        rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
 103        snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
 104                            &capture_ops);
 105        stream = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];
 106
 107        /* Set port names for MIDI input. */
 108        list_for_each_entry(subs, &stream->substreams, list) {
 109                /* TODO: support virtual MIDI ports. */
 110                if (subs->number < tscm->spec->midi_capture_ports) {
 111                        /* Hardware MIDI ports. */
 112                        snprintf(subs->name, sizeof(subs->name),
 113                                 "%s MIDI %d",
 114                                 tscm->card->shortname, subs->number + 1);
 115                }
 116        }
 117
 118        rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
 119        snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
 120                            &playback_ops);
 121        stream = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
 122
 123        /* Set port names for MIDI ourput. */
 124        list_for_each_entry(subs, &stream->substreams, list) {
 125                if (subs->number < tscm->spec->midi_playback_ports) {
 126                        /* Hardware MIDI ports only. */
 127                        snprintf(subs->name, sizeof(subs->name),
 128                                 "%s MIDI %d",
 129                                 tscm->card->shortname, subs->number + 1);
 130                }
 131        }
 132
 133        rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;
 134
 135        return 0;
 136}
 137