Commit 993a44fa authored by Yunhao Tian's avatar Yunhao Tian Committed by Greg Kroah-Hartman
Browse files

usb: gadget: f_uac2: allow changing interface name via configfs



This adds "function_name" configfs entry to change string value
of the iInterface field. This field will be shown in Windows' audio
settings panel, so being able to change it is useful. It will default
to "Source/Sink" just as before.

Signed-off-by: default avatarYunhao Tian <t123yh.xyz@gmail.com>
Link: https://lore.kernel.org/r/20220122112446.1415547-2-t123yh.xyz@gmail.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent dfb05b5d
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -32,4 +32,5 @@ Description:
					(in 1/256 dB)
		req_number		the number of pre-allocated requests
					for both capture and playback
		function_name		name of the interface
		=====================	=======================================
+1 −0
Original line number Diff line number Diff line
@@ -934,6 +934,7 @@ The uac1 function provides these attributes in its function directory:
	p_volume_res     playback volume control resolution (in 1/256 dB)
	req_number       the number of pre-allocated requests for both capture
	                 and playback
	function_name    name of the interface
	================ ====================================================

The attributes have sane default values.
+45 −1
Original line number Diff line number Diff line
@@ -107,7 +107,7 @@ enum {
};

static struct usb_string strings_fn[] = {
	[STR_ASSOC].s = "Source/Sink",
	/* [STR_ASSOC].s = DYNAMIC, */
	[STR_IF_CTRL].s = "Topology Control",
	[STR_CLKSRC_IN].s = "Input Clock",
	[STR_CLKSRC_OUT].s = "Output Clock",
@@ -984,6 +984,8 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
	if (ret)
		return ret;

	strings_fn[STR_ASSOC].s = uac2_opts->function_name;

	us = usb_gstrings_attach(cdev, fn_strings, ARRAY_SIZE(strings_fn));
	if (IS_ERR(us))
		return PTR_ERR(us);
@@ -1963,6 +1965,42 @@ end: \
									\
CONFIGFS_ATTR(f_uac2_opts_, name)

#define UAC2_ATTRIBUTE_STRING(name)					\
static ssize_t f_uac2_opts_##name##_show(struct config_item *item,	\
					 char *page)			\
{									\
	struct f_uac2_opts *opts = to_f_uac2_opts(item);		\
	int result;							\
									\
	mutex_lock(&opts->lock);					\
	result = snprintf(page, sizeof(opts->name), "%s", opts->name);	\
	mutex_unlock(&opts->lock);					\
									\
	return result;							\
}									\
									\
static ssize_t f_uac2_opts_##name##_store(struct config_item *item,	\
					  const char *page, size_t len)	\
{									\
	struct f_uac2_opts *opts = to_f_uac2_opts(item);		\
	int ret = 0;							\
									\
	mutex_lock(&opts->lock);					\
	if (opts->refcnt) {						\
		ret = -EBUSY;						\
		goto end;						\
	}								\
									\
	ret = snprintf(opts->name, min(sizeof(opts->name), len),	\
			"%s", page);					\
									\
end:									\
	mutex_unlock(&opts->lock);					\
	return ret;							\
}									\
									\
CONFIGFS_ATTR(f_uac2_opts_, name)

UAC2_ATTRIBUTE(u32, p_chmask);
UAC2_RATE_ATTRIBUTE(p_srate);
UAC2_ATTRIBUTE(u32, p_ssize);
@@ -1984,6 +2022,7 @@ UAC2_ATTRIBUTE(s16, c_volume_min);
UAC2_ATTRIBUTE(s16, c_volume_max);
UAC2_ATTRIBUTE(s16, c_volume_res);
UAC2_ATTRIBUTE(u32, fb_max);
UAC2_ATTRIBUTE_STRING(function_name);

static struct configfs_attribute *f_uac2_attrs[] = {
	&f_uac2_opts_attr_p_chmask,
@@ -2008,6 +2047,8 @@ static struct configfs_attribute *f_uac2_attrs[] = {
	&f_uac2_opts_attr_c_volume_max,
	&f_uac2_opts_attr_c_volume_res,

	&f_uac2_opts_attr_function_name,

	NULL,
};

@@ -2061,6 +2102,9 @@ static struct usb_function_instance *afunc_alloc_inst(void)

	opts->req_number = UAC2_DEF_REQ_NUM;
	opts->fb_max = FBACK_FAST_MAX;

	snprintf(opts->function_name, sizeof(opts->function_name), "Source/Sink");

	return &opts->func_inst;
}

+2 −0
Original line number Diff line number Diff line
@@ -59,6 +59,8 @@ struct f_uac2_opts {
	int				fb_max;
	bool			bound;

	char			function_name[32];

	struct mutex			lock;
	int				refcnt;
};