STM32 USB to I2S multi channel - log - ask for help

Hm, I do not remember any issues with the feedback EP IN bInterval=4 on Win10 from the current linux gadget. Quite a few people use it, combined with CamillaDSP.
lsusb -v (descriptor dump):
Code:
Bus 001 Device 006: ID 1d6b:0101 Linux Foundation Audio Gadget
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.01
  bDeviceClass          239 Miscellaneous Device
  bDeviceSubClass         2
  bDeviceProtocol         1 Interface Association
  bMaxPacketSize0        64
  idVendor           0x1d6b Linux Foundation
  idProduct          0x0101 Audio Gadget
  bcdDevice            6.01
  iManufacturer           1
  iProduct                2
  iSerial                 0
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength       0x010d
    bNumInterfaces          3
    bConfigurationValue     1
    iConfiguration          0
    bmAttributes         0xc0
      Self Powered
    MaxPower                0mA
    Interface Association:
      bLength                 8
      bDescriptorType        11
      bFirstInterface         0
      bInterfaceCount         3
      bFunctionClass          1 Audio
      bFunctionSubClass       0
      bFunctionProtocol      32
      iFunction               4
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         1 Audio
      bInterfaceSubClass      1 Control Device
      bInterfaceProtocol     32
      iInterface              5
      AudioControl Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      1 (HEADER)
        bcdADC               2.00
        bCategory               8
        wTotalLength       0x0077
        bmControls           0x00
      AudioControl Interface Descriptor:
        bLength                 8
        bDescriptorType        36
        bDescriptorSubtype     10 (CLOCK_SOURCE)
        bClockID                8
        bmAttributes            1 Internal fixed clock
        bmControls           0x03
          Clock Frequency Control (read/write)
        bAssocTerminal          0
        iClockSource            6
      AudioControl Interface Descriptor:
        bLength                 8
        bDescriptorType        36
        bDescriptorSubtype     10 (CLOCK_SOURCE)
        bClockID                7
        bmAttributes            1 Internal fixed clock
        bmControls           0x03
          Clock Frequency Control (read/write)
        bAssocTerminal          0
        iClockSource            7
      AudioControl Interface Descriptor:
        bLength                17
        bDescriptorType        36
        bDescriptorSubtype      2 (INPUT_TERMINAL)
        bTerminalID             1
        wTerminalType      0x0101 USB Streaming
        bAssocTerminal          0
        bCSourceID              7
        bNrChannels             2
        bmChannelConfig    0x00000003
          Front Left (FL)
          Front Right (FR)
        iChannelNames           0
        bmControls         0x0003
          Copy Protect Control (read/write)
        iTerminal               8
      AudioControl Interface Descriptor:
        bLength                18
        bDescriptorType        36
        bDescriptorSubtype      6 (FEATURE_UNIT)
        bUnitID                 5
        bSourceID               1
        bmaControls(0)     0x0000000f
          Mute Control (read/write)
          Volume Control (read/write)
        bmaControls(1)     0x00000000
        bmaControls(2)     0x00000000
        iFeature               13
      AudioControl Interface Descriptor:
        bLength                17
        bDescriptorType        36
        bDescriptorSubtype      2 (INPUT_TERMINAL)
        bTerminalID             2
        wTerminalType      0x0201 Microphone
        bAssocTerminal          0
        bCSourceID              8
        bNrChannels             2
        bmChannelConfig    0x00000003
          Front Left (FL)
          Front Right (FR)
        iChannelNames           0
        bmControls         0x0003
          Copy Protect Control (read/write)
        iTerminal               9
      AudioControl Interface Descriptor:
        bLength                18
        bDescriptorType        36
        bDescriptorSubtype      6 (FEATURE_UNIT)
        bUnitID                 6
        bSourceID               2
        bmaControls(0)     0x0000000f
          Mute Control (read/write)
          Volume Control (read/write)
        bmaControls(1)     0x00000000
        bmaControls(2)     0x00000000
        iFeature               12
      AudioControl Interface Descriptor:
        bLength                12
        bDescriptorType        36
        bDescriptorSubtype      3 (OUTPUT_TERMINAL)
        bTerminalID             4
        wTerminalType      0x0101 USB Streaming
        bAssocTerminal          0
        bSourceID               6
        bCSourceID              8
        bmControls         0x0003
          Copy Protect Control (read/write)
        iTerminal              10
      AudioControl Interface Descriptor:
        bLength                12
        bDescriptorType        36
        bDescriptorSubtype      3 (OUTPUT_TERMINAL)
        bTerminalID             3
        wTerminalType      0x0301 Speaker
        bAssocTerminal          0
        bSourceID               5
        bCSourceID              7
        bmControls         0x0003
          Copy Protect Control (read/write)
        iTerminal              11
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0006  1x 6 bytes
        bInterval               4
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           0
      bInterfaceClass         1 Audio
      bInterfaceSubClass      2 Streaming
      bInterfaceProtocol     32
      iInterface             14
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       1
      bNumEndpoints           2
      bInterfaceClass         1 Audio
      bInterfaceSubClass      2 Streaming
      bInterfaceProtocol     32
      iInterface             15
      AudioStreaming Interface Descriptor:
        bLength                16
        bDescriptorType        36
        bDescriptorSubtype      1 (AS_GENERAL)
        bTerminalLink           1
        bmControls           0x00
        bFormatType             1
        bmFormats          0x00000001
          PCM
        bNrChannels             2
        bmChannelConfig    0x00000003
          Front Left (FL)
          Front Right (FR)
        iChannelNames           0
      AudioStreaming Interface Descriptor:
        bLength                 6
        bDescriptorType        36
        bDescriptorSubtype      2 (FORMAT_TYPE)
        bFormatType             1 (FORMAT_TYPE_I)
        bSubslotSize            4
        bBitResolution         32
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x02  EP 2 OUT
        bmAttributes            5
          Transfer Type            Isochronous
          Synch Type               Asynchronous
          Usage Type               Data
        wMaxPacketSize     0x0308  1x 776 bytes
        bInterval               1
        AudioStreaming Endpoint Descriptor:
          bLength                 8
          bDescriptorType        37
          bDescriptorSubtype      1 (EP_GENERAL)
          bmAttributes         0x00
          bmControls           0x00
          bLockDelayUnits         0 Undefined
          wLockDelay         0x0000
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x83  EP 3 IN
        bmAttributes           17
          Transfer Type            Isochronous
          Synch Type               None
          Usage Type               Feedback
        wMaxPacketSize     0x0004  1x 4 bytes
        bInterval               4
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        2
      bAlternateSetting       0
      bNumEndpoints           0
      bInterfaceClass         1 Audio
      bInterfaceSubClass      2 Streaming
      bInterfaceProtocol     32
      iInterface             16
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        2
      bAlternateSetting       1
      bNumEndpoints           1
      bInterfaceClass         1 Audio
      bInterfaceSubClass      2 Streaming
      bInterfaceProtocol     32
      iInterface             17
      AudioStreaming Interface Descriptor:
        bLength                16
        bDescriptorType        36
        bDescriptorSubtype      1 (AS_GENERAL)
        bTerminalLink           4
        bmControls           0x00
        bFormatType             1
        bmFormats          0x00000001
          PCM
        bNrChannels             2
        bmChannelConfig    0x00000003
          Front Left (FL)
          Front Right (FR)
        iChannelNames           0
      AudioStreaming Interface Descriptor:
        bLength                 6
        bDescriptorType        36
        bDescriptorSubtype      2 (FORMAT_TYPE)
        bFormatType             1 (FORMAT_TYPE_I)
        bSubslotSize            4
        bBitResolution         32
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x85  EP 5 IN
        bmAttributes            5
          Transfer Type            Isochronous
          Synch Type               Asynchronous
          Usage Type               Data
        wMaxPacketSize     0x0308  1x 776 bytes
        bInterval               1
        AudioStreaming Endpoint Descriptor:
          bLength                 8
          bDescriptorType        37
          bDescriptorSubtype      1 (EP_GENERAL)
          bmAttributes         0x00
          bmControls           0x00
          bLockDelayUnits         0 Undefined
          wLockDelay         0x0000

The way the linux host driver views the device:

Code:
Linux 6.1.43-467115-gad02bcf12c1d-dirty with ff400000.usb Linux USB Audio Gadge
: USB Audio

Playback:
  Status: Stop
  Interface 1
    Altset 1
    Format: S32_LE
    Channels: 2
    Endpoint: 0x02 (2 OUT) (ASYNC)
    Rates: 48000, 96000, 192000, 384000, 768000
    Data packet interval: 125 us
    Bits: 32
    Channel map: FL FR
    Sync Endpoint: 0x83 (3 IN)
    Sync EP Interface: 1
    Sync EP Altset: 1
    Implicit Feedback Mode: No

Capture:
  Status: Stop
  Interface 2
    Altset 1
    Format: S32_LE
    Channels: 2
    Endpoint: 0x85 (5 IN) (ASYNC)
    Rates: 48000, 96000, 192000, 384000, 768000
    Data packet interval: 125 us
    Bits: 32
    Channel map: FL FR
 
Thanks for the feedback phofman. From readintg the above, I also note that the linux gadget seems seems to only propose 32 bits interface (and several sampling frequencies). This is interesting to me as it would allow to avoid to manage different alt settings for 12, 24 and 32 bits.

Do you confirm? Does it has some inconvenience in practice? Is it OK as Windows/Linux/Mac easily map 16 and 24 bits to 32 bits?

Nota: I also noted that that the OpenUAC bridge has only 2 configs (24 and 32 bits, no 16 bits).
 
From readintg the above, I also note that the linux gadget seems seems to only propose 32 bits interface (and several sampling frequencies). This is interesting to me as it would allow to avoid to manage different alt settings for 12, 24 and 32 bits.
It's just that specific configuration of mine. Any number of bytes (integer format only, for now), any channels, any samplerate combination can be specified https://www.kernel.org/doc/Documentation/ABI/testing/configfs-usb-gadget-uac2 . It's just about copying byte arrays from/to the packet in the end :)

Multiple altsets with individual configurations are coming too https://lore.kernel.org/all/CAB0kiB.../T/#mc2b68c2e74ed57e2998c1b0f42bfca82e07db181
 
I do not remember any issues with the feedback EP IN bInterval=4 on Win10 from the current linux gadget.
It has been a while since I worked on this but IIRC it is about Synopsys OTG used in STM32 MCUs. If FB packet frame number parity (odd or even) does not match to what host has sent Synopsys OTG sends an empty feedback packet. I did not spend much time on a workaround as easiest fix is to use bInterval = 1.
 
FB packets are sent but Win10 driver ignores them as they are empty.
This is how it looks like in Win10 uac2 driver logs:
Code:
[0]464C.4744::04/28/2024-17:05:08.806 [USBAudio2](0x01): FEEDBACK Isoch Buffers: BufferCount=3 BytesPerPacket=4 PacketsPerBuffer=16 PacketFreq=1000 PollingInterval=8
...
[0]464C.4744::04/28/2024-17:05:08.810 [USBAudio2](OUT): packetNumber=1 flags=0x00000000 eosPacketLength=21504
[0]0000.0000::04/28/2024-17:05:08.829 [USBAudio2](0x01): COMPL OUT buf 0 CurrenLinearPosition=1344  
[0]0000.0000::04/28/2024-17:05:08.830 [USBAudio2](0x01): buf 0 feedback packet 0 has invalid packet length 0, ignoring packet
[0]0000.0000::04/28/2024-17:05:08.830 [USBAudio2](0x01): buf 0 feedback packet 1 has invalid packet length 0, ignoring packet
[0]0000.0000::04/28/2024-17:05:08.830 [USBAudio2](0x01): buf 0 feedback packet 2 has invalid packet length 0, ignoring packet
[0]0000.0000::04/28/2024-17:05:08.830 [USBAudio2](0x01): buf 0 feedback packet 3 has invalid packet length 0, ignoring packet
[0]0000.0000::04/28/2024-17:05:08.830 [USBAudio2](0x01): buf 0 feedback packet 4 has invalid packet length 0, ignoring packet
 
I will have a look at the Win10 uac2 driver logs to check if I have the same behaviour.

After some searches on the net, and old posrs on ST community, I reverted to bInterval=5 and tried to see if I got some IsoInIncompleteCallbacks.

I have, and at each uFrame.

In that case, the ST usbx adaptation layer does:
HAL_PCD_EP_Transmit(dcd_stm32 -> pcd_handle,
endpoint->ux_slave_endpoint_descriptor.bEndpointAddress,
endpoint->ux_slave_endpoint_transfer_request.ux_slave_transfer_request_data_pointer,
endpoint->ux_slave_endpoint_transfer_request.ux_slave_transfer_request_requested_length);

Which looks similar to OpenUAC2 code in case of IsoInIncomplete, which seems to work with bInterval=4 for feedback:
if (epnum == FEEDBACK_EP_NUM)
{
USBD_LL_Transmit(pdev, FEEDBACK_EP_ADDR, (uint8_t*)&haudio->feedback_value, FEEDBACK_PACKET_SIZE);
}

And possibly https://community.st.com/t5/stm32-m...eedback-problem-and-even-odd-frame/m-p/542335

But the usbx code is not sufficient to get the thing right :-(

This could to be a sort of odd behaviour of the stm32 USB peripheral...

JMF,
 
USBD_LL_Transmit() and HAL_PCD_EP_Transmit() are the same thing. No test that would make not execute the needed action...

USBD_StatusTypeDef USBD_LL_Transmit(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t *pbuf, uint32_t size) { HAL_StatusTypeDef hal_status = HAL_OK; USBD_StatusTypeDef usb_status = USBD_OK; hal_status = HAL_PCD_EP_Transmit(pdev->pData, ep_addr, pbuf, size); usb_status = USBD_Get_USB_Status(hal_status); return usb_status; }

So if OpenUAC2 bridge is working, this should work.

Same type of solution/workaround based on IsoInIncomplete is reported here https://community.st.com/t5/stm32-m...ue-with-stm32h7-series-and-usb3320/m-p/198584.

Good that the bInterval=1 should be a workaround, but I would be happy to clarify that point...
 
My assumption is that when host polling period is more than 1 (e.g. bInterval=4) device does not know when host polling occurs. This leads to IsoInIncomplete event if host does not read the feedback in time (IN event). Sending feedback at IsoInIncomplete is a workaround as feedback is then sent much more frequently than needed. So instead of sending feedback at 1ms period the actual period is closer to 125us.
 
My understanding is that when feedback processing is working there should be zero IsoInIncomplete events and same number of In events as feedback messages sent.
I did some testing and with bInterval=1 this is the case: number of IsoInIncomplete events is close to zero and number of In events close to feedbacks sent. So almost all feedback messages processed ok.
However with bInterval=4 the number of IsoInIncomplete events is close to number of feedbacks sent if host polling and device are not in sync. So almost all feedback messages are not processed ok. Syncing host polling and device feedbacks with bInterval > 1 is quite tricky so the workaround of sending feedback at IsoInIncomplete events is easier although IMO not a proper fix.

All this applies to STM32 MCUs with Synopsys OTG. Other implementations may work differently.
 
I find it hard to believe that the Synopsys OTG IP were so buggy in STM, the sync feedback communication is a standard USB method. Synopsys OTG IPs are ubiquitous (dwc2 in RPi or Rockchips, dwc3 in Rockchips or Intel), of course the implementations always differ a bit.

Maybe there really is some issue with generating the sync EP IN packets in your FW which prevents the host controller/USB core driver from accepting them. Maybe the packets would be visible in wireshark (if the host controller accepts them). Best would be tracking the traffic using wire capture, using e.g. that simple https://www.diyaudio.com/community/threads/usb-sniffer-protocol-analyzer-using-wireshark.407540/
 
I would not call Synopsys OTG buggy as it works according to USB specifications. What is the bug in your opinion?

Regarding my FW you should take a closer look at e.g. the links in post #69 & #70. There are plenty of similar links to be found. So this behaviour is not limited to my FW.
 
Last edited:
I am afraid I cannot help with STM code, zero knowledge here :) Also the question is what those HAL methods do internally, they could be buggy too.

But if you wanted I could capture some linux gadget UAC2 packets with bInterval=4 in wireshark which could be compared with packets generated by your device (if they can be captured by software in your case, i.e. if they make it past the host controller/usb core driver).
 
BTW here is another similar issue which was fixed with setting bInterval=1.
https://learn.microsoft.com/en-us/a...cit-feedback-for-asynchronous-audio-with-usba
IIUC that report concerns the linux gadget and IMO the bInterval discussed relates to the EP OUT, not to the sync packet. That thread is from 2021, and the commit which fixed the behavior for HS EP OUT bInterval > 1 is from September 2021 https://github.com/torvalds/linux/c...b2fd31a0a731bcad75b48ee8eb5386ea7b77R133-R139 - which happened to be submitted by me (with help of a number of great developers, of course).

The HS sync fback EP IN bInterval has always been fixed at 4 https://github.com/torvalds/linux/blame/master/drivers/usb/gadget/function/f_uac2.c#L406-L413