Re: uac2/hid gadget issues on Win10 hosts
From: Pavel Hofman <hidden>
Date: 2021-08-23 13:17:28
Hi Tak, Dne 23. 08. 21 v 13:45 N. Chen napsal(a):
quoted hunk ↗ jump to hunk
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.cb/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_descriptorio_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_descriptorio_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, }; --
There is a problem with max packet size calculation for EP-IN. It has been discussed here recently https://www.spinics.net/lists/linux-usb/msg214615.html The simple change in the post above fixed Win10 enumeration for me and another tester. Also, there is a problem with feedback value calculation which Win10 ignores and keeps sending the same amount of samples. The fix is to send number of samples per the actual packet, not per microframe for USB2. I have not posted the attached patch as the whole patchset will most likely be reverted for 5.15 https://www.spinics.net/lists/linux-usb/msg216042.html and I wanted to wait till the situation works out to avoid confusion. In the attached patch just change the ->c_srate_active to ->c_srate (the patch is on top of more changes for switching between multiple samplerates). Best regards, Pavel.
Attachments
- 0009-usb-gadget-u_audio-EP-OUT-bInterval-in-fback-frequen.patch [text/x-patch] 2666 bytes · preview