From de2eb28cdb76df9ce7587e1c6552b169069af4bb Mon Sep 17 00:00:00 2001 From: James Gruber Date: Thu, 14 Sep 2023 15:27:46 -0700 Subject: [PATCH] usb: gadget: f_uac2: allow changing terminal types through configfs Add "c_terminal_type" and "p_terminal_type" configfs entries in order to allow the user to change the capture and playback terminal type codes. These fields affect the type of audio device that Windows detects, so being able to modify this is useful when it would be advantageous for a gadget to be detected as something other than a generic speaker/microphone. The fields default to microphone for the capture type field and speaker for the playback type field as was the case before. Signed-off-by: James Gruber Link: https://lore.kernel.org/r/20230914222746.155126-1-jimmyjgruber@gmail.com Signed-off-by: Greg Kroah-Hartman --- .../ABI/testing/configfs-usb-gadget-uac2 | 2 ++ Documentation/usb/gadget-testing.rst | 2 ++ drivers/usb/gadget/function/f_uac2.c | 16 ++++++++++++++-- drivers/usb/gadget/function/u_uac2.h | 8 ++++++++ 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/Documentation/ABI/testing/configfs-usb-gadget-uac2 b/Documentation/ABI/testing/configfs-usb-gadget-uac2 index 3371c39f651db..a2bf4fd82a5b7 100644 --- a/Documentation/ABI/testing/configfs-usb-gadget-uac2 +++ b/Documentation/ABI/testing/configfs-usb-gadget-uac2 @@ -35,4 +35,6 @@ Description: req_number the number of pre-allocated requests for both capture and playback function_name name of the interface + c_terminal_type code of the capture terminal type + p_terminal_type code of the playback terminal type ===================== ======================================= diff --git a/Documentation/usb/gadget-testing.rst b/Documentation/usb/gadget-testing.rst index 394cd226bfaeb..29072c166d236 100644 --- a/Documentation/usb/gadget-testing.rst +++ b/Documentation/usb/gadget-testing.rst @@ -755,6 +755,8 @@ The uac2 function provides these attributes in its function directory: req_number the number of pre-allocated request for both capture and playback function_name name of the interface + c_terminal_type code of the capture terminal type + p_terminal_type code of the playback terminal type ================ ==================================================== 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 0219cd79493a7..f9a0f07a7476b 100644 --- a/drivers/usb/gadget/function/f_uac2.c +++ b/drivers/usb/gadget/function/f_uac2.c @@ -212,7 +212,7 @@ static struct uac2_input_terminal_descriptor io_in_it_desc = { .bDescriptorSubtype = UAC_INPUT_TERMINAL, /* .bTerminalID = DYNAMIC */ - .wTerminalType = cpu_to_le16(UAC_INPUT_TERMINAL_MICROPHONE), + /* .wTerminalType = DYNAMIC */ .bAssocTerminal = 0, /* .bCSourceID = DYNAMIC */ .iChannelNames = 0, @@ -240,7 +240,7 @@ static struct uac2_output_terminal_descriptor io_out_ot_desc = { .bDescriptorSubtype = UAC_OUTPUT_TERMINAL, /* .bTerminalID = DYNAMIC */ - .wTerminalType = cpu_to_le16(UAC_OUTPUT_TERMINAL_SPEAKER), + /* .wTerminalType = DYNAMIC */ .bAssocTerminal = 0, /* .bSourceID = DYNAMIC */ /* .bCSourceID = DYNAMIC */ @@ -977,6 +977,9 @@ static void setup_descriptor(struct f_uac2_opts *opts) iad_desc.bInterfaceCount++; } + io_in_it_desc.wTerminalType = cpu_to_le16(opts->c_terminal_type); + io_out_ot_desc.wTerminalType = cpu_to_le16(opts->p_terminal_type); + setup_headers(opts, fs_audio_desc, USB_SPEED_FULL); setup_headers(opts, hs_audio_desc, USB_SPEED_HIGH); setup_headers(opts, ss_audio_desc, USB_SPEED_SUPER); @@ -2095,6 +2098,9 @@ UAC2_ATTRIBUTE(s16, c_volume_res); UAC2_ATTRIBUTE(u32, fb_max); UAC2_ATTRIBUTE_STRING(function_name); +UAC2_ATTRIBUTE(s16, p_terminal_type); +UAC2_ATTRIBUTE(s16, c_terminal_type); + static struct configfs_attribute *f_uac2_attrs[] = { &f_uac2_opts_attr_p_chmask, &f_uac2_opts_attr_p_srate, @@ -2122,6 +2128,9 @@ static struct configfs_attribute *f_uac2_attrs[] = { &f_uac2_opts_attr_function_name, + &f_uac2_opts_attr_p_terminal_type, + &f_uac2_opts_attr_c_terminal_type, + NULL, }; @@ -2180,6 +2189,9 @@ static struct usb_function_instance *afunc_alloc_inst(void) snprintf(opts->function_name, sizeof(opts->function_name), "Source/Sink"); + opts->p_terminal_type = UAC2_DEF_P_TERM_TYPE; + opts->c_terminal_type = UAC2_DEF_C_TERM_TYPE; + return &opts->func_inst; } diff --git a/drivers/usb/gadget/function/u_uac2.h b/drivers/usb/gadget/function/u_uac2.h index 0510c9bad58db..5e81bdd6c5fba 100644 --- a/drivers/usb/gadget/function/u_uac2.h +++ b/drivers/usb/gadget/function/u_uac2.h @@ -35,6 +35,11 @@ #define UAC2_DEF_REQ_NUM 2 #define UAC2_DEF_INT_REQ_NUM 10 +#define UAC2_DEF_P_TERM_TYPE 0x301 + /* UAC_OUTPUT_TERMINAL_SPEAKER */ +#define UAC2_DEF_C_TERM_TYPE 0x201 + /* UAC_INPUT_TERMINAL_MICROPHONE*/ + struct f_uac2_opts { struct usb_function_instance func_inst; int p_chmask; @@ -65,6 +70,9 @@ struct f_uac2_opts { char function_name[32]; + s16 p_terminal_type; + s16 c_terminal_type; + struct mutex lock; int refcnt; };