Linux Audio

Check our new training course

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