Vendor Audio Requests implementation

Discussions about USB Audio on XMOS devices
MaximLiadov
XCore Addict
Posts: 130
Joined: Mon Apr 16, 2018 9:14 am

Post by MaximLiadov »

Unfortunately, I still got stuck with this interrupt EP. I assume something wrong with a descriptor. Linux and Android stopped recognize USB device. Windows and iOS works fine. alsamixer said: Cannot load mixer controls: Protocol error.

I think I set correctly two hidden problems:

main.xc

Code: Select all

XUD_EpType epTypeTableIn[ENDPOINT_COUNT_IN]
...
XUD_EPTYPE_INT
descriptor.h

Code: Select all

.Audio_StdControlInterface = 
...
.bNumEndpoints                 = 0x01,                    /* 0 or 1 if optional interrupt endpoint is present */
The descriptor still isn't correct. Feeling like I'm very close to success, but miss something.

Update. I found that Thesycon USB Descriptor Dumper also indicated "ERROR: Descriptor has errors!"
In the log: Audio Control Interface Header Descriptor ERROR. Invalid wTotalLength 0x0086, should be 0x007F

I corrected wTotalLength. Windows works fine. iOS works fine. Linux doesn't work. Protocol error. Android doesn't recognize USB Audio. Does anybody know a diagnostic utility for Linux?
Last edited by MaximLiadov on Sun Apr 23, 2023 3:18 pm, edited 1 time in total.
MaximLiadov
XCore Addict
Posts: 130
Joined: Mon Apr 16, 2018 9:14 am

Post by MaximLiadov »

Concerning Error code: 0x0000001F. I have found it's a new specification, that was made for Windows family only:
https://learn.microsoft.com/en-us/windo ... cification
MaximLiadov
XCore Addict
Posts: 130
Joined: Mon Apr 16, 2018 9:14 am

Post by MaximLiadov »

Meanwhile I found the way how to get detailed information on Linux. It's in the /var/log/kern.log

Code: Select all

Apr 29 19:05:54 raspberrypi kernel: [  263.941560] usb 1-1.3: New USB device found, idVendor=1234, idProduct=1234, bcdDevice= 1.32
Apr 29 19:05:54 raspberrypi kernel: [  263.941619] usb 1-1.3: New USB device strings: Mfr=1, Product=3, SerialNumber=2
Apr 29 19:05:54 raspberrypi kernel: [  263.941636] usb 1-1.3: Product: XXX
Apr 29 19:05:54 raspberrypi kernel: [  263.941648] usb 1-1.3: Manufacturer: XXX Audio
Apr 29 19:05:54 raspberrypi kernel: [  263.941660] usb 1-1.3: SerialNumber: 12345
Apr 29 19:06:00 raspberrypi kernel: [  269.276799] usb 1-1.3: parse_audio_format_rates_v2v3(): unable to find clock source (clock -110)
Apr 29 19:06:00 raspberrypi kernel: [  269.277668] usb 1-1.3: uac_clock_source_is_valid(): cannot get clock validity for id 41
Apr 29 19:06:00 raspberrypi kernel: [  269.277688] usb 1-1.3: clock source 41 is not valid, cannot use
Apr 29 19:06:00 raspberrypi kernel: [  269.279870] usb 1-1.3: parse_audio_format_rates_v2v3(): unable to find clock source (clock -71)
Apr 29 19:06:00 raspberrypi kernel: [  269.280606] usb 1-1.3: uac_clock_source_is_valid(): cannot get clock validity for id 41
Apr 29 19:06:00 raspberrypi kernel: [  269.280628] usb 1-1.3: clock source 41 is not valid, cannot use
Apr 29 19:06:00 raspberrypi kernel: [  269.282406] usb 1-1.3: 1:3 : unsupported format bits 0x100000000
Apr 29 19:06:00 raspberrypi kernel: [  269.282780] usb 1-1.3: parse_audio_format_rates_v2v3(): unable to find clock source (clock -71)
Apr 29 19:06:00 raspberrypi kernel: [  269.283483] usb 1-1.3: uac_clock_source_is_valid(): cannot get clock validity for id 41
Apr 29 19:06:00 raspberrypi kernel: [  269.283501] usb 1-1.3: clock source 41 is not valid, cannot use
Apr 29 19:06:00 raspberrypi kernel: [  269.286168] usb 1-1.3: parse_audio_format_rates_v2v3(): unable to find clock source (clock -71)
Apr 29 19:06:00 raspberrypi kernel: [  269.287046] usb 1-1.3: uac_clock_source_is_valid(): cannot get clock validity for id 41
Apr 29 19:06:00 raspberrypi kernel: [  269.287073] usb 1-1.3: clock source 41 is not valid, cannot use
Apr 29 19:06:00 raspberrypi kernel: [  269.290212] usb 1-1.3: 10:0: failed to get current value for ch 0 (-71)
Apr 29 19:06:00 raspberrypi kernel: [  269.294546] usb 1-1.3: 10:0: cannot get min/max values for control 2 (id 10)
Apr 29 19:06:00 raspberrypi kernel: [  269.295670] usb 1-1.3: 11:0: failed to get current value for ch 1 (-71)
Apr 29 19:06:00 raspberrypi kernel: [  269.299236] usb 1-1.3: 11:0: failed to get current value for ch 2 (-71)
Apr 29 19:06:00 raspberrypi kernel: [  269.302943] usb 1-1.3: 11:0: failed to get current value for ch 3 (-71)
Apr 29 19:06:00 raspberrypi kernel: [  269.306771] usb 1-1.3: 11:0: failed to get current value for ch 4 (-71)
Apr 29 19:06:00 raspberrypi kernel: [  269.310593] usb 1-1.3: 11:0: failed to get current value for ch 0 (-71)
Apr 29 19:06:00 raspberrypi kernel: [  269.314331] usb 1-1.3: 11:0: cannot get min/max values for control 2 (id 11)
Apr 29 19:06:00 raspberrypi kernel: [  269.314721] usb 1-1.3: 11:0: cannot get min/max values for control 2 (id 11)
Apr 29 19:06:00 raspberrypi kernel: [  269.316073] usbcore: registered new interface driver snd-usb-audio
Apr 29 19:06:00 raspberrypi kernel: [  269.405850] usb 1-1.3: 10:0: cannot get min/max values for control 2 (id 10)
Apr 29 19:06:00 raspberrypi kernel: [  269.406211] usb 1-1.3: 10:0: cannot get min/max values for control 2 (id 10)
Apr 29 19:06:00 raspberrypi kernel: [  269.406517] usb 1-1.3: 10:0: cannot get min/max values for control 2 (id 10)
Apr 29 19:06:00 raspberrypi kernel: [  269.406817] usb 1-1.3: 10:0: cannot get min/max values for control 2 (id 10)
Apr 29 19:06:00 raspberrypi kernel: [  269.407123] usb 1-1.3: 10:0: cannot get min/max values for control 2 (id 10)
Apr 29 19:06:00 raspberrypi kernel: [  269.407431] usb 1-1.3: 10:0: cannot get min/max values for control 2 (id 10)
Apr 29 19:06:00 raspberrypi kernel: [  269.407728] usb 1-1.3: 10:0: cannot get min/max values for control 2 (id 10)
So using Clock Interrupt "as is" didn't went well on Linux. Seems to be I need to change firmware significantly to make it work.

I am curiouse, if it's possible to get rid of all clock selection/validity stuff in firmware that causes troubles?
User avatar
fabriceo
XCore Addict
Posts: 213
Joined: Mon Jan 08, 2018 4:14 pm

Post by fabriceo »

Hi MaximLiadov,
you said earlier that you have done a search and replace in many place with SPDIF_RX.
This is good to enable the Interrupt endpoint and its corresponding descriptor, but the side effect is that you have also enabled an additional clock identity (I think)
you should review all your search/replace and be careful on this. One way to identify the clock stuff is by also looking ADAT and then you see another clock identity for it.

on my side I have not pursued a full implementation yet because this would require to adjust also the front panel software so that the user could choose who is the "master" of the Volume (Knob, Host, Both with some caveat) and also some MAX/MIN protection are required. I can see that in some case the host just send 0dB, before finally sending the slider value...

I follow your progress which is inspiring !
MaximLiadov
XCore Addict
Posts: 130
Joined: Mon Apr 16, 2018 9:14 am

Post by MaximLiadov »

Thank you, Fabrice!

As you could see, even if you not defined SPDIF_RX, descriptor has some active lines, like these:

devicedefines.h

Code: Select all

/* Length of clock unit/clock-selector units */
#if defined(SPDIF_RX) && defined(ADAT_RX)
#define NUM_CLOCKS               (3)
#elif defined(SPDIF_RX) || defined(ADAT_RX)
#define NUM_CLOCKS               (2)
#else
#define NUM_CLOCKS               (1)
#endif
descriptors.h

Code: Select all

#if (NUM_CLOCKS == 1)
#define USB_Descriptor_Audio_ClockSelector_t USB_Descriptor_Audio_ClockSelector_1_t
...
USB_Descriptor_Audio_ClockSource_t          Audio_ClockSource;
USB_Descriptor_Audio_ClockSelector_t        Audio_ClockSelector;


It's interesting if we use the only internal clock, can we remove all this stuff from descriptor and command processing? Or UAC2.0 needs this in any case?
MaximLiadov
XCore Addict
Posts: 130
Joined: Mon Apr 16, 2018 9:14 am

Post by MaximLiadov »

Update. When I comment out these lines

Code: Select all

//    USB_Descriptor_Audio_ClockSelector_t        Audio_ClockSelector;
//    STR_TABLE_ENTRY(clockSelectorStr);            /* iClockSel */
//    .clockSelectorStr            = APPEND_VENDOR_STR(Clock Selector),
        /* Clock Selector Descriptor (4.7.2.2) */
/*        .Audio_ClockSelector = ... */
the error log starts to look significantly better:

Code: Select all

Apr 29 20:57:51 raspberrypi kernel: [  113.635025] usb 1-1.3: parse_audio_format_rates_v2v3(): unable to find clock source (clock -22)
Apr 29 20:57:54 raspberrypi kernel: [  116.878230] usb 1-1.3: parse_audio_format_rates_v2v3(): unable to find clock source (clock -22)
Apr 29 20:57:54 raspberrypi kernel: [  116.968247] usb 1-1.3: 1:3 : unsupported format bits 0x100000000
Apr 29 20:57:54 raspberrypi kernel: [  116.968280] usb 1-1.3: parse_audio_format_rates_v2v3(): unable to find clock source (clock -22)
Apr 29 20:57:55 raspberrypi kernel: [  117.030486] usb 1-1.3: parse_audio_format_rates_v2v3(): unable to find clock source (clock -22)
Unfurtunately the same idea does not work with Audio_ClockSource. Seems to be Audio_ClockSource is used in Sampling Frequency request.
The strange thing is, if I disable Interrupt Endpoint, Linux starts working flawlessly.
MaximLiadov
XCore Addict
Posts: 130
Joined: Mon Apr 16, 2018 9:14 am

Post by MaximLiadov »

Update. Almost done! Alsamixer does work at last. Volume control in Linux does work. Current Linux log is:

Code: Select all

Apr 29 22:45:01 raspberrypi kernel: [  204.276668] usb 1-1.3: New USB device found, idVendor=1234, idProduct=1234, bcdDevice= 1.32
Apr 29 22:45:01 raspberrypi kernel: [  204.276713] usb 1-1.3: New USB device strings: Mfr=1, Product=3, SerialNumber=2
Apr 29 22:45:01 raspberrypi kernel: [  204.276731] usb 1-1.3: Product: XXX
Apr 29 22:45:01 raspberrypi kernel: [  204.276745] usb 1-1.3: Manufacturer: XXX Audio
Apr 29 22:45:01 raspberrypi kernel: [  204.276759] usb 1-1.3: SerialNumber: 12345
Apr 29 22:45:01 raspberrypi kernel: [  204.705239] usb 1-1.3: 1:3 : unsupported format bits 0x100000000
Apr 29 22:45:01 raspberrypi kernel: [  204.771561] usbcore: registered new interface driver snd-usb-audio
MaximLiadov
XCore Addict
Posts: 130
Joined: Mon Apr 16, 2018 9:14 am

Post by MaximLiadov »

The solution that worked for me was simple. No need to comment out anything in descriptors.h.
Just reporting all the time Internal Clock selected instead:

audiorequests.xc

Code: Select all

                /* Clock Selector Unit(s) */
                case ID_CLKSEL:
                {
                    if ((sp.wValue >> 8) == CX_CLOCK_SELECTOR_CONTROL)
                    {
                        /* Direction: Host-to-device */
                        if(sp.bmRequestType.Direction == USB_BM_REQTYPE_DIRECTION_H2D )
                        {
                            if((result = XUD_GetBuffer(ep0_out, buffer, datalength)) != XUD_RES_OKAY)
                            {

				/*** commented out all code here ***/
				
                                return result;
                            }

                            /* Check for correct datalength for clock sel */
                            if(datalength == 1)
                            {

                                /* Send 0 Length as status stage */
                                return XUD_DoSetRequestStatus(ep0_in);
                            }

                        }
                        else
                        {
                            /* Direction: Device-to-host: Send Current Selection */
                            buffer[0] = 1;

 				/*** commented out all code here ***/

                            return XUD_DoGetRequest( ep0_out, ep0_in, buffer, 1, sp.wLength );

                        }
                    }
                    break;
                }
While Windows and Apple don't care and worked fine, Linux was hanging on the get clock or set clock command. I saw many users with XMOS based devices reported exactly the same problem on Linux forums.
MaximLiadov
XCore Addict
Posts: 130
Joined: Mon Apr 16, 2018 9:14 am

Post by MaximLiadov »

I googled "unsupported format bits 0x100000000" and found a lot of searching results. So might it be a false positive diagnostics? Anyway, Linux does work fine now.

https://github.com/torvalds/linux/blob/ ... b/format.c
line 150 said that