2 * ff-midi.c - a part of driver for RME Fireface series
4 * Copyright (c) 2015-2017 Takashi Sakamoto
6 * Licensed under the terms of the GNU General Public License, version 2.
11 static int midi_capture_open(struct snd_rawmidi_substream
*substream
)
17 static int midi_playback_open(struct snd_rawmidi_substream
*substream
)
19 struct snd_ff
*ff
= substream
->rmidi
->private_data
;
21 /* Initialize internal status. */
22 ff
->running_status
[substream
->number
] = 0;
23 ff
->rx_midi_error
[substream
->number
] = false;
25 WRITE_ONCE(ff
->rx_midi_substreams
[substream
->number
], substream
);
30 static int midi_capture_close(struct snd_rawmidi_substream
*substream
)
36 static int midi_playback_close(struct snd_rawmidi_substream
*substream
)
38 struct snd_ff
*ff
= substream
->rmidi
->private_data
;
40 cancel_work_sync(&ff
->rx_midi_work
[substream
->number
]);
41 WRITE_ONCE(ff
->rx_midi_substreams
[substream
->number
], NULL
);
46 static void midi_capture_trigger(struct snd_rawmidi_substream
*substream
,
49 struct snd_ff
*ff
= substream
->rmidi
->private_data
;
52 spin_lock_irqsave(&ff
->lock
, flags
);
55 WRITE_ONCE(ff
->tx_midi_substreams
[substream
->number
],
58 WRITE_ONCE(ff
->tx_midi_substreams
[substream
->number
], NULL
);
60 spin_unlock_irqrestore(&ff
->lock
, flags
);
63 static void midi_playback_trigger(struct snd_rawmidi_substream
*substream
,
66 struct snd_ff
*ff
= substream
->rmidi
->private_data
;
69 spin_lock_irqsave(&ff
->lock
, flags
);
71 if (up
|| !ff
->rx_midi_error
[substream
->number
])
72 schedule_work(&ff
->rx_midi_work
[substream
->number
]);
74 spin_unlock_irqrestore(&ff
->lock
, flags
);
77 static void set_midi_substream_names(struct snd_rawmidi_str
*stream
,
78 const char *const name
)
80 struct snd_rawmidi_substream
*substream
;
82 list_for_each_entry(substream
, &stream
->substreams
, list
) {
83 snprintf(substream
->name
, sizeof(substream
->name
),
84 "%s MIDI %d", name
, substream
->number
+ 1);
88 int snd_ff_create_midi_devices(struct snd_ff
*ff
)
90 static const struct snd_rawmidi_ops midi_capture_ops
= {
91 .open
= midi_capture_open
,
92 .close
= midi_capture_close
,
93 .trigger
= midi_capture_trigger
,
95 static const struct snd_rawmidi_ops midi_playback_ops
= {
96 .open
= midi_playback_open
,
97 .close
= midi_playback_close
,
98 .trigger
= midi_playback_trigger
,
100 struct snd_rawmidi
*rmidi
;
101 struct snd_rawmidi_str
*stream
;
104 err
= snd_rawmidi_new(ff
->card
, ff
->card
->driver
, 0,
105 ff
->spec
->midi_out_ports
, ff
->spec
->midi_in_ports
,
110 snprintf(rmidi
->name
, sizeof(rmidi
->name
),
111 "%s MIDI", ff
->card
->shortname
);
112 rmidi
->private_data
= ff
;
114 rmidi
->info_flags
|= SNDRV_RAWMIDI_INFO_INPUT
;
115 snd_rawmidi_set_ops(rmidi
, SNDRV_RAWMIDI_STREAM_INPUT
,
117 stream
= &rmidi
->streams
[SNDRV_RAWMIDI_STREAM_INPUT
];
118 set_midi_substream_names(stream
, ff
->card
->shortname
);
120 rmidi
->info_flags
|= SNDRV_RAWMIDI_INFO_OUTPUT
;
121 snd_rawmidi_set_ops(rmidi
, SNDRV_RAWMIDI_STREAM_OUTPUT
,
123 stream
= &rmidi
->streams
[SNDRV_RAWMIDI_STREAM_OUTPUT
];
124 set_midi_substream_names(stream
, ff
->card
->shortname
);
126 rmidi
->info_flags
|= SNDRV_RAWMIDI_INFO_DUPLEX
;