Commit dfb05b5d authored by Yunhao Tian's avatar Yunhao Tian Committed by Greg Kroah-Hartman

usb: gadget: f_uac1: 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 "AC Interface" just as before if unchanged.
Signed-off-by: default avatarYunhao Tian <t123yh.xyz@gmail.com>
Link: https://lore.kernel.org/r/20220122112446.1415547-1-t123yh.xyz@gmail.comSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent d1d11dd1
...@@ -29,4 +29,5 @@ Description: ...@@ -29,4 +29,5 @@ Description:
(in 1/256 dB) (in 1/256 dB)
req_number the number of pre-allocated requests req_number the number of pre-allocated requests
for both capture and playback for both capture and playback
function_name name of the interface
===================== ======================================= ===================== =======================================
...@@ -745,6 +745,7 @@ The uac2 function provides these attributes in its function directory: ...@@ -745,6 +745,7 @@ The uac2 function provides these attributes in its function directory:
p_volume_res playback volume control resolution (in 1/256 dB) p_volume_res playback volume control resolution (in 1/256 dB)
req_number the number of pre-allocated request for both capture req_number the number of pre-allocated request for both capture
and playback and playback
function_name name of the interface
================ ==================================================== ================ ====================================================
The attributes have sane default values. The attributes have sane default values.
......
...@@ -309,7 +309,7 @@ enum { ...@@ -309,7 +309,7 @@ enum {
}; };
static struct usb_string strings_uac1[] = { static struct usb_string strings_uac1[] = {
[STR_AC_IF].s = "AC Interface", /* [STR_AC_IF].s = DYNAMIC, */
[STR_USB_OUT_IT].s = "Playback Input terminal", [STR_USB_OUT_IT].s = "Playback Input terminal",
[STR_USB_OUT_IT_CH_NAMES].s = "Playback Channels", [STR_USB_OUT_IT_CH_NAMES].s = "Playback Channels",
[STR_IO_OUT_OT].s = "Playback Output terminal", [STR_IO_OUT_OT].s = "Playback Output terminal",
...@@ -1192,6 +1192,8 @@ static int f_audio_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -1192,6 +1192,8 @@ static int f_audio_bind(struct usb_configuration *c, struct usb_function *f)
audio_opts = container_of(f->fi, struct f_uac1_opts, func_inst); audio_opts = container_of(f->fi, struct f_uac1_opts, func_inst);
strings_uac1[STR_AC_IF].s = audio_opts->function_name;
us = usb_gstrings_attach(cdev, uac1_strings, ARRAY_SIZE(strings_uac1)); us = usb_gstrings_attach(cdev, uac1_strings, ARRAY_SIZE(strings_uac1));
if (IS_ERR(us)) if (IS_ERR(us))
return PTR_ERR(us); return PTR_ERR(us);
...@@ -1551,6 +1553,42 @@ end: \ ...@@ -1551,6 +1553,42 @@ end: \
\ \
CONFIGFS_ATTR(f_uac1_opts_, name) CONFIGFS_ATTR(f_uac1_opts_, name)
#define UAC1_ATTRIBUTE_STRING(name) \
static ssize_t f_uac1_opts_##name##_show(struct config_item *item, \
char *page) \
{ \
struct f_uac1_opts *opts = to_f_uac1_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_uac1_opts_##name##_store(struct config_item *item, \
const char *page, size_t len) \
{ \
struct f_uac1_opts *opts = to_f_uac1_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_uac1_opts_, name)
UAC1_ATTRIBUTE(u32, c_chmask); UAC1_ATTRIBUTE(u32, c_chmask);
UAC1_RATE_ATTRIBUTE(c_srate); UAC1_RATE_ATTRIBUTE(c_srate);
UAC1_ATTRIBUTE(u32, c_ssize); UAC1_ATTRIBUTE(u32, c_ssize);
...@@ -1570,6 +1608,7 @@ UAC1_ATTRIBUTE(bool, c_volume_present); ...@@ -1570,6 +1608,7 @@ UAC1_ATTRIBUTE(bool, c_volume_present);
UAC1_ATTRIBUTE(s16, c_volume_min); UAC1_ATTRIBUTE(s16, c_volume_min);
UAC1_ATTRIBUTE(s16, c_volume_max); UAC1_ATTRIBUTE(s16, c_volume_max);
UAC1_ATTRIBUTE(s16, c_volume_res); UAC1_ATTRIBUTE(s16, c_volume_res);
UAC1_ATTRIBUTE_STRING(function_name);
static struct configfs_attribute *f_uac1_attrs[] = { static struct configfs_attribute *f_uac1_attrs[] = {
&f_uac1_opts_attr_c_chmask, &f_uac1_opts_attr_c_chmask,
...@@ -1592,6 +1631,8 @@ static struct configfs_attribute *f_uac1_attrs[] = { ...@@ -1592,6 +1631,8 @@ static struct configfs_attribute *f_uac1_attrs[] = {
&f_uac1_opts_attr_c_volume_max, &f_uac1_opts_attr_c_volume_max,
&f_uac1_opts_attr_c_volume_res, &f_uac1_opts_attr_c_volume_res,
&f_uac1_opts_attr_function_name,
NULL, NULL,
}; };
...@@ -1643,6 +1684,9 @@ static struct usb_function_instance *f_audio_alloc_inst(void) ...@@ -1643,6 +1684,9 @@ static struct usb_function_instance *f_audio_alloc_inst(void)
opts->c_volume_res = UAC1_DEF_RES_DB; opts->c_volume_res = UAC1_DEF_RES_DB;
opts->req_number = UAC1_DEF_REQ_NUM; opts->req_number = UAC1_DEF_REQ_NUM;
snprintf(opts->function_name, sizeof(opts->function_name), "AC Interface");
return &opts->func_inst; return &opts->func_inst;
} }
......
...@@ -52,6 +52,8 @@ struct f_uac1_opts { ...@@ -52,6 +52,8 @@ struct f_uac1_opts {
int req_number; int req_number;
unsigned bound:1; unsigned bound:1;
char function_name[32];
struct mutex lock; struct mutex lock;
int refcnt; int refcnt;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment