Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Yunhao Tian and committed by
Greg Kroah-Hartman
993a44fa dfb05b5d

+49 -1
+1
Documentation/ABI/testing/configfs-usb-gadget-uac2
··· 32 32 (in 1/256 dB) 33 33 req_number the number of pre-allocated requests 34 34 for both capture and playback 35 + function_name name of the interface 35 36 ===================== =======================================
+1
Documentation/usb/gadget-testing.rst
··· 934 934 p_volume_res playback volume control resolution (in 1/256 dB) 935 935 req_number the number of pre-allocated requests for both capture 936 936 and playback 937 + function_name name of the interface 937 938 ================ ==================================================== 938 939 939 940 The attributes have sane default values.
+45 -1
drivers/usb/gadget/function/f_uac2.c
··· 107 107 }; 108 108 109 109 static struct usb_string strings_fn[] = { 110 - [STR_ASSOC].s = "Source/Sink", 110 + /* [STR_ASSOC].s = DYNAMIC, */ 111 111 [STR_IF_CTRL].s = "Topology Control", 112 112 [STR_CLKSRC_IN].s = "Input Clock", 113 113 [STR_CLKSRC_OUT].s = "Output Clock", ··· 983 983 ret = afunc_validate_opts(agdev, dev); 984 984 if (ret) 985 985 return ret; 986 + 987 + strings_fn[STR_ASSOC].s = uac2_opts->function_name; 986 988 987 989 us = usb_gstrings_attach(cdev, fn_strings, ARRAY_SIZE(strings_fn)); 988 990 if (IS_ERR(us)) ··· 1965 1963 \ 1966 1964 CONFIGFS_ATTR(f_uac2_opts_, name) 1967 1965 1966 + #define UAC2_ATTRIBUTE_STRING(name) \ 1967 + static ssize_t f_uac2_opts_##name##_show(struct config_item *item, \ 1968 + char *page) \ 1969 + { \ 1970 + struct f_uac2_opts *opts = to_f_uac2_opts(item); \ 1971 + int result; \ 1972 + \ 1973 + mutex_lock(&opts->lock); \ 1974 + result = snprintf(page, sizeof(opts->name), "%s", opts->name); \ 1975 + mutex_unlock(&opts->lock); \ 1976 + \ 1977 + return result; \ 1978 + } \ 1979 + \ 1980 + static ssize_t f_uac2_opts_##name##_store(struct config_item *item, \ 1981 + const char *page, size_t len) \ 1982 + { \ 1983 + struct f_uac2_opts *opts = to_f_uac2_opts(item); \ 1984 + int ret = 0; \ 1985 + \ 1986 + mutex_lock(&opts->lock); \ 1987 + if (opts->refcnt) { \ 1988 + ret = -EBUSY; \ 1989 + goto end; \ 1990 + } \ 1991 + \ 1992 + ret = snprintf(opts->name, min(sizeof(opts->name), len), \ 1993 + "%s", page); \ 1994 + \ 1995 + end: \ 1996 + mutex_unlock(&opts->lock); \ 1997 + return ret; \ 1998 + } \ 1999 + \ 2000 + CONFIGFS_ATTR(f_uac2_opts_, name) 2001 + 1968 2002 UAC2_ATTRIBUTE(u32, p_chmask); 1969 2003 UAC2_RATE_ATTRIBUTE(p_srate); 1970 2004 UAC2_ATTRIBUTE(u32, p_ssize); ··· 2022 1984 UAC2_ATTRIBUTE(s16, c_volume_max); 2023 1985 UAC2_ATTRIBUTE(s16, c_volume_res); 2024 1986 UAC2_ATTRIBUTE(u32, fb_max); 1987 + UAC2_ATTRIBUTE_STRING(function_name); 2025 1988 2026 1989 static struct configfs_attribute *f_uac2_attrs[] = { 2027 1990 &f_uac2_opts_attr_p_chmask, ··· 2046 2007 &f_uac2_opts_attr_c_volume_min, 2047 2008 &f_uac2_opts_attr_c_volume_max, 2048 2009 &f_uac2_opts_attr_c_volume_res, 2010 + 2011 + &f_uac2_opts_attr_function_name, 2049 2012 2050 2013 NULL, 2051 2014 }; ··· 2102 2061 2103 2062 opts->req_number = UAC2_DEF_REQ_NUM; 2104 2063 opts->fb_max = FBACK_FAST_MAX; 2064 + 2065 + snprintf(opts->function_name, sizeof(opts->function_name), "Source/Sink"); 2066 + 2105 2067 return &opts->func_inst; 2106 2068 } 2107 2069
+2
drivers/usb/gadget/function/u_uac2.h
··· 59 59 int fb_max; 60 60 bool bound; 61 61 62 + char function_name[32]; 63 + 62 64 struct mutex lock; 63 65 int refcnt; 64 66 };