summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYunhao Tian <t123yh.xyz@gmail.com>2022-01-22 19:24:41 +0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2022-01-26 14:10:44 +0100
commit993a44fa85c1ea5989fb5c46236ca2e3cfd71b78 (patch)
tree46c6d2a9c6c7de6e7481524261aae193624bef56
parentdfb05b5dc3afd90e564b69b88ff6be6947a0f32f (diff)
downloadlinux-993a44fa85c1ea5989fb5c46236ca2e3cfd71b78.tar.bz2
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: Yunhao Tian <t123yh.xyz@gmail.com> Link: https://lore.kernel.org/r/20220122112446.1415547-2-t123yh.xyz@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--Documentation/ABI/testing/configfs-usb-gadget-uac21
-rw-r--r--Documentation/usb/gadget-testing.rst1
-rw-r--r--drivers/usb/gadget/function/f_uac2.c46
-rw-r--r--drivers/usb/gadget/function/u_uac2.h2
4 files changed, 49 insertions, 1 deletions
diff --git a/Documentation/ABI/testing/configfs-usb-gadget-uac2 b/Documentation/ABI/testing/configfs-usb-gadget-uac2
index 9d2f59ab9701..4c6bf63fcb22 100644
--- a/Documentation/ABI/testing/configfs-usb-gadget-uac2
+++ b/Documentation/ABI/testing/configfs-usb-gadget-uac2
@@ -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
===================== =======================================
diff --git a/Documentation/usb/gadget-testing.rst b/Documentation/usb/gadget-testing.rst
index 1792bd88f666..6e8fdfaf19e7 100644
--- a/Documentation/usb/gadget-testing.rst
+++ b/Documentation/usb/gadget-testing.rst
@@ -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.
diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c
index 3e6339439b88..d874e0d34188 100644
--- a/drivers/usb/gadget/function/f_uac2.c
+++ b/drivers/usb/gadget/function/f_uac2.c
@@ -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;
}
diff --git a/drivers/usb/gadget/function/u_uac2.h b/drivers/usb/gadget/function/u_uac2.h
index 6bfcf6d0e863..ed96c7c853e4 100644
--- a/drivers/usb/gadget/function/u_uac2.h
+++ b/drivers/usb/gadget/function/u_uac2.h
@@ -59,6 +59,8 @@ struct f_uac2_opts {
int fb_max;
bool bound;
+ char function_name[32];
+
struct mutex lock;
int refcnt;
};