From: Victor Krawiec Date: Tue, 9 Dec 2025 16:40:06 +0000 (+0100) Subject: usb: gadget: f_midi: allow customizing the USB MIDI interface string through configfs X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1c93738177d3a94d51dcb1c3ea41967f3fe946ba;p=thirdparty%2Fkernel%2Flinux.git usb: gadget: f_midi: allow customizing the USB MIDI interface string through configfs 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 Link: https://patch.msgid.link/20251209164006.143219-1-victor.krawiec@arturia.com Signed-off-by: Greg Kroah-Hartman --- diff --git a/Documentation/ABI/testing/configfs-usb-gadget-midi b/Documentation/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: - ========== ==================================== - 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 - ========== ==================================== + ================ ==================================== + 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 + ================ ==================================== diff --git a/Documentation/usb/gadget-testing.rst b/Documentation/usb/gadget-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: - =============== ==================================== - 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 - =============== ==================================== + ================ ==================================== + 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 + ================ ==================================== Testing the MIDI function ------------------------- diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/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, struct usb_function *f) struct usb_composite_dev *cdev = c->cdev; struct f_midi *midi = func_to_midi(f); struct usb_string *us; + struct f_midi_opts *opts; int status, n, jack = 1, i = 0, endpoint_descriptor_index = 0; midi->gadget = cdev->gadget; @@ -883,6 +884,10 @@ static int f_midi_bind(struct usb_configuration *c, struct usb_function *f) if (status < 0) goto fail_register; + opts = container_of(f->fi, struct f_midi_opts, func_inst); + if (opts->interface_string) + midi_string_defs[STRING_FUNC_IDX].s = opts->interface_string; + /* maybe allocate device-global string ID */ us = usb_gstrings_attach(c->cdev, midi_strings, ARRAY_SIZE(midi_string_defs)); @@ -1178,59 +1183,60 @@ end: \ \ CONFIGFS_ATTR(f_midi_opts_, name); +#define F_MIDI_OPT_STRING(name) \ +static ssize_t f_midi_opts_##name##_show(struct config_item *item, char *page) \ +{ \ + struct f_midi_opts *opts = to_f_midi_opts(item); \ + ssize_t result; \ + \ + mutex_lock(&opts->lock); \ + if (opts->name) { \ + result = strscpy(page, opts->name, PAGE_SIZE); \ + } else { \ + page[0] = 0; \ + result = 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 = to_f_midi_opts(item); \ + int ret; \ + char *c; \ + \ + mutex_lock(&opts->lock); \ + if (opts->refcnt > 1) { \ + ret = -EBUSY; \ + goto end; \ + } \ + \ + c = kstrndup(page, len, GFP_KERNEL); \ + if (!c) { \ + ret = -ENOMEM; \ + goto end; \ + } \ + kfree(opts->name); \ + opts->name = c; \ + ret = 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 = to_f_midi_opts(item); - ssize_t result; - - mutex_lock(&opts->lock); - if (opts->id) { - result = strscpy(page, opts->id, PAGE_SIZE); - } else { - page[0] = 0; - result = 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 = to_f_midi_opts(item); - int ret; - char *c; - - mutex_lock(&opts->lock); - if (opts->refcnt > 1) { - ret = -EBUSY; - goto end; - } - - c = kstrndup(page, len, GFP_KERNEL); - if (!c) { - ret = -ENOMEM; - goto end; - } - if (opts->id_allocated) - kfree(opts->id); - opts->id = c; - opts->id_allocated = true; - ret = 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); static struct configfs_attribute *midi_attrs[] = { &f_midi_opts_attr_index, @@ -1239,6 +1245,7 @@ static struct configfs_attribute *midi_attrs[] = { &f_midi_opts_attr_in_ports, &f_midi_opts_attr_out_ports, &f_midi_opts_attr_id, + &f_midi_opts_attr_interface_string, NULL, }; @@ -1262,8 +1269,8 @@ static void f_midi_free_inst(struct usb_function_instance *f) mutex_unlock(&opts->lock); 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_inst(void) mutex_init(&opts->lock); opts->func_inst.free_func_inst = f_midi_free_inst; opts->index = SNDRV_DEFAULT_IDX1; - opts->id = SNDRV_DEFAULT_STR1; + opts->id = NULL; + opts->interface_string = NULL; opts->buflen = 512; opts->qlen = 32; opts->in_ports = 1; diff --git a/drivers/usb/gadget/function/u_midi.h b/drivers/usb/gadget/function/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;