root/sound/firewire/digi00x/digi00x-midi.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. midi_open
  2. midi_close
  3. midi_capture_trigger
  4. midi_playback_trigger
  5. set_substream_names
  6. add_substream_pair
  7. snd_dg00x_create_midi_devices

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * digi00x-midi.h - a part of driver for Digidesign Digi 002/003 family
   4  *
   5  * Copyright (c) 2014-2015 Takashi Sakamoto
   6  */
   7 
   8 #include "digi00x.h"
   9 
  10 static int midi_open(struct snd_rawmidi_substream *substream)
  11 {
  12         struct snd_dg00x *dg00x = substream->rmidi->private_data;
  13         int err;
  14 
  15         err = snd_dg00x_stream_lock_try(dg00x);
  16         if (err < 0)
  17                 return err;
  18 
  19         mutex_lock(&dg00x->mutex);
  20         err = snd_dg00x_stream_reserve_duplex(dg00x, 0);
  21         if (err >= 0) {
  22                 ++dg00x->substreams_counter;
  23                 err = snd_dg00x_stream_start_duplex(dg00x);
  24                 if (err < 0)
  25                         --dg00x->substreams_counter;
  26         }
  27         mutex_unlock(&dg00x->mutex);
  28         if (err < 0)
  29                 snd_dg00x_stream_lock_release(dg00x);
  30 
  31         return err;
  32 }
  33 
  34 static int midi_close(struct snd_rawmidi_substream *substream)
  35 {
  36         struct snd_dg00x *dg00x = substream->rmidi->private_data;
  37 
  38         mutex_lock(&dg00x->mutex);
  39         --dg00x->substreams_counter;
  40         snd_dg00x_stream_stop_duplex(dg00x);
  41         mutex_unlock(&dg00x->mutex);
  42 
  43         snd_dg00x_stream_lock_release(dg00x);
  44         return 0;
  45 }
  46 
  47 static void midi_capture_trigger(struct snd_rawmidi_substream *substream,
  48                                  int up)
  49 {
  50         struct snd_dg00x *dg00x = substream->rmidi->private_data;
  51         unsigned int port;
  52         unsigned long flags;
  53 
  54         if (substream->rmidi->device == 0)
  55                 port = substream->number;
  56         else
  57                 port = 2;
  58 
  59         spin_lock_irqsave(&dg00x->lock, flags);
  60 
  61         if (up)
  62                 amdtp_dot_midi_trigger(&dg00x->tx_stream, port, substream);
  63         else
  64                 amdtp_dot_midi_trigger(&dg00x->tx_stream, port, NULL);
  65 
  66         spin_unlock_irqrestore(&dg00x->lock, flags);
  67 }
  68 
  69 static void midi_playback_trigger(struct snd_rawmidi_substream *substream,
  70                                   int up)
  71 {
  72         struct snd_dg00x *dg00x = substream->rmidi->private_data;
  73         unsigned int port;
  74         unsigned long flags;
  75 
  76         if (substream->rmidi->device == 0)
  77                 port = substream->number;
  78         else
  79                 port = 2;
  80 
  81         spin_lock_irqsave(&dg00x->lock, flags);
  82 
  83         if (up)
  84                 amdtp_dot_midi_trigger(&dg00x->rx_stream, port, substream);
  85         else
  86                 amdtp_dot_midi_trigger(&dg00x->rx_stream, port, NULL);
  87 
  88         spin_unlock_irqrestore(&dg00x->lock, flags);
  89 }
  90 
  91 static void set_substream_names(struct snd_dg00x *dg00x,
  92                                 struct snd_rawmidi *rmidi, bool is_console)
  93 {
  94         struct snd_rawmidi_substream *subs;
  95         struct snd_rawmidi_str *str;
  96         int i;
  97 
  98         for (i = 0; i < 2; ++i) {
  99                 str = &rmidi->streams[i];
 100 
 101                 list_for_each_entry(subs, &str->substreams, list) {
 102                         if (!is_console) {
 103                                 snprintf(subs->name, sizeof(subs->name),
 104                                          "%s MIDI %d",
 105                                          dg00x->card->shortname,
 106                                          subs->number + 1);
 107                         } else {
 108                                 snprintf(subs->name, sizeof(subs->name),
 109                                          "%s control",
 110                                          dg00x->card->shortname);
 111                         }
 112                 }
 113         }
 114 }
 115 
 116 static int add_substream_pair(struct snd_dg00x *dg00x, unsigned int out_ports,
 117                               unsigned int in_ports, bool is_console)
 118 {
 119         static const struct snd_rawmidi_ops capture_ops = {
 120                 .open = midi_open,
 121                 .close = midi_close,
 122                 .trigger = midi_capture_trigger,
 123         };
 124         static const struct snd_rawmidi_ops playback_ops = {
 125                 .open = midi_open,
 126                 .close = midi_close,
 127                 .trigger = midi_playback_trigger,
 128         };
 129         const char *label;
 130         struct snd_rawmidi *rmidi;
 131         int err;
 132 
 133         /* Add physical midi ports. */
 134         err = snd_rawmidi_new(dg00x->card, dg00x->card->driver, is_console,
 135                               out_ports, in_ports, &rmidi);
 136         if (err < 0)
 137                 return err;
 138         rmidi->private_data = dg00x;
 139 
 140         if (!is_console)
 141                 label = "%s control";
 142         else
 143                 label = "%s MIDI";
 144         snprintf(rmidi->name, sizeof(rmidi->name), label,
 145                  dg00x->card->shortname);
 146 
 147         snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &playback_ops);
 148         snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &capture_ops);
 149 
 150         rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT |
 151                              SNDRV_RAWMIDI_INFO_OUTPUT |
 152                              SNDRV_RAWMIDI_INFO_DUPLEX;
 153 
 154         set_substream_names(dg00x, rmidi, is_console);
 155 
 156         return 0;
 157 }
 158 
 159 int snd_dg00x_create_midi_devices(struct snd_dg00x *dg00x)
 160 {
 161         int err;
 162 
 163         /* Add physical midi ports. */
 164         err = add_substream_pair(dg00x, DOT_MIDI_OUT_PORTS, DOT_MIDI_IN_PORTS,
 165                                  false);
 166         if (err < 0)
 167                 return err;
 168 
 169         if (dg00x->is_console)
 170                 err = add_substream_pair(dg00x, 1, 1, true);
 171 
 172         return err;
 173 }

/* [<][>][^][v][top][bottom][index][help] */