linux-usb-gadgets / libusbgx

C library encapsulating the Linux kernel USB gadget configfs userspace API functionality
GNU General Public License v2.0
216 stars 72 forks source link

UAC2 gadget not recognized on Windows 10. #24

Closed robiwano closed 6 years ago

robiwano commented 6 years ago

Using gadget-import (initial config retrieved via gadget-uac2 + gadget-export) to initialize a UAC2 audio device, but it fails to load completely on Windows 10. This is the config file (modifications done to initial config market with !!!):

attrs :
{
    bcdUSB = 0x200;
    bDeviceClass = 0x1; !!!
    bDeviceSubClass = 0x0; !!!
    bDeviceProtocol = 0x20; !!!
    bMaxPacketSize0 = 0x40;
    idVendor = 0x1D6B;
    idProduct = 0x104;
    bcdDevice = 0x100; !!!
};
os_descs :
{
    use = 1; !!!
    qw_sign = "MSFT100"; !!!
    b_vendor_code = 0xcd; !!!
};
strings = (
    {
        lang = 0x0409;
        manufacturer = "Foo Inc.";
        product = "Bar Gadget";
        serialnumber = "0123456789";
    } );
functions :
{
    uac2_usb0 :
    {
        instance = "usb0";
        type = "uac2";
        attrs :
        {
            c_chmask = 3;
            c_srate = 48000; !!!
            c_ssize = 4;
            p_chmask = 3;
            p_srate = 48000; !!!
            p_ssize = 4;
        };
        os_descs = ( );
    };
};
configs = (
    {
        id = 1;
        name = "The only one";
        attrs :
        {
            bmAttributes = 0x80;
            bMaxPower = 0x2;
        };
        strings = (
            {
                lang = 0x0409;
                configuration = "1xUAC2";
            } );
        functions = (
            {
                name = "some_name";
                function = "uac2_usb0";
            } );
    } );

See descriptor dump in next comment.

Microsoft OS Descriptor is not available. Error code: 0x0000001F

but still osvc is set to 01cd in Windows Registry...

What is needed to get it recognized by Windows 10 ?

robiwano commented 6 years ago

Information for device Bar Gadget (VID=0x1D6B PID=0x0104):

*** ERROR: Descriptor has errors! ***

Connection Information:
------------------------------
Device current bus speed: HighSpeed
Device supports USB 1.1 specification
Device supports USB 2.0 specification
Device address: 0x0014
Current configuration value: 0x00
Number of open pipes: 0

Device Descriptor:
------------------------------
0x12    bLength
0x01    bDescriptorType
0x0200  bcdUSB
0x01    bDeviceClass   (Audio Device Class)
0x00    bDeviceSubClass   
0x20    bDeviceProtocol   
0x40    bMaxPacketSize0   (64 bytes)
0x1D6B  idVendor
0x0104  idProduct
0x0100  bcdDevice
0x01    iManufacturer   "Foo Inc."
0x02    iProduct   "Bar Gadget"
0x03    iSerialNumber   "0123456789"
0x01    bNumConfigurations

Device Qualifier Descriptor:
------------------------------
0x0A    bLength
0x06    bDescriptorType
0x0200  bcdUSB
0x01    bDeviceClass   (Audio Device Class)
0x00    bDeviceSubClass   
0x20    bDeviceProtocol   
0x40    bMaxPacketSize0   (64 bytes)
0x01    bNumConfigurations 
0x00    bReserved 

Configuration Descriptor:
------------------------------
0x09    bLength
0x02    bDescriptorType
0x00DB  wTotalLength   (219 bytes)
0x03    bNumInterfaces
0x01    bConfigurationValue
0x04    iConfiguration   "1xUAC2"
0x80    bmAttributes   (Bus-powered Device)
0x01    bMaxPower      (2 mA)

Interface Association Descriptor:
------------------------------
0x08    bLength
0x0B    bDescriptorType
0x00    bFirstInterface
0x03    bInterfaceCount
0x01    bFunctionClass   (Audio Device Class)
0x00    bFunctionSubClass   
0x20    bFunctionProtocol   
0x05    iFunction   "Source/Sink"

Interface Descriptor:
------------------------------
0x09    bLength
0x04    bDescriptorType
0x00    bInterfaceNumber
0x00    bAlternateSetting
0x00    bNumEndPoints
0x01    bInterfaceClass      (Audio Device Class)
0x01    bInterfaceSubClass   (Audio Control Interface)
0x20    bInterfaceProtocol   
0x06    iInterface   "Topology Control"

AC Interface Header Descriptor:
------------------------------
0x09    bLength
0x24    bDescriptorType
0x01    bDescriptorSubtype
0x0200  bcdADC
0x08    bCategory   (IO_BOX)
0x004A  wTotalLength   (74 bytes)
*** ERROR: Invalid wTotalLength 0x004A, should be 0x0053.
0x00    bmControls

AC Clock Source Descriptor:
------------------------------
0x08    bLength
0x24    bDescriptorType
0x0A    bDescriptorSubtype
0x06    bClockID
0x01    bmAttributes
0x01    bmControls
0x00    bAssocTerminal
0x07    iClockSource   "48000Hz"

AC Clock Source Descriptor:
------------------------------
0x08    bLength
0x24    bDescriptorType
0x0A    bDescriptorSubtype
0x05    bClockID
0x01    bmAttributes
0x01    bmControls
0x00    bAssocTerminal
0x08    iClockSource   "48000Hz"

AC Input Terminal Descriptor:
------------------------------
0x11    bLength
0x24    bDescriptorType
0x02    bDescriptorSubtype
0x01    bTerminalID
0x0101  wTerminalType   (USB Streaming)
0x00    bAssocTerminal
0x05    bCSourceID
0x02    bNrChannels   (2 channels)
0x00000003  bmChannelConfig
0x00    iChannelNames
0x03    bmControls
0x09    iTerminal   "USBH Out"

AC Input Terminal Descriptor:
------------------------------
0x11    bLength
0x24    bDescriptorType
0x02    bDescriptorSubtype
0x02    bTerminalID
0x0200  wTerminalType   (Input Undefined)
0x00    bAssocTerminal
0x06    bCSourceID
0x02    bNrChannels   (2 channels)
0x00000003  bmChannelConfig
0x00    iChannelNames
0x03    bmControls
0x0A    iTerminal   "USBD Out"

AC Output Terminal Descriptor:
------------------------------
0x0C    bLength
0x24    bDescriptorType
0x03    bDescriptorSubtype
0x04    bTerminalID
0x0101  wTerminalType   (USB Streaming)
0x00    bAssocTerminal
0x02    bSourceID
0x06    bCSourceID
0x0003  bmControls
0x0B    iTerminal   "USBH In"

AC Output Terminal Descriptor:
------------------------------
0x0C    bLength
0x24    bDescriptorType
0x03    bDescriptorSubtype
0x03    bTerminalID
0x0300  wTerminalType   (Output Undefined)
0x00    bAssocTerminal
0x01    bSourceID
0x05    bCSourceID
0x0003  bmControls
0x0C    iTerminal   "USBD In"

Interface Descriptor:
------------------------------
0x09    bLength
0x04    bDescriptorType
0x01    bInterfaceNumber
0x00    bAlternateSetting
0x00    bNumEndPoints
0x01    bInterfaceClass      (Audio Device Class)
0x02    bInterfaceSubClass   (Audio Streaming Interface)
0x20    bInterfaceProtocol   
0x0D    iInterface   "Playback Inactive"

Interface Descriptor:
------------------------------
0x09    bLength
0x04    bDescriptorType
0x01    bInterfaceNumber
0x01    bAlternateSetting
0x01    bNumEndPoints
0x01    bInterfaceClass      (Audio Device Class)
0x02    bInterfaceSubClass   (Audio Streaming Interface)
0x20    bInterfaceProtocol   
0x0E    iInterface   "Playback Active"

AS Interface Descriptor:
------------------------------
0x10    bLength
0x24    bDescriptorType
0x01    bDescriptorSubtype
0x01    bTerminalLink
0x00    bmControls
0x01    bFormatType   (FORMAT_TYPE_1)
0x00000001  bmFormats
0x02    bNrChannels   (2 channels)
0x00000003  bmChannelConfig
0x00    iChannelNames

AS Format Type 1 Descriptor:
------------------------------
0x06    bLength
0x24    bDescriptorType
0x02    bDescriptorSubtype
0x01    bFormatType   (FORMAT_TYPE_1)
0x04    bSubslotSize
0x20    bBitResolution   (32 bits per sample)

Endpoint Descriptor:
------------------------------
0x07    bLength
0x05    bDescriptorType
0x01    bEndpointAddress  (OUT endpoint 1)
0x05    bmAttributes      (Transfer: Isochronous / Synch: Asynchronous / Usage: Data)
0x0180  wMaxPacketSize    (1 x 384 bytes) 
0x04    bInterval

AS Isochronous Data Endpoint Descriptor:
------------------------------
0x08    bLength
0x25    bDescriptorType
0x01    bDescriptorSubtype
0x00    bmAttributes
0x00    bmControls
0x00    bLockDelayUnits   (undefined)
0x0000  wLockDelay

Interface Descriptor:
------------------------------
0x09    bLength
0x04    bDescriptorType
0x02    bInterfaceNumber
0x00    bAlternateSetting
0x00    bNumEndPoints
0x01    bInterfaceClass      (Audio Device Class)
0x02    bInterfaceSubClass   (Audio Streaming Interface)
0x20    bInterfaceProtocol   
0x0F    iInterface   "Capture Inactive"

Interface Descriptor:
------------------------------
0x09    bLength
0x04    bDescriptorType
0x02    bInterfaceNumber
0x01    bAlternateSetting
0x01    bNumEndPoints
0x01    bInterfaceClass      (Audio Device Class)
0x02    bInterfaceSubClass   (Audio Streaming Interface)
0x20    bInterfaceProtocol   
0x10    iInterface   "Capture Active"

AS Interface Descriptor:
------------------------------
0x10    bLength
0x24    bDescriptorType
0x01    bDescriptorSubtype
0x04    bTerminalLink
0x00    bmControls
0x01    bFormatType   (FORMAT_TYPE_1)
0x00000001  bmFormats
0x02    bNrChannels   (2 channels)
0x00000003  bmChannelConfig
0x00    iChannelNames

AS Format Type 1 Descriptor:
------------------------------
0x06    bLength
0x24    bDescriptorType
0x02    bDescriptorSubtype
0x01    bFormatType   (FORMAT_TYPE_1)
0x04    bSubslotSize
0x20    bBitResolution   (32 bits per sample)

Endpoint Descriptor:
------------------------------
0x07    bLength
0x05    bDescriptorType
0x81    bEndpointAddress  (IN endpoint 1)
0x05    bmAttributes      (Transfer: Isochronous / Synch: Asynchronous / Usage: Data)
0x0180  wMaxPacketSize    (1 x 384 bytes) 
0x04    bInterval

AS Isochronous Data Endpoint Descriptor:
------------------------------
0x08    bLength
0x25    bDescriptorType
0x01    bDescriptorSubtype
0x00    bmAttributes
0x00    bmControls
0x00    bLockDelayUnits   (undefined)
0x0000  wLockDelay

Other Speed Configuration Descriptor:
------------------------------
0x09    bLength
0x07    bDescriptorType
0x00DB  wTotalLength   (219 bytes)
0x03    bNumInterfaces
0x01    bConfigurationValue
0x04    iConfiguration   "1xUAC2"
0x80    bmAttributes   (Bus-powered Device)
0x01    bMaxPower      (2 mA)

Interface Association Descriptor:
------------------------------
0x08    bLength
0x0B    bDescriptorType
0x00    bFirstInterface
0x03    bInterfaceCount
0x01    bFunctionClass   (Audio Device Class)
0x00    bFunctionSubClass   
0x20    bFunctionProtocol   
0x05    iFunction   "Source/Sink"

Interface Descriptor:
------------------------------
0x09    bLength
0x04    bDescriptorType
0x00    bInterfaceNumber
0x00    bAlternateSetting
0x00    bNumEndPoints
0x01    bInterfaceClass      (Audio Device Class)
0x01    bInterfaceSubClass   (Audio Control Interface)
0x20    bInterfaceProtocol   
0x06    iInterface   "Topology Control"

AC Interface Header Descriptor:
------------------------------
0x09    bLength
0x24    bDescriptorType
0x01    bDescriptorSubtype
0x0200  bcdADC
0x08    bCategory   (IO_BOX)
0x004A  wTotalLength   (74 bytes)
*** ERROR: Invalid wTotalLength 0x004A, should be 0x0053.
0x00    bmControls

AC Clock Source Descriptor:
------------------------------
0x08    bLength
0x24    bDescriptorType
0x0A    bDescriptorSubtype
0x06    bClockID
0x01    bmAttributes
0x01    bmControls
0x00    bAssocTerminal
0x07    iClockSource   "48000Hz"

AC Clock Source Descriptor:
------------------------------
0x08    bLength
0x24    bDescriptorType
0x0A    bDescriptorSubtype
0x05    bClockID
0x01    bmAttributes
0x01    bmControls
0x00    bAssocTerminal
0x08    iClockSource   "48000Hz"

AC Input Terminal Descriptor:
------------------------------
0x11    bLength
0x24    bDescriptorType
0x02    bDescriptorSubtype
0x01    bTerminalID
0x0101  wTerminalType   (USB Streaming)
0x00    bAssocTerminal
0x05    bCSourceID
0x02    bNrChannels   (2 channels)
0x00000003  bmChannelConfig
0x00    iChannelNames
0x03    bmControls
0x09    iTerminal   "USBH Out"

AC Input Terminal Descriptor:
------------------------------
0x11    bLength
0x24    bDescriptorType
0x02    bDescriptorSubtype
0x02    bTerminalID
0x0200  wTerminalType   (Input Undefined)
0x00    bAssocTerminal
0x06    bCSourceID
0x02    bNrChannels   (2 channels)
0x00000003  bmChannelConfig
0x00    iChannelNames
0x03    bmControls
0x0A    iTerminal   "USBD Out"

AC Output Terminal Descriptor:
------------------------------
0x0C    bLength
0x24    bDescriptorType
0x03    bDescriptorSubtype
0x04    bTerminalID
0x0101  wTerminalType   (USB Streaming)
0x00    bAssocTerminal
0x02    bSourceID
0x06    bCSourceID
0x0003  bmControls
0x0B    iTerminal   "USBH In"

AC Output Terminal Descriptor:
------------------------------
0x0C    bLength
0x24    bDescriptorType
0x03    bDescriptorSubtype
0x03    bTerminalID
0x0300  wTerminalType   (Output Undefined)
0x00    bAssocTerminal
0x01    bSourceID
0x05    bCSourceID
0x0003  bmControls
0x0C    iTerminal   "USBD In"

Interface Descriptor:
------------------------------
0x09    bLength
0x04    bDescriptorType
0x01    bInterfaceNumber
0x00    bAlternateSetting
0x00    bNumEndPoints
0x01    bInterfaceClass      (Audio Device Class)
0x02    bInterfaceSubClass   (Audio Streaming Interface)
0x20    bInterfaceProtocol   
0x0D    iInterface   "Playback Inactive"

Interface Descriptor:
------------------------------
0x09    bLength
0x04    bDescriptorType
0x01    bInterfaceNumber
0x01    bAlternateSetting
0x01    bNumEndPoints
0x01    bInterfaceClass      (Audio Device Class)
0x02    bInterfaceSubClass   (Audio Streaming Interface)
0x20    bInterfaceProtocol   
0x0E    iInterface   "Playback Active"

AS Interface Descriptor:
------------------------------
0x10    bLength
0x24    bDescriptorType
0x01    bDescriptorSubtype
0x01    bTerminalLink
0x00    bmControls
0x01    bFormatType   (FORMAT_TYPE_1)
0x00000001  bmFormats
0x02    bNrChannels   (2 channels)
0x00000003  bmChannelConfig
0x00    iChannelNames

AS Format Type 1 Descriptor:
------------------------------
0x06    bLength
0x24    bDescriptorType
0x02    bDescriptorSubtype
0x01    bFormatType   (FORMAT_TYPE_1)
0x04    bSubslotSize
0x20    bBitResolution   (32 bits per sample)

Endpoint Descriptor:
------------------------------
0x07    bLength
0x05    bDescriptorType
0x01    bEndpointAddress  (OUT endpoint 1)
0x05    bmAttributes      (Transfer: Isochronous / Synch: Asynchronous / Usage: Data)
0x0180  wMaxPacketSize    (1 x 384 bytes) 
0x01    bInterval

AS Isochronous Data Endpoint Descriptor:
------------------------------
0x08    bLength
0x25    bDescriptorType
0x01    bDescriptorSubtype
0x00    bmAttributes
0x00    bmControls
0x00    bLockDelayUnits   (undefined)
0x0000  wLockDelay

Interface Descriptor:
------------------------------
0x09    bLength
0x04    bDescriptorType
0x02    bInterfaceNumber
0x00    bAlternateSetting
0x00    bNumEndPoints
0x01    bInterfaceClass      (Audio Device Class)
0x02    bInterfaceSubClass   (Audio Streaming Interface)
0x20    bInterfaceProtocol   
0x0F    iInterface   "Capture Inactive"

Interface Descriptor:
------------------------------
0x09    bLength
0x04    bDescriptorType
0x02    bInterfaceNumber
0x01    bAlternateSetting
0x01    bNumEndPoints
0x01    bInterfaceClass      (Audio Device Class)
0x02    bInterfaceSubClass   (Audio Streaming Interface)
0x20    bInterfaceProtocol   
0x10    iInterface   "Capture Active"

AS Interface Descriptor:
------------------------------
0x10    bLength
0x24    bDescriptorType
0x01    bDescriptorSubtype
0x04    bTerminalLink
0x00    bmControls
0x01    bFormatType   (FORMAT_TYPE_1)
0x00000001  bmFormats
0x02    bNrChannels   (2 channels)
0x00000003  bmChannelConfig
0x00    iChannelNames

AS Format Type 1 Descriptor:
------------------------------
0x06    bLength
0x24    bDescriptorType
0x02    bDescriptorSubtype
0x01    bFormatType   (FORMAT_TYPE_1)
0x04    bSubslotSize
0x20    bBitResolution   (32 bits per sample)

Endpoint Descriptor:
------------------------------
0x07    bLength
0x05    bDescriptorType
0x81    bEndpointAddress  (IN endpoint 1)
0x05    bmAttributes      (Transfer: Isochronous / Synch: Asynchronous / Usage: Data)
0x0180  wMaxPacketSize    (1 x 384 bytes) 
0x01    bInterval

AS Isochronous Data Endpoint Descriptor:
------------------------------
0x08    bLength
0x25    bDescriptorType
0x01    bDescriptorSubtype
0x00    bmAttributes
0x00    bmControls
0x00    bLockDelayUnits   (undefined)
0x0000  wLockDelay

Microsoft OS Descriptor is not available. Error code: 0x0000001F

String Descriptor Table
--------------------------------
Index  LANGID  String
0x00   0x0000  0x0409 
0x01   0x0409  "Foo Inc."
0x02   0x0409  "Bar Gadget"
0x03   0x0409  "0123456789"
0x04   0x0409  "1xUAC2"
0x05   0x0409  "Source/Sink"
0x06   0x0409  "Topology Control"
0x07   0x0409  "48000Hz"
0x08   0x0409  "48000Hz"
0x09   0x0409  "USBH Out"
0x0A   0x0409  "USBD Out"
0x0B   0x0409  "USBH In"
0x0C   0x0409  "USBD In"
0x0D   0x0409  "Playback Inactive"
0x0E   0x0409  "Playback Active"
0x0F   0x0409  "Capture Inactive"
0x10   0x0409  "Capture Active"

------------------------------

Connection path for device: 
USB xHCI Compliant Host Controller
Root Hub
Bar Gadget (VID=0x1D6B PID=0x0104) Port: 1

Running on: Windows 10 or greater

Brought to you by TDD v2.10.0, Feb  2 2018, 10:25:51
robiwano commented 6 years ago

With some pointers I think I've found the problem, the problem lies in the linux kernel f_uac2 driver (https://github.com/torvalds/linux/blob/master/drivers/usb/gadget/function/f_uac2.c#L219). wTotalLength should really be computed as:

    .wTotalLength = cpu_to_le16(sizeof ac_hdr_desc   /* missing part */
                        + sizeof in_clk_src_desc +
            + sizeof out_clk_src_desc + sizeof usb_out_it_desc
            + sizeof io_in_it_desc + sizeof usb_in_ot_desc
            + sizeof io_out_ot_desc),
kopasiak commented 6 years ago

Hmm so looks like a bug in a kernel. Care to send a patch for this?

robiwano commented 6 years ago

Should I send it to you, based on head of linux sources ? Or should I send it through the main channels (https://www.kernel.org/doc/html/latest/process/submitting-patches.html) ?

kopasiak commented 6 years ago

Definitely main channel (linux-usb mailing list). You may CC when sending a patch so I'll review it. It would be also nice to point to the UAC standard to justify that this field should contain also the length of this header.

BTW. Please remember to use () in sizeof and run checkpatch before sending

robiwano commented 6 years ago

Ok, will do, thanks!

liziru commented 5 years ago

有一些指示我认为我发现了问题,问题在于linux内核f_uac2驱动程序(https://github.com/torvalds/linux/blob/master/drivers/usb/gadget/function/f_uac2.c# L219)。wTotalLength应该真正计算为:

  .wTotalLength = cpu_to_le16(sizeof ac_hdr_desc   /* missing part */
                        + sizeof in_clk_src_desc +
          + sizeof out_clk_src_desc + sizeof usb_out_it_desc
          + sizeof io_in_it_desc + sizeof usb_in_ot_desc
          + sizeof io_out_ot_desc),

Does this way work? I tried this way,but my windows still does not recognize my uac2 gadget.

liziru commented 5 years ago

Who knows any approaches to this problem? I will appreciate it very much.

gschmottlach commented 5 years ago

Apparently there is an issue with the Linux UAC 2.0 driver that was identified early last year (2018) but has not been fixed yet. More details can be found in this thread. Basically, as quoted:

an isochronous OUT ep with asynchronous synchronization is required (at least by Microsoft) to have a feedback IN ep, to be able to report to the host the rate so no under- or overrun condition occurs.

The Linux UAC2 driver does not provide this and hence the Microsoft driver will not start. So until the Linux UAC2 developers make some changes your Linux UAC2 gadget will not speak to a Windows 10 machine. It doesn't appear to have been any work on this for over a year.