Received: by 2002:a05:6a10:8c0a:0:0:0:0 with SMTP id go10csp1537078pxb; Fri, 26 Feb 2021 13:28:59 -0800 (PST) X-Google-Smtp-Source: ABdhPJym1J5a3/2BOGUbbI3a/kINWJ0UClZZEO2U0aDq2SBnm0d5swye27VXAq1NYQ4QSMCPlGQf X-Received: by 2002:a50:fe17:: with SMTP id f23mr5753040edt.258.1614374939118; Fri, 26 Feb 2021 13:28:59 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1614374939; cv=none; d=google.com; s=arc-20160816; b=oe94+yY/F1WPOfsiDltsC0vUI4TaO3WeagwOv8V3pPc2T68a56A8/0Cekr4RQw3LL7 Y1waPEfDEtDKP8dT78C4eS7+WKCgGeznlIl4HGx9r0sHfoi1Wh9+YHdJUa1D0fy9O5y1 B/8vvSHOEc7bYLBQlNs6V+/QNEdGWxL7cufAiGW3LGeR2n79ftIbJ21iZkpHc8ZbwzCL 40/bP8FirSlCUEwBKDxT01y1TTNrwGN5ZSPJCNYh1o102V7iY5IKvgOK7E9Ym70GV616 LE7oHzEDLYFYyz/d4Y490yQ5BaeGpwooUM4emyYJ32VmE3PbGloYUwFRKN98K0eY25zD oHcg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=cQuLN6vQ1ptZtp4bMRyyZsTd6BPgreKDQsJfM9SJC9A=; b=Oy973rHFJ993RiBRL9Jt/yWPgvTbEEOZrOCvR+6C5dmK2cBNV0BP+9vxaLkuPFV48I s+qweaqxobvSXHJOz1duQ9XBaRw2PnBwYpxm36EyO+J6+py1r9D5EmdIT7YcKmrppJpG 0xmYJYf6za9HwrZDnP4vxiouu55AiFwmAIMA0iTvyae++ZhHfOp9b8RxzDBQGXD4/V5p +ZjbwlmNSiOIb81qcSQrLaFTYLJUT76ZXibr46hKmJqBGkMsmh2pWu62g/w9kk9b6tIT KzYYtp4loS86YwSyyYiVTeZrqOKI97aFnA8FOnA8Q8kCIWCe3kpphjF6WJCWTpTwj9Tg JOyg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@george-graphics-co-uk.20150623.gappssmtp.com header.s=20150623 header.b=z0wP+jbM; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id 38si6683258edq.44.2021.02.26.13.28.37; Fri, 26 Feb 2021 13:28:59 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@george-graphics-co-uk.20150623.gappssmtp.com header.s=20150623 header.b=z0wP+jbM; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230125AbhBZV1U (ORCPT + 99 others); Fri, 26 Feb 2021 16:27:20 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56440 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229745AbhBZV1R (ORCPT ); Fri, 26 Feb 2021 16:27:17 -0500 Received: from mail-pg1-x52b.google.com (mail-pg1-x52b.google.com [IPv6:2607:f8b0:4864:20::52b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 819B3C06174A for ; Fri, 26 Feb 2021 13:26:37 -0800 (PST) Received: by mail-pg1-x52b.google.com with SMTP id a4so6952222pgc.11 for ; Fri, 26 Feb 2021 13:26:37 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=george-graphics-co-uk.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=cQuLN6vQ1ptZtp4bMRyyZsTd6BPgreKDQsJfM9SJC9A=; b=z0wP+jbM8a/adjYckcngBEkj2zXwVLvEBn3vXSDtf1a6Y0jvtGJFxOg4yRsVtx3EpP NNBnzHcf/0Htw5NGifO11vjhzkwDe7TK7VQdOqquglYuMgz1YJQ+USY2KC8nzB55e2lI uKDEjnPuLm2IFn1H1AddfMyALhDt2PxSgp7WGKAwBTK65uCk3/csgDFeNJd0ThxKDGyr IL7ZfqazEfJw14JeGOkb1+4S6QpLPAi1xEgPYG04K4yl1OEvcDf9StevIGs7shu8g6GS tGe8O0QUwi7xsBnur2LqxbJujG9dzrQGvV83Pxlx0jFeoEVTi3uelAbdgXLEzD4jFBrb L6IA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=cQuLN6vQ1ptZtp4bMRyyZsTd6BPgreKDQsJfM9SJC9A=; b=ThvPfzqm0/3eR7lGUQMaRAl7uOyASsEKAtiJnK4MLFDFgxQmcXue6UZGSZ5WHo3+ZO +Tpb6U9Lr5hHH5ATN5F5gWx5ih9Bfy0+L7KyLg9OK2pdP1iqsjB9BiuwhDiZ6vak2EAo mjGispo+J9i4lbAaZycr5vz70J80HHUulUFkxkBS3VBobWqqb6guOD1oiKF7x/yDAL71 2lP6EUTR7f+zAYJ5QhEGh0eFJYP1h15yMc/fTXz8Kx/kizMiPInnRqSBLaGVPw4eBevf LCgsvfGgqA2mVASKjY9gPDbOYGr4QoeMm+HXnABDlWt24E6S2tnfH1lKh7KfCnAr7XL7 vbnw== X-Gm-Message-State: AOAM532gODJ9nEMJwqdBTul9fe03bNgjktdWO4ZVPOQZmHqul4aiuo+C u4WH6HU8KTLI1dGFKcWcKxMc2g== X-Received: by 2002:aa7:9aad:0:b029:1ee:468a:d950 with SMTP id x13-20020aa79aad0000b02901ee468ad950mr2812806pfi.40.1614374796894; Fri, 26 Feb 2021 13:26:36 -0800 (PST) Received: from sequencer.hsd1.wa.comcast.net ([2601:602:8000:181:df1d:64b5:575f:9598]) by smtp.gmail.com with ESMTPSA id 125sm10862073pfu.7.2021.02.26.13.26.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 26 Feb 2021 13:26:36 -0800 (PST) From: George Harker To: Takashi Iwai Cc: George Harker , Clemens Ladisch , Jaroslav Kysela , Takashi Iwai , alsa-devel@alsa-project.org, linux-kernel@vger.kernel.org Subject: [PATCH 2/2] midi streaming substream names from jack names A number of devices have named substreams which are hard to remember / decypher from MIDI n names. Eg. Korg puts a pass through on one substream and iConnectivity devices name the connections. Date: Fri, 26 Feb 2021 21:26:16 +0000 Message-Id: <20210226212617.24616-1-george@george-graphics.co.uk> X-Mailer: git-send-email 2.20.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This makes it easier to connect to the correct device. Devices which handle naming through quirks are unaffected by this change. Addresses TODO comment in sound/usb/midi.c Signed-off-by: George Harker --- sound/usb/midi.c | 103 ++++++++++++++++++++++++++++++++++++++++++++--- sound/usb/midi.h | 2 + 2 files changed, 100 insertions(+), 5 deletions(-) diff --git a/sound/usb/midi.c b/sound/usb/midi.c index 610cf54ee..9efda4b06 100644 --- a/sound/usb/midi.c +++ b/sound/usb/midi.c @@ -1740,12 +1740,68 @@ static void snd_usbmidi_get_port_info(struct snd_rawmidi *rmidi, int number, } } +static struct usb_midi_in_jack_descriptor *find_usb_in_jack_descriptor( + struct usb_host_interface *hostif, uint8_t jack_id) +{ + unsigned char *extra = hostif->extra; + int extralen = hostif->extralen; + + while (extralen > 4) { + struct usb_midi_in_jack_descriptor *injd = + (struct usb_midi_in_jack_descriptor *)extra; + + if (injd->bLength > 4 && + injd->bDescriptorType == USB_DT_CS_INTERFACE && + injd->bDescriptorSubtype == UAC_MIDI_IN_JACK && + injd->bJackID == jack_id) + return injd; + if (!extra[0]) + break; + extralen -= extra[0]; + extra += extra[0]; + } + return NULL; +} + +static struct usb_midi_out_jack_descriptor *find_usb_out_jack_descriptor( + struct usb_host_interface *hostif, uint8_t jack_id) +{ + unsigned char *extra = hostif->extra; + int extralen = hostif->extralen; + + while (extralen > 4) { + struct usb_midi_out_jack_descriptor *outjd = + (struct usb_midi_out_jack_descriptor *)extra; + + if (outjd->bLength > 4 && + outjd->bDescriptorType == USB_DT_CS_INTERFACE && + outjd->bDescriptorSubtype == UAC_MIDI_OUT_JACK && + outjd->bJackID == jack_id) + return outjd; + if (!extra[0]) + break; + extralen -= extra[0]; + extra += extra[0]; + } + return NULL; +} + static void snd_usbmidi_init_substream(struct snd_usb_midi *umidi, - int stream, int number, + int stream, int number, int jack_id, struct snd_rawmidi_substream **rsubstream) { struct port_info *port_info; const char *name_format; + struct usb_interface *intf; + struct usb_host_interface *hostif; + struct usb_midi_in_jack_descriptor *injd; + struct usb_midi_out_jack_descriptor *outjd; + uint8_t jack_name_buf[32]; + uint8_t *default_jack_name = "MIDI"; + uint8_t *jack_name = default_jack_name; + uint8_t iJack; + size_t sz; + int res; struct snd_rawmidi_substream *substream = snd_usbmidi_find_substream(umidi, stream, number); @@ -1755,11 +1811,36 @@ static void snd_usbmidi_init_substream(struct snd_usb_midi *umidi, return; } - /* TODO: read port name from jack descriptor */ + intf = umidi->iface; + if (intf && jack_id >= 0) { + hostif = intf->cur_altsetting; + iJack = 0; + if (stream != SNDRV_RAWMIDI_STREAM_OUTPUT) { + /* in jacks connect to outs */ + outjd = find_usb_out_jack_descriptor(hostif, jack_id); + if (outjd) { + sz = USB_DT_MIDI_OUT_SIZE(outjd->bNrInputPins); + iJack = *(((uint8_t *) outjd) + sz - sizeof(uint8_t)); + } + } else { + /* and out jacks connect to ins */ + injd = find_usb_in_jack_descriptor(hostif, jack_id); + if (injd) + iJack = injd->iJack; + } + if (iJack != 0) { + res = usb_string(umidi->dev, iJack, jack_name_buf, + ARRAY_SIZE(jack_name_buf)); + if (res) + jack_name = jack_name_buf; + } + } + port_info = find_port_info(umidi, number); - name_format = port_info ? port_info->name : "%s MIDI %d"; + name_format = port_info ? port_info->name : + (jack_name != default_jack_name ? "%s %s" : "%s %s %d"); snprintf(substream->name, sizeof(substream->name), - name_format, umidi->card->shortname, number + 1); + name_format, umidi->card->shortname, jack_name, number + 1); *rsubstream = substream; } @@ -1794,6 +1875,7 @@ static int snd_usbmidi_create_endpoints(struct snd_usb_midi *umidi, snd_usbmidi_init_substream(umidi, SNDRV_RAWMIDI_STREAM_OUTPUT, out_ports, + endpoints[i].assoc_out_jacks[j], &umidi->endpoints[i].out->ports[j].substream); ++out_ports; } @@ -1801,6 +1883,7 @@ static int snd_usbmidi_create_endpoints(struct snd_usb_midi *umidi, snd_usbmidi_init_substream(umidi, SNDRV_RAWMIDI_STREAM_INPUT, in_ports, + endpoints[i].assoc_in_jacks[j], &umidi->endpoints[i].in->ports[j].substream); ++in_ports; } @@ -1846,7 +1929,7 @@ static int snd_usbmidi_get_ms_info(struct snd_usb_midi *umidi, struct usb_host_endpoint *hostep; struct usb_endpoint_descriptor *ep; struct usb_ms_endpoint_descriptor *ms_ep; - int i, epidx; + int i, j, epidx; intf = umidi->iface; if (!intf) @@ -1895,6 +1978,10 @@ static int snd_usbmidi_get_ms_info(struct snd_usb_midi *umidi, endpoints[epidx].out_interval = 1; endpoints[epidx].out_cables = (1 << ms_ep->bNumEmbMIDIJack) - 1; + for (j = 0; j < ms_ep->bNumEmbMIDIJack; ++j) + endpoints[epidx].assoc_out_jacks[j] = ms_ep->baAssocJackID[j]; + for (; j < ARRAY_SIZE(endpoints[epidx].assoc_out_jacks); ++j) + endpoints[epidx].assoc_out_jacks[j] = -1; dev_dbg(&umidi->dev->dev, "EP %02X: %d jack(s)\n", ep->bEndpointAddress, ms_ep->bNumEmbMIDIJack); } else { @@ -1912,6 +1999,10 @@ static int snd_usbmidi_get_ms_info(struct snd_usb_midi *umidi, endpoints[epidx].in_interval = 1; endpoints[epidx].in_cables = (1 << ms_ep->bNumEmbMIDIJack) - 1; + for (j = 0; j < ms_ep->bNumEmbMIDIJack; ++j) + endpoints[epidx].assoc_in_jacks[j] = ms_ep->baAssocJackID[j]; + for (; j < ARRAY_SIZE(endpoints[epidx].assoc_in_jacks); ++j) + endpoints[epidx].assoc_in_jacks[j] = -1; dev_dbg(&umidi->dev->dev, "EP %02X: %d jack(s)\n", ep->bEndpointAddress, ms_ep->bNumEmbMIDIJack); } @@ -2228,11 +2319,13 @@ static int snd_usbmidi_create_endpoints_midiman(struct snd_usb_midi *umidi, snd_usbmidi_init_substream(umidi, SNDRV_RAWMIDI_STREAM_OUTPUT, cable, + -1 /* prevent trying to find jack */, &umidi->endpoints[cable & 1].out->ports[cable].substream); if (endpoint->in_cables & (1 << cable)) snd_usbmidi_init_substream(umidi, SNDRV_RAWMIDI_STREAM_INPUT, cable, + -1 /* prevent trying to find jack */, &umidi->endpoints[0].in->ports[cable].substream); } return 0; diff --git a/sound/usb/midi.h b/sound/usb/midi.h index 8c38aec22..3f153195c 100644 --- a/sound/usb/midi.h +++ b/sound/usb/midi.h @@ -13,6 +13,8 @@ struct snd_usb_midi_endpoint_info { uint8_t in_interval; uint16_t out_cables; /* bitmask */ uint16_t in_cables; /* bitmask */ + int16_t assoc_in_jacks[16]; + int16_t assoc_out_jacks[16]; }; /* for QUIRK_MIDI_YAMAHA, data is NULL */ -- 2.20.1