Commit | Line | Data |
---|---|---|
248b7802 TS |
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 | ||
11 | static int midi_capture_open(struct snd_rawmidi_substream *substream) | |
12 | { | |
13 | struct snd_bebob *bebob = substream->rmidi->private_data; | |
618eabea TS |
14 | int err; |
15 | ||
16 | err = snd_bebob_stream_lock_try(bebob); | |
17 | if (err < 0) | |
18 | goto end; | |
248b7802 | 19 | |
2a71e701 | 20 | mutex_lock(&bebob->mutex); |
4fd6c6c7 | 21 | bebob->substreams_counter++; |
618eabea | 22 | err = snd_bebob_stream_start_duplex(bebob, 0); |
2a71e701 | 23 | mutex_unlock(&bebob->mutex); |
618eabea TS |
24 | if (err < 0) |
25 | snd_bebob_stream_lock_release(bebob); | |
26 | end: | |
27 | return err; | |
248b7802 TS |
28 | } |
29 | ||
30 | static int midi_playback_open(struct snd_rawmidi_substream *substream) | |
31 | { | |
32 | struct snd_bebob *bebob = substream->rmidi->private_data; | |
618eabea TS |
33 | int err; |
34 | ||
35 | err = snd_bebob_stream_lock_try(bebob); | |
36 | if (err < 0) | |
37 | goto end; | |
248b7802 | 38 | |
2a71e701 | 39 | mutex_lock(&bebob->mutex); |
4fd6c6c7 | 40 | bebob->substreams_counter++; |
618eabea | 41 | err = snd_bebob_stream_start_duplex(bebob, 0); |
2a71e701 | 42 | mutex_unlock(&bebob->mutex); |
618eabea TS |
43 | if (err < 0) |
44 | snd_bebob_stream_lock_release(bebob); | |
45 | end: | |
46 | return err; | |
248b7802 TS |
47 | } |
48 | ||
49 | static int midi_capture_close(struct snd_rawmidi_substream *substream) | |
50 | { | |
51 | struct snd_bebob *bebob = substream->rmidi->private_data; | |
52 | ||
2a71e701 | 53 | mutex_lock(&bebob->mutex); |
4fd6c6c7 | 54 | bebob->substreams_counter--; |
248b7802 | 55 | snd_bebob_stream_stop_duplex(bebob); |
2a71e701 | 56 | mutex_unlock(&bebob->mutex); |
248b7802 | 57 | |
618eabea | 58 | snd_bebob_stream_lock_release(bebob); |
248b7802 TS |
59 | return 0; |
60 | } | |
61 | ||
62 | static int midi_playback_close(struct snd_rawmidi_substream *substream) | |
63 | { | |
64 | struct snd_bebob *bebob = substream->rmidi->private_data; | |
65 | ||
2a71e701 | 66 | mutex_lock(&bebob->mutex); |
4fd6c6c7 | 67 | bebob->substreams_counter--; |
248b7802 | 68 | snd_bebob_stream_stop_duplex(bebob); |
2a71e701 | 69 | mutex_unlock(&bebob->mutex); |
248b7802 | 70 | |
618eabea | 71 | snd_bebob_stream_lock_release(bebob); |
248b7802 TS |
72 | return 0; |
73 | } | |
74 | ||
75 | static 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) | |
03e2a67e TS |
83 | amdtp_am824_midi_trigger(&bebob->tx_stream, |
84 | substrm->number, substrm); | |
248b7802 | 85 | else |
03e2a67e TS |
86 | amdtp_am824_midi_trigger(&bebob->tx_stream, |
87 | substrm->number, NULL); | |
248b7802 TS |
88 | |
89 | spin_unlock_irqrestore(&bebob->lock, flags); | |
90 | } | |
91 | ||
92 | static 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) | |
03e2a67e TS |
100 | amdtp_am824_midi_trigger(&bebob->rx_stream, |
101 | substrm->number, substrm); | |
248b7802 | 102 | else |
03e2a67e TS |
103 | amdtp_am824_midi_trigger(&bebob->rx_stream, |
104 | substrm->number, NULL); | |
248b7802 TS |
105 | |
106 | spin_unlock_irqrestore(&bebob->lock, flags); | |
107 | } | |
108 | ||
248b7802 TS |
109 | static void set_midi_substream_names(struct snd_bebob *bebob, |
110 | struct snd_rawmidi_str *str) | |
111 | { | |
112 | struct snd_rawmidi_substream *subs; | |
113 | ||
114 | list_for_each_entry(subs, &str->substreams, list) { | |
115 | snprintf(subs->name, sizeof(subs->name), | |
116 | "%s MIDI %d", | |
117 | bebob->card->shortname, subs->number + 1); | |
118 | } | |
119 | } | |
120 | ||
121 | int snd_bebob_create_midi_devices(struct snd_bebob *bebob) | |
122 | { | |
57eb6799 | 123 | static const struct snd_rawmidi_ops capture_ops = { |
4780f774 TS |
124 | .open = midi_capture_open, |
125 | .close = midi_capture_close, | |
126 | .trigger = midi_capture_trigger, | |
127 | }; | |
57eb6799 | 128 | static const struct snd_rawmidi_ops playback_ops = { |
4780f774 TS |
129 | .open = midi_playback_open, |
130 | .close = midi_playback_close, | |
131 | .trigger = midi_playback_trigger, | |
132 | }; | |
248b7802 TS |
133 | struct snd_rawmidi *rmidi; |
134 | struct snd_rawmidi_str *str; | |
135 | int err; | |
136 | ||
137 | /* create midi ports */ | |
138 | err = snd_rawmidi_new(bebob->card, bebob->card->driver, 0, | |
139 | bebob->midi_output_ports, bebob->midi_input_ports, | |
140 | &rmidi); | |
141 | if (err < 0) | |
142 | return err; | |
143 | ||
144 | snprintf(rmidi->name, sizeof(rmidi->name), | |
145 | "%s MIDI", bebob->card->shortname); | |
146 | rmidi->private_data = bebob; | |
147 | ||
148 | if (bebob->midi_input_ports > 0) { | |
149 | rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT; | |
150 | ||
151 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, | |
4780f774 | 152 | &capture_ops); |
248b7802 TS |
153 | |
154 | str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT]; | |
155 | ||
156 | set_midi_substream_names(bebob, str); | |
157 | } | |
158 | ||
159 | if (bebob->midi_output_ports > 0) { | |
160 | rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT; | |
161 | ||
162 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, | |
4780f774 | 163 | &playback_ops); |
248b7802 TS |
164 | |
165 | str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT]; | |
166 | ||
167 | set_midi_substream_names(bebob, str); | |
168 | } | |
169 | ||
170 | if ((bebob->midi_output_ports > 0) && (bebob->midi_input_ports > 0)) | |
171 | rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX; | |
172 | ||
173 | return 0; | |
174 | } |