Commit 1c937381 authored by Victor Krawiec's avatar Victor Krawiec Committed by Greg Kroah-Hartman
Browse files

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: default avatarVictor Krawiec <victor.krawiec@arturia.com>
Reviewed-by: default avatarTakashi Iwai <tiwai@suse.de>
Link: https://patch.msgid.link/20251209164006.143219-1-victor.krawiec@arturia.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 4dee13db
Loading
Loading
Loading
Loading
+9 −8
Original line number Diff line number Diff line
@@ -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
		==========	====================================
		interface_string	USB AudioControl interface string
		================	====================================
+9 −8
Original line number Diff line number Diff line
@@ -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
	=============== ====================================
	interface_string USB AudioControl interface string
	================ ====================================

Testing the MIDI function
-------------------------
+59 −51
Original line number Diff line number Diff line
@@ -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->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;
+1 −1
Original line number Diff line number Diff line
@@ -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;