linux/sound/firewire/bebob/bebob_midi.c
<<
>>
Prefs
   1/*
   2 * bebob_midi.c - a part of driver for BeBoB based devices
   3 *
   4 * Copyright (c) 2013-2014 Takashi Sakamoto
   5 *
   6 * Licensed under the terms of the GNU General Public License, version 2.
   7 */
   8
   9#include "bebob.h"
  10
  11static int midi_capture_open(struct snd_rawmidi_substream *substream)
  12{
  13        struct snd_bebob *bebob = substream->rmidi->private_data;
  14        int err;
  15
  16        err = snd_bebob_stream_lock_try(bebob);
  17        if (err < 0)
  18                goto end;
  19
  20        atomic_inc(&bebob->capture_substreams);
  21        err = snd_bebob_stream_start_duplex(bebob, 0);
  22        if (err < 0)
  23                snd_bebob_stream_lock_release(bebob);
  24end:
  25        return err;
  26}
  27
  28static int midi_playback_open(struct snd_rawmidi_substream *substream)
  29{
  30        struct snd_bebob *bebob = substream->rmidi->private_data;
  31        int err;
  32
  33        err = snd_bebob_stream_lock_try(bebob);
  34        if (err < 0)
  35                goto end;
  36
  37        atomic_inc(&bebob->playback_substreams);
  38        err = snd_bebob_stream_start_duplex(bebob, 0);
  39        if (err < 0)
  40                snd_bebob_stream_lock_release(bebob);
  41end:
  42        return err;
  43}
  44
  45static int midi_capture_close(struct snd_rawmidi_substream *substream)
  46{
  47        struct snd_bebob *bebob = substream->rmidi->private_data;
  48
  49        atomic_dec(&bebob->capture_substreams);
  50        snd_bebob_stream_stop_duplex(bebob);
  51
  52        snd_bebob_stream_lock_release(bebob);
  53        return 0;
  54}
  55
  56static int midi_playback_close(struct snd_rawmidi_substream *substream)
  57{
  58        struct snd_bebob *bebob = substream->rmidi->private_data;
  59
  60        atomic_dec(&bebob->playback_substreams);
  61        snd_bebob_stream_stop_duplex(bebob);
  62
  63        snd_bebob_stream_lock_release(bebob);
  64        return 0;
  65}
  66
  67static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up)
  68{
  69        struct snd_bebob *bebob = substrm->rmidi->private_data;
  70        unsigned long flags;
  71
  72        spin_lock_irqsave(&bebob->lock, flags);
  73
  74        if (up)
  75                amdtp_stream_midi_trigger(&bebob->tx_stream,
  76                                          substrm->number, substrm);
  77        else
  78                amdtp_stream_midi_trigger(&bebob->tx_stream,
  79                                          substrm->number, NULL);
  80
  81        spin_unlock_irqrestore(&bebob->lock, flags);
  82}
  83
  84static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)
  85{
  86        struct snd_bebob *bebob = substrm->rmidi->private_data;
  87        unsigned long flags;
  88
  89        spin_lock_irqsave(&bebob->lock, flags);
  90
  91        if (up)
  92                amdtp_stream_midi_trigger(&bebob->rx_stream,
  93                                          substrm->number, substrm);
  94        else
  95                amdtp_stream_midi_trigger(&bebob->rx_stream,
  96                                          substrm->number, NULL);
  97
  98        spin_unlock_irqrestore(&bebob->lock, flags);
  99}
 100
 101static struct snd_rawmidi_ops midi_capture_ops = {
 102        .open           = midi_capture_open,
 103        .close          = midi_capture_close,
 104        .trigger        = midi_capture_trigger,
 105};
 106
 107static struct snd_rawmidi_ops midi_playback_ops = {
 108        .open           = midi_playback_open,
 109        .close          = midi_playback_close,
 110        .trigger        = midi_playback_trigger,
 111};
 112
 113static void set_midi_substream_names(struct snd_bebob *bebob,
 114                                     struct snd_rawmidi_str *str)
 115{
 116        struct snd_rawmidi_substream *subs;
 117
 118        list_for_each_entry(subs, &str->substreams, list) {
 119                snprintf(subs->name, sizeof(subs->name),
 120                         "%s MIDI %d",
 121                         bebob->card->shortname, subs->number + 1);
 122        }
 123}
 124
 125int snd_bebob_create_midi_devices(struct snd_bebob *bebob)
 126{
 127        struct snd_rawmidi *rmidi;
 128        struct snd_rawmidi_str *str;
 129        int err;
 130
 131        /* create midi ports */
 132        err = snd_rawmidi_new(bebob->card, bebob->card->driver, 0,
 133                              bebob->midi_output_ports, bebob->midi_input_ports,
 134                              &rmidi);
 135        if (err < 0)
 136                return err;
 137
 138        snprintf(rmidi->name, sizeof(rmidi->name),
 139                 "%s MIDI", bebob->card->shortname);
 140        rmidi->private_data = bebob;
 141
 142        if (bebob->midi_input_ports > 0) {
 143                rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
 144
 145                snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
 146                                    &midi_capture_ops);
 147
 148                str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];
 149
 150                set_midi_substream_names(bebob, str);
 151        }
 152
 153        if (bebob->midi_output_ports > 0) {
 154                rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
 155
 156                snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
 157                                    &midi_playback_ops);
 158
 159                str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
 160
 161                set_midi_substream_names(bebob, str);
 162        }
 163
 164        if ((bebob->midi_output_ports > 0) && (bebob->midi_input_ports > 0))
 165                rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;
 166
 167        return 0;
 168}
 169