Try to parse the UMP Endpoint and UMP Function Blocks for building the
topology at first. Only when those are missing (e.g. on an older USB
MIDI 2.0 spec or a unidirectional endpoint), the driver still creates
blocks based on USB group terminal block information as fallback.
Signed-off-by: Takashi Iwai <[email protected]>
---
sound/usb/midi2.c | 34 +++++++++++++++++++++++++++++++++-
1 file changed, 33 insertions(+), 1 deletion(-)
diff --git a/sound/usb/midi2.c b/sound/usb/midi2.c
index 341783418a6a..fad094e15999 100644
--- a/sound/usb/midi2.c
+++ b/sound/usb/midi2.c
@@ -80,6 +80,7 @@ struct snd_usb_midi2_ump {
struct snd_usb_midi2_endpoint *eps[2]; /* USB MIDI endpoints */
int index; /* rawmidi device index */
unsigned char usb_block_id; /* USB GTB id used for finding a pair */
+ bool ump_parsed; /* Parsed UMP 1.1 EP/FB info*/
struct list_head list; /* list to umidi->rawmidi_list */
};
@@ -786,6 +787,31 @@ static int find_matching_ep_partner(struct snd_usb_midi2_interface *umidi,
return 0;
}
+/* Call UMP helper to parse UMP endpoints;
+ * this needs to be called after starting the input streams for bi-directional
+ * communications
+ */
+static int parse_ump_endpoints(struct snd_usb_midi2_interface *umidi)
+{
+ struct snd_usb_midi2_ump *rmidi;
+ int err;
+
+ list_for_each_entry(rmidi, &umidi->rawmidi_list, list) {
+ if (!rmidi->ump ||
+ !(rmidi->ump->core.info_flags & SNDRV_RAWMIDI_INFO_DUPLEX))
+ continue;
+ err = snd_ump_parse_endpoint(rmidi->ump);
+ if (!err) {
+ rmidi->ump_parsed = true;
+ } else {
+ if (err == -ENOMEM)
+ return err;
+ /* fall back to GTB later */
+ }
+ }
+ return 0;
+}
+
/* create a UMP block from a GTB entry */
static int create_gtb_block(struct snd_usb_midi2_ump *rmidi, int dir, int blk)
{
@@ -856,7 +882,7 @@ static int create_blocks_from_gtb(struct snd_usb_midi2_interface *umidi)
if (!rmidi->ump)
continue;
/* Blocks have been already created? */
- if (rmidi->ump->info.num_blocks)
+ if (rmidi->ump_parsed || rmidi->ump->info.num_blocks)
continue;
/* loop over GTBs */
for (dir = 0; dir < 2; dir++) {
@@ -1110,6 +1136,12 @@ int snd_usb_midi_v2_create(struct snd_usb_audio *chip,
goto error;
}
+ err = parse_ump_endpoints(umidi);
+ if (err < 0) {
+ usb_audio_err(chip, "Failed to parse UMP endpoint\n");
+ goto error;
+ }
+
err = create_blocks_from_gtb(umidi);
if (err < 0) {
usb_audio_err(chip, "Failed to create GTB blocks\n");
--
2.35.3