I'm attempting to create a composite gadget device that uses uac2 and hid functions (speakerphone), using the latest kernel branch (rpi-5.14.y) on a rpi4 device. Windows10 host does not recognize the device as an audio usb device. In order to get it recognized, I had to use c_sync in adaptive mode, as well as make the following adjustments: diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c index ae29ff2b2b68..74a221939ca0 100644 --- a/drivers/usb/gadget/function/f_uac2.c +++ b/drivers/usb/gadget/function/f_uac2.c @@ -177,7 +177,7 @@ static struct uac2_input_terminal_descriptor io_in_it_desc = { .bDescriptorSubtype = UAC_INPUT_TERMINAL, /* .bTerminalID = DYNAMIC */ - .wTerminalType = cpu_to_le16(UAC_INPUT_TERMINAL_UNDEFINED), + .wTerminalType = cpu_to_le16(UAC_INPUT_TERMINAL_MICROPHONE), .bAssocTerminal = 0, /* .bCSourceID = DYNAMIC */ .iChannelNames = 0, @@ -205,7 +205,7 @@ static struct uac2_output_terminal_descriptor io_out_ot_desc = { .bDescriptorSubtype = UAC_OUTPUT_TERMINAL, /* .bTerminalID = DYNAMIC */ - .wTerminalType = cpu_to_le16(UAC_OUTPUT_TERMINAL_UNDEFINED), + .wTerminalType = cpu_to_le16(UAC_OUTPUT_TERMINAL_SPEAKER), .bAssocTerminal = 0, /* .bSourceID = DYNAMIC */ /* .bCSourceID = DYNAMIC */ @@ -216,7 +216,7 @@ static struct uac2_ac_header_descriptor ac_hdr_desc = { .bLength = sizeof ac_hdr_desc, .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubtype = UAC_MS_HEADER, + .bDescriptorSubtype = UAC_HEADER, .bcdADC = cpu_to_le16(0x200), .bCategory = UAC2_FUNCTION_IO_BOX, /* .wTotalLength = DYNAMIC */ @@ -400,7 +400,7 @@ static struct usb_endpoint_descriptor fs_epin_desc = { .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC, + .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_SYNC, /* .wMaxPacketSize = DYNAMIC */ .bInterval = 1, }; @@ -409,7 +409,7 @@ static struct usb_endpoint_descriptor hs_epin_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, - .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC, + .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_SYNC, /* .wMaxPacketSize = DYNAMIC */ .bInterval = 4, }; @@ -419,7 +419,7 @@ static struct usb_endpoint_descriptor ss_epin_desc = { .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC, + .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_SYNC, /* .wMaxPacketSize = DYNAMIC */ .bInterval = 4, }; -- For the hid function report descriptor, I used the telephony led page with off-hook, mute and ring. I was not able to get any hid packets when tested using Teams. I made the following change, and it allowed me to get the ring hid alone, but not the led and the off-hook, so I guess this hack is incorrect: diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c index bb476e121eae..10882e18cb88 100644 --- a/drivers/usb/gadget/function/f_hid.c +++ b/drivers/usb/gadget/function/f_hid.c @@ -549,7 +549,9 @@ static int hidg_setup(struct usb_function *f, case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8 | HID_REQ_SET_REPORT): VDBG(cdev, "set_report | wLength=%d\n", ctrl->wLength); - goto stall; + req->context = hidg; + req->complete = hidg_set_report_complete; + goto respond; break; case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8 -- I'm aware that the aforementioned changes to uac2 function might be incorrect as well, but it allowed me to get through the first hurdle. I have no objections to making it more correct. I especially value an opinion on this matter from someone that has worked with Windows10 hosts before, as it is a specific issue with this OS (it works well for Ubuntu hosts, yet to be tested on Macs). Thanks, Tak