From nobody Wed Dec 17 12:21:11 2025 Received: from mail-wm1-f51.google.com (mail-wm1-f51.google.com [209.85.128.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 46A99328276 for ; Tue, 9 Dec 2025 16:40:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1765298437; cv=none; b=F6PL1B9KEjvwC/ADtPcejhnILi4ecaNiPHAFCv2Pf31xNhUTzvGALPAx3Aw/jDxpawVDbFZxaarWKVg5ss7kvLk7IkSdR1rs7Jl2izqL0EGoWEgKGsS3f9jYMwvOFN9vW1nQB0vWPjnN5D083mC2NwXJ6c73KpRwfnPdMSLPCmg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1765298437; c=relaxed/simple; bh=++9OHvhMumrV20LJ7q5JsVuI+EnRyA0/+GtmYBQSsVE=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=cmCfKrLVUd3qr0lByAo6clissSRwQ3rgddZ3q+pe6XlNs6Tv3LD/xbrV3i1lHgD1+OxFMW3D7l4xx9OjZ4lwlfE+k84rSfDBw/YybWrhCBOW9WL4adMVa969hWD0f+pfrjjyudYEy5Yd7Y26W7b9lzyfFXnwQNr545wvpEW+9Qw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arturia.com; spf=pass smtp.mailfrom=arturia.com; dkim=pass (2048-bit key) header.d=arturia.com header.i=@arturia.com header.b=APIMrdAo; arc=none smtp.client-ip=209.85.128.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arturia.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arturia.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=arturia.com header.i=@arturia.com header.b="APIMrdAo" Received: by mail-wm1-f51.google.com with SMTP id 5b1f17b1804b1-4775ae77516so70852165e9.1 for ; Tue, 09 Dec 2025 08:40:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=arturia.com; s=arturia; t=1765298432; x=1765903232; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=Sd5cGMdlvX87FNTFw7luLCsJmzXmWV6Bmc5tqLNvtGs=; b=APIMrdAol+fI3N3Po0REqnGQjtvM5s63PeoM18gUxbvTWO2QunC8fWgiqm2w94NL8Q 4moXbHy4uWqK19f1g0w9MtA4H0cxvm6m/An1DrRVGwtaLSmPzYzlKsmWA5/rCLbKEsrh 7pQHq8LjGbTlPt+/y9E0YwJ3fyvW/hl5ot04j/83rmDoUo8yrxN+xuAJG92sJxAxh1YI 2ng/Clx47zJ4Q8fwdCoIF+E5Tlu0BX8akmjlPAFBE9nfAlomf5cAwgXZFESxkGBomFN6 +ikZmFBPhTm5qO/5mru14H5IET9D5pNJblNhxjf14jbZ5gwVig++ySkpjSBUS0CwpQvq GNMQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1765298432; x=1765903232; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=Sd5cGMdlvX87FNTFw7luLCsJmzXmWV6Bmc5tqLNvtGs=; b=V4vaMFilV8PIQSvGL8PGHJGjVsToaAV0ZRnkETneCQoPapna4gKH6iiGmS6UM5t2jC S4xaT/EUBoTDWg5JSp2erdSRmNBBvCmufBjG1jO+4+eCqee1Gwe2YQny7CEtIw/WocIy ifDHBOmkGR4C9SpIEDq/jeY75ZtFpLfS5BVCPgB9G+TUz15eAwFj//E1vEjcciEYkedK q+QfOu/VBs1whrp5n9sDc/sHEYrgfF//JMCBc8jC6jE7aSmLHRMS9CZHvDyCvdMY69j7 /UeuZAy8cjQ7qABX47mqY43nzqXiGxeIBpwkXzo2cyQCc17awgHDshr9p0RTn2iM99Pk l6Kw== X-Forwarded-Encrypted: i=1; AJvYcCV746F48g4fmAuEM34FaFKU3oVSxeEJLt4uiHKO9yTvwUwHDoDrBGnLZJoUVsCPAXvg6UunTDYmVxqJPAQ=@vger.kernel.org X-Gm-Message-State: AOJu0YxL/obWEBvhO19rnggs70upjlQ4s4Y6zs4hTE1HwR4kImEYFlDe iAKJbS/8kWrjM7ePvnKnSUJxcgAYBjueCRKGKHYSRQRmELF/RjAxt5Yp1/KzfZUvxjw= X-Gm-Gg: ASbGncv73sd1zNRO6hptslK6BpRUyaxDY0buhvFesXYYvS8XlSiOYJ47vxe92d80lxR D3C6cZ8oc3PeO5C+n61nzpB6szeC6Pmtj7XWJYmFcRo+A3Uylj+DLR4mmEMXS70Y5N/Hz/WbxEy mSBbMqWDs7Rp+MXcUthniBiYrI5auoaFPfHvOIWIUl9+cdcdvPAXTuKcnZ2VcblfWQVhwxd2u5o HdMKuV0nfFpzbeUCzP68LUi8gsHyXHj53ktJlD2JNNb4AsTDAIf5qF8PTWi4gmmrqc26TlyNSu9 hsadZPg9dTsBaANaW6NqMlpz6CI2jcaxzqX3CvqQcksXX5742RPcMnLLBudUL9iz+e2VpodgkOX XrwTgTI9p00hQt3EDJnpUqi/s2n+emQ909Gd/r9djk7lXbb3NWYYEZ7iUyUICM72X2qZiwWG0N8 UXbKLpW3YwiNXZSTrIjdWk50VG9EYSp+p0mhE7 X-Google-Smtp-Source: AGHT+IELAzcsYpOj9uuRdYM2/XzumHYICgClkqlPJHMr4EhFYRmtgMYYKCFf5swysg49tA6DSYOSlg== X-Received: by 2002:a05:600c:1c1b:b0:477:b734:8c53 with SMTP id 5b1f17b1804b1-47939dfa09fmr113474715e9.12.1765298432259; Tue, 09 Dec 2025 08:40:32 -0800 (PST) Received: from localhost.localdomain ([2a01:cb15:854c:e000:e58b:a5ca:200b:e2e2]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-42f7cbfee71sm32550060f8f.15.2025.12.09.08.40.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 09 Dec 2025 08:40:31 -0800 (PST) From: Victor Krawiec To: gregkh@linuxfoundation.org Cc: tiwai@suse.de, corbet@lwn.net, jilliandonahue58@gmail.com, selvarasu.g@samsung.com, jkeeping@inmusicbrands.com, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org, linux-doc@vger.kernel.org, linux-api@vger.kernel.org, Victor Krawiec Subject: [PATCH v2] usb: gadget: f_midi: allow customizing the USB MIDI interface string through configfs Date: Tue, 9 Dec 2025 17:40:06 +0100 Message-ID: <20251209164006.143219-1-victor.krawiec@arturia.com> X-Mailer: git-send-email 2.43.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" When using f_midi from configfs the USB MIDI interface string is hardcoded to 'MIDI function'. This USB string descriptor is used by some third-party OS or software to display the name of the MIDI device Since we add an additional string option a new macro block was created to factorize declarations Signed-off-by: Victor Krawiec Reviewed-by: Takashi Iwai --- V1 -> V2: - Add documentation - Cleanup unnecessary *_allocated boolean as requested in review .../ABI/testing/configfs-usb-gadget-midi | 17 +-- Documentation/usb/gadget-testing.rst | 17 +-- drivers/usb/gadget/function/f_midi.c | 110 ++++++++++-------- drivers/usb/gadget/function/u_midi.h | 2 +- 4 files changed, 78 insertions(+), 68 deletions(-) diff --git a/Documentation/ABI/testing/configfs-usb-gadget-midi b/Documenta= tion/ABI/testing/configfs-usb-gadget-midi index 07389cddd51a..d6bd67bb91fc 100644 --- a/Documentation/ABI/testing/configfs-usb-gadget-midi +++ b/Documentation/ABI/testing/configfs-usb-gadget-midi @@ -4,11 +4,12 @@ KernelVersion: 3.19 Description: The attributes: =20 - =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D - index index value for the USB MIDI adapter - id ID string for the USB MIDI adapter - buflen MIDI buffer length - qlen USB read request queue length - in_ports number of MIDI input ports - out_ports number of MIDI output ports - =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D + index index value for the USB MIDI adapter + id ID string for the USB MIDI adapter + buflen MIDI buffer length + qlen USB read request queue length + in_ports number of MIDI input ports + out_ports number of MIDI output ports + interface_string USB AudioControl interface string + =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D diff --git a/Documentation/usb/gadget-testing.rst b/Documentation/usb/gadge= t-testing.rst index 5f90af1fb573..01a128d664cb 100644 --- a/Documentation/usb/gadget-testing.rst +++ b/Documentation/usb/gadget-testing.rst @@ -368,14 +368,15 @@ Function-specific configfs interface The function name to use when creating the function directory is "midi". The MIDI function provides these attributes in its function directory: =20 - =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D - buflen MIDI buffer length - id ID string for the USB MIDI adapter - in_ports number of MIDI input ports - index index value for the USB MIDI adapter - out_ports number of MIDI output ports - qlen USB read request queue length - =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D + =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D + buflen MIDI buffer length + id ID string for the USB MIDI adapter + in_ports number of MIDI input ports + index index value for the USB MIDI adapter + out_ports number of MIDI output ports + qlen USB read request queue length + interface_string USB AudioControl interface string + =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D =20 Testing the MIDI function ------------------------- diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/func= tion/f_midi.c index da82598fcef8..ad679a6ecac1 100644 --- a/drivers/usb/gadget/function/f_midi.c +++ b/drivers/usb/gadget/function/f_midi.c @@ -875,6 +875,7 @@ static int f_midi_bind(struct usb_configuration *c, str= uct usb_function *f) struct usb_composite_dev *cdev =3D c->cdev; struct f_midi *midi =3D func_to_midi(f); struct usb_string *us; + struct f_midi_opts *opts; int status, n, jack =3D 1, i =3D 0, endpoint_descriptor_index =3D 0; =20 midi->gadget =3D cdev->gadget; @@ -883,6 +884,10 @@ static int f_midi_bind(struct usb_configuration *c, st= ruct usb_function *f) if (status < 0) goto fail_register; =20 + opts =3D container_of(f->fi, struct f_midi_opts, func_inst); + if (opts->interface_string) + midi_string_defs[STRING_FUNC_IDX].s =3D opts->interface_string; + /* maybe allocate device-global string ID */ us =3D usb_gstrings_attach(c->cdev, midi_strings, ARRAY_SIZE(midi_string_defs)); @@ -1178,59 +1183,60 @@ end: \ \ CONFIGFS_ATTR(f_midi_opts_, name); =20 +#define F_MIDI_OPT_STRING(name) \ +static ssize_t f_midi_opts_##name##_show(struct config_item *item, char *p= age) \ +{ \ + struct f_midi_opts *opts =3D to_f_midi_opts(item); \ + ssize_t result; \ + \ + mutex_lock(&opts->lock); \ + if (opts->name) { \ + result =3D strscpy(page, opts->name, PAGE_SIZE); \ + } else { \ + page[0] =3D 0; \ + result =3D 0; \ + } \ + \ + mutex_unlock(&opts->lock); \ + \ + return result; \ +} \ + \ +static ssize_t f_midi_opts_##name##_store(struct config_item *item, \ + const char *page, size_t len) \ +{ \ + struct f_midi_opts *opts =3D to_f_midi_opts(item); \ + int ret; \ + char *c; \ + \ + mutex_lock(&opts->lock); \ + if (opts->refcnt > 1) { \ + ret =3D -EBUSY; \ + goto end; \ + } \ + \ + c =3D kstrndup(page, len, GFP_KERNEL); \ + if (!c) { \ + ret =3D -ENOMEM; \ + goto end; \ + } \ + kfree(opts->name); \ + opts->name =3D c; \ + ret =3D len; \ +end: \ + mutex_unlock(&opts->lock); \ + return ret; \ +} \ + \ +CONFIGFS_ATTR(f_midi_opts_, name) + F_MIDI_OPT_SIGNED(index, true, SNDRV_CARDS); F_MIDI_OPT(buflen, false, 0); F_MIDI_OPT(qlen, false, 0); F_MIDI_OPT(in_ports, true, MAX_PORTS); F_MIDI_OPT(out_ports, true, MAX_PORTS); - -static ssize_t f_midi_opts_id_show(struct config_item *item, char *page) -{ - struct f_midi_opts *opts =3D to_f_midi_opts(item); - ssize_t result; - - mutex_lock(&opts->lock); - if (opts->id) { - result =3D strscpy(page, opts->id, PAGE_SIZE); - } else { - page[0] =3D 0; - result =3D 0; - } - - mutex_unlock(&opts->lock); - - return result; -} - -static ssize_t f_midi_opts_id_store(struct config_item *item, - const char *page, size_t len) -{ - struct f_midi_opts *opts =3D to_f_midi_opts(item); - int ret; - char *c; - - mutex_lock(&opts->lock); - if (opts->refcnt > 1) { - ret =3D -EBUSY; - goto end; - } - - c =3D kstrndup(page, len, GFP_KERNEL); - if (!c) { - ret =3D -ENOMEM; - goto end; - } - if (opts->id_allocated) - kfree(opts->id); - opts->id =3D c; - opts->id_allocated =3D true; - ret =3D len; -end: - mutex_unlock(&opts->lock); - return ret; -} - -CONFIGFS_ATTR(f_midi_opts_, id); +F_MIDI_OPT_STRING(id); +F_MIDI_OPT_STRING(interface_string); =20 static struct configfs_attribute *midi_attrs[] =3D { &f_midi_opts_attr_index, @@ -1239,6 +1245,7 @@ static struct configfs_attribute *midi_attrs[] =3D { &f_midi_opts_attr_in_ports, &f_midi_opts_attr_out_ports, &f_midi_opts_attr_id, + &f_midi_opts_attr_interface_string, NULL, }; =20 @@ -1262,8 +1269,8 @@ static void f_midi_free_inst(struct usb_function_inst= ance *f) mutex_unlock(&opts->lock); =20 if (free) { - if (opts->id_allocated) - kfree(opts->id); + kfree(opts->id); + kfree(opts->interface_string); kfree(opts); } } @@ -1279,7 +1286,8 @@ static struct usb_function_instance *f_midi_alloc_ins= t(void) mutex_init(&opts->lock); opts->func_inst.free_func_inst =3D f_midi_free_inst; opts->index =3D SNDRV_DEFAULT_IDX1; - opts->id =3D SNDRV_DEFAULT_STR1; + opts->id =3D NULL; + opts->interface_string =3D NULL; opts->buflen =3D 512; opts->qlen =3D 32; opts->in_ports =3D 1; diff --git a/drivers/usb/gadget/function/u_midi.h b/drivers/usb/gadget/func= tion/u_midi.h index 2e400b495cb8..41cb8aa73f09 100644 --- a/drivers/usb/gadget/function/u_midi.h +++ b/drivers/usb/gadget/function/u_midi.h @@ -19,7 +19,7 @@ struct f_midi_opts { struct usb_function_instance func_inst; int index; char *id; - bool id_allocated; + char *interface_string; unsigned int in_ports; unsigned int out_ports; unsigned int buflen; base-commit: 67a454e6b1c604555c04501c77b7fedc5d98a779 --=20 2.43.0