[PATCH 03/10] ALSA: usb-audio: Parse UMP Endpoint and Function Blocks at first

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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 <tiwai@xxxxxxx>
---
 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




[Index of Archives]     [ALSA User]     [Linux Audio Users]     [Pulse Audio]     [Kernel Archive]     [Asterisk PBX]     [Photo Sharing]     [Linux Sound]     [Video 4 Linux]     [Gimp]     [Yosemite News]

  Powered by Linux