Created attachment 306638 [details] dmesg The problem is very similar to https://bugzilla.kernel.org/show_bug.cgi?id=217089: the Xone:23C is supposed to be a 2 stereo input/2 stereo outputs but only 1 in and 1 out show under Linux (Windows with related drivers installs show the correct amount of in/out). Trying to set bConfigurationValue, either by editing /sys/bus/usb/devices/1-9/bConfigurationValue by hand or using a udev rule won't work: # echo 2 > /sys/devices/pci0000:00/0000:00:01.3/0000:01:00.0/usb1/1-2/bConfigurationValue bash: echo: write error: Invalid argument Please find enclosed with this ticket, the relevant journalctl, dmsg, lsusb and `cat /sys/kernel/debug/usb/usbmon/1u` of the moment I plug the device. Reproduced on a Fedora 40 with kernel 6.9.11.
Created attachment 306639 [details] journalctl -f journalctl -f produce when the deviced it plugged
Created attachment 306640 [details] cat /sys/kernel/debug/usb/usbmon/1u result of `cat /sys/kernel/debug/usb/usbmon/1u` after device is plugged.
Created attachment 306641 [details] lsusb -v -d 22f0:0008~
Note: I also tried the `echo Y >/sys/module/usbcore/parameters/old_scheme_first`, unplugged the deviced, restarted the device and restarted the computer but the device still appears as a 1 stereo in/1 stereo out.
Restarting the computer erases the old_scheme_first setting. You have to do the echo Y thing _after_ restarting the computer and _before_ plugging in the device.
Ah dear, yes, you're right… But there's no way to get it to work out of the box without the old_scheme_first setting?
I don't know of any way. The device has a very unusual, non-standard behavior. Also, I don't know how Windows handles it. Maybe there's some way to tell the device to reset itself back to the original two configurations without unplugging it. Are you able to test a patch?
Sure I can do that.
Created attachment 306649 [details] Skip second reset if the maxpacket size is large enough See if this change makes any difference. The patch is against kernel version 6.10; if it doesn't apply to your kernel tree, let me know what version to base it on.
Can you patch against the 6.9.11? That's the most recent source RPM in Fedora's repo and I'm safer using the RPM to build and install the kernel.
Created attachment 306650 [details] skip-2nd-reset patched on 6.9.11
Or rather: I addapted your patch on the 6.9.11 RPM I have. Can you confirm that the diff is good?
Yes, the adapted diff looks okay. Have you tried testing it?
The kernel is compiling as we speak.
Hmm… The patch is not working but it doesn't mean anything. I think I messed something up while compiling the RPM. Can you confirm me that this patch will end up in the vmlinuz binary? Can I add a print statement somewhere that will show in journalctl or demsg that will confirm me that I am indeed running the patched kernel?
Created attachment 306656 [details] Add debug info for skipping second reset patch Apply this patch on top of the previous one. It will print a message to the kernel log when the new code takes effect.
I'm sorry, I'm a bit stuck here. The kernel I compiled doesn't correctly boot. It gets stuck at the systemd cryptsetup (luks) stage which failes (both / and /home are encrypted) and nothing gets logged to systemd, the boot to this kernel is not event listed in `journalctl --list-boots`. How can I debug this?
Ok, so I finally managed to correclty install and run the patched kernel and it appears your patch doesn't work. Here's the journalctl trace from when I plug the mixer: août 04 17:32:42 localhost kernel: usb 1-2: new high-speed USB device number 7 using xhci_hcd août 04 17:32:42 localhost kernel: usb 1-2: Patch applied août 04 17:32:42 localhost kernel: usb 1-2: Skipped second reset août 04 17:32:42 localhost kernel: usb 1-2: New USB device found, idVendor=22f0, idProduct=0008, bcdDevice= 2.00 août 04 17:32:42 localhost kernel: usb 1-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3 août 04 17:32:42 localhost kernel: usb 1-2: Product: Xone:23C août 04 17:32:42 localhost kernel: usb 1-2: Manufacturer: Allen&Heath août 04 17:32:42 localhost kernel: usb 1-2: SerialNumber: no serial number août 04 17:32:42 localhost kernel: usb 1-2: 1:2 : UAC_AS_GENERAL descriptor not found août 04 17:32:42 localhost kernel: usb 1-2: 2:2 : UAC_AS_GENERAL descriptor not found août 04 17:32:42 localhost kernel: usb 1-2: Quirk or no altset; falling back to MIDI 1.0 août 04 17:32:42 localhost mtp-probe[5421]: checking bus 1, device 7: "/sys/devices/pci0000:00/0000:00:01.3/0000:01:00.0/usb1/1-2" août 04 17:32:42 localhost mtp-probe[5421]: bus: 1, device: 7 was not an MTP device août 04 17:32:42 localhost (udev-worker)[5420]: 1-2: /usr/lib/udev/rules.d/69-mixxx-usb-uaccess.rules:19 Failed to write ATTR{/sys/devices/pci0000:00/0000:00:01.3/0000:01:00.0/usb1/1-2/bConfigurationValue}, ignoring: Invalid argument août 04 17:32:42 localhost mtp-probe[5443]: checking bus 1, device 7: "/sys/devices/pci0000:00/0000:00:01.3/0000:01:00.0/usb1/1-2" août 04 17:32:42 localhost mtp-probe[5443]: bus: 1, device: 7 was not an MTP device août 04 17:32:42 localhost kded6[3384]: org.kde.pulseaudio: No object for name "alsa_output.pci-0000_08_00.4.analog-stereo.monitor" août 04 17:32:42 localhost plasmashell[3409]: org.kde.pulseaudio: No object for name "alsa_output.pci-0000_08_00.4.analog-stereo.monitor" août 04 17:32:42 localhost kded6[3384]: org.kde.pulseaudio: No object for name "alsa_output.pci-0000_08_00.4.analog-stereo.monitor" août 04 17:32:42 localhost plasmashell[3409]: org.kde.pulseaudio: No object for name "alsa_output.pci-0000_08_00.4.analog-stereo.monitor" août 04 17:32:42 localhost kded6[3384]: org.kde.pulseaudio: No object for name "alsa_output.pci-0000_08_00.4.analog-stereo.monitor" août 04 17:32:42 localhost kded6[3384]: org.kde.pulseaudio: No object for name "alsa_output.pci-0000_08_00.4.analog-stereo.monitor" août 04 17:32:42 localhost plasmashell[3409]: org.kde.pulseaudio: No object for name "alsa_output.pci-0000_08_00.4.analog-stereo.monitor" août 04 17:32:42 localhost plasmashell[3409]: org.kde.pulseaudio: No object for name "alsa_output.pci-0000_08_00.4.analog-stereo.monitor" août 04 17:32:42 localhost kded6[3384]: org.kde.pulseaudio: No object for name "alsa_output.pci-0000_08_00.4.analog-stereo.monitor" août 04 17:32:42 localhost plasmashell[3409]: org.kde.pulseaudio: No object for name "alsa_output.pci-0000_08_00.4.analog-stereo.monitor" août 04 17:32:42 localhost kded6[3384]: org.kde.pulseaudio: No object for name "alsa_output.pci-0000_08_00.4.analog-stereo.monitor" août 04 17:32:42 localhost plasmashell[3409]: org.kde.pulseaudio: No object for name "alsa_output.pci-0000_08_00.4.analog-stereo.monitor" You can see the *Patch applied* log which is a line I added to ensure I was indeed running the patched kernel and the *Skipped second reset* line that indicates the `if (maxp0 <= 18)` was skipped but udev still fails to apply the `bConfigurationValue` rule. If you want to test another patch, I now know how to do.
For now, I can't think of any other patches to try. If you have a Windows system, you could do a USB packet capture (using Wireshark, for example). That might give an indication of how the device is meant to work.
Created attachment 306667 [details] USB traffic capture occuring when pluggin the Xone:23C
I did the previous capture. Does that help you?
It doesn't help. It shows that the device provides one input and one output stream, plus a MIDI connection -- no more. And it also shows the device claims to have only one configuration, not two. (Plus it shows Windows setting the data rates to 44100 samples per second, whereas your earlier Linux usbmon trace showed the data rates being set to 48000 samples per second, but I assume this doesn't matter much.) Are you certain that the device has two input and two output streams under Windows? The USB packet capture gives no indication of it. Also, how does the device behave under Linux if you set the old_scheme_first parameter to Y? In comment #6 you didn't say.
Yes, the device shows as a 2 in/2 out under Windows but only with the driver installed. Otherwise, it shows as a 1 in/1 out like on Linux with `old_scheme_first` to `N`. And yes, the device do appear as a 2 in/2 out under Linux with `old_scheme_first` set to yes.
May the usbmon trace with `old_scheme_first` to `Y` help you?
Did you do the Windows packet capture with the driver installed? It does not look like you did (because the capture log shows only 1 in/1 out), but that's what I need to see. I do not need a usbmon trace with old_scheme_first set to Y.
Created attachment 306675 [details] Presentation of the device's inputs in Mixxx
Wait is there a difference in the protocol between 2 stereo in and one 4 channels in? See the picture I just uploaded. This is what the devices inputs look like in Mixxx under Windows, with the driver installed (the Wireshark trace in the same).
As I understand it, each audio channel gets transported over its own USB endpoint. (This is true for both mono channels and stereo channels.) So two stereo-in channels require two endpoints, and two stereo-out channels would require an additional two endpoints. Similarly, four in channels would require four endpoints. Maybe my understanding is wrong; I'll have to read through the USB Audio Class specification to make sure. The usbmon trace and the Wireshark log you attached both mention only two endpoints. Can you get a Wireshark trace showing what happens when you transmit or receive data over two in channels and two out channels (so using four endpoints) all at the same time? Also, can you attach a copy of the "lsusb -v" output for the device when it is attached with old_scheme_first set to Y?
Created attachment 306676 [details] lsusb -v -d 22f0:0008 with old_scheme_first set to Y
I also recorded 2 minutes of USB traffic with music going in and out all the channels using Mixxx but it weights ~60Mio. Where can I upload this?
2 minutes is way more than I need; 1 second would be more than enough. Just the first 100 KB of data should be sufficient. You should be able to attach it to this bug report.
Created attachment 306682 [details] Xone 23C Wireshark capture with audio passing through USB
Here it is. I hope it help. Otherwise I guess I'll have to ship you the device. Is it doable?
BTW, I [can see here](https://lkml.iu.edu/hypermail/linux/kernel/2106.0/02532.html) a similar problem seems to affect the Xone:43C.
Created attachment 306699 [details] lsusb -v -d 22f0:0008 with old_scheme_first set to N For comparison with what's lsusb outputs when old_scheme_first set to Y
It looks like the Xone:23C can operate in two different modes, and it decides during the initial startup which mode it will use. The first mode (what you get with old_scheme_first=N) exposes a single configuration, which has a USB audio class 1 interface and 2-channel stereo in/out. The second mode (what you get with old_scheme_first=Y) exposes two configurations. The first config is the same as the one described above, but the second config has a USB audio class 2 interface with 4-channel "stereo" in/out. The problem is how to make the device go into its second mode. Your Windows packet captures don't show this happening. In fact, they do show the device in its first mode, using the only configuration in that mode, so it shouldn't be doing 4-channel I/O at all! I don't understand that. The only way we know to put the device into the second mode is to set old_scheme_first to Y. Maybe this doesn't have to be done before the device initially starts up; you may find that resetting the device while old_scheme_first is Y will cause it to go into the second mode, even if it was in the first mode before. You could try that to see if it works. If it does, the kernel could be changed to make this happen automatically.
The mixer driver s an ASIO driver and Mixxx uses ASIO as primary sound API. Maybe that's the reason? Maybe the driver don't even interrogate the device about its configuration because it already knows it and what we can see in he Wireshark dump is Windows interrogating the device not using the ASIO driver? Can you elaborate what old_scheme_first does?
It's more than just the driver knowing what configuration to use. The device has to be _told_ to use that configuration; until it is told it won't use any configuration at all and won't function. Your usbmon traces and Windows packet captures all show the computer telling the device to use configuration 1. (If you made a usbmon trace with old_scheme_first=Y, presumably it would show the computer telling the device to use configuration 2.) The configuration matters because the data sent over the USB connection is formatted differently depending on the number of channels. No matter what the driver may know about the possible configs, as long as the device is using config 1, it will provide only two-channel stereo. And as long as it is using config 2, it will provide only four-channel stereo. The difference between the old scheme and the new scheme is rather technical. It has to do with how the device is initialized when it is first plugged in (and also whenever it gets reset). With the old scheme, after performing an initial reset the computer asks the device to send just the first 8 bytes of its device descriptor, then the computer tells the device what address to use, and then it reads the complete device descriptor and all the other descriptors. With the new scheme, after performing the initial reset the computer asks the device to send the first 64 bytes of its device descriptor. Since the device descriptor is only 18 bytes long, the response is always a short one. The computer then resets the device a second time, tells it what address to use, and reads all the descriptors. (That's why I thought skipping the second reset might cause the device to make both configurations available, like it does with the old scheme.) The old scheme is what the USB 2.0 specification recommends. The new scheme is what Microsoft implemented early on, however, and as a result quite a few devices would work with the new scheme but not the old one. In theory any device should work properly with either scheme, but in practice they don't always do so. As in this case.
> In fact, they do show the device in its first mode, using the only configuration in that mode, so it shouldn't be doing 4-channel I/O at all! I don't understand that. Maybe I messed up the Wireshark capture in some way? > you may find that resetting the device while old_scheme_first is Y will cause it to go into the second mode, even if it was in the first mode before. You could try that to see if it works. How can I do that?
I don't think you messed up the Wireshark capture. But I can't tell what happened. You can reset the device by using the usbreset program, which is part of the usbutils package. Some distributions (such as Ubuntu) include it whereas others (such as Fedora) don't. But if you don't have it, you can get the source code from https://github.com/gregkh/usbutils/ and build it yourself. The idea is that you start with old_scheme_first set to N, plug in the device, check that bNumConfigurations is 1 in the "lsusb -v" output, set old_scheme_first to Y, and then use usbreset to reset the device. If bNumConfigurations changes to 2, you'll know that the reset caused the device to go into its other mode.
> The idea is that you start with old_scheme_first set to N, plug in the device, check that bNumConfigurations is 1 in the "lsusb -v" output, set old_scheme_first to Y, and then use usbreset to reset the device. If bNumConfigurations changes to 2, you'll know that the reset caused the device to go into its other mode. Unhopefully, that doesn't seem to work. I really need to turn off/turn on the device to get the proper `bConfigurationValue`s ``` # echo N >/sys/module/usbcore/parameters/old_scheme_first # cat /sys/module/usbcore/parameters/old_scheme_first N # lsusb -v -d 22f0:0008~ | grep bConfiguration bConfigurationValue 1 # echo Y >/sys/module/usbcore/parameters/old_scheme_first # cat /sys/module/usbcore/parameters/old_scheme_first Y # usbreset 22f0:0008 Resetting Xone:23C ... ok # lsusb -v -d 22f0:0008~ | grep bConfiguration bConfigurationValue 1 ## Here, I unplug the device without restarting it # lsusb -v -d 22f0:0008~ | grep bConfiguration bConfigurationValue 1 ## Here, I restart the device without unplugging it # lsusb -v -d 22f0:0008~ | grep bConfiguration bConfigurationValue 1 bConfigurationValue 2 ```
"Unplug" is clear enough. What do you mean by "restarting" the device? Is this something the kernel could do automatically? Would a usbmon trace of a restart show anything useful? What happens if you restart the device while old_scheme_first is N?
By restarting I mean turning off and on again, using the power button. > What happens if you restart the device while old_scheme_first is N? Not much: # echo N >/sys/module/usbcore/parameters/old_scheme_first # cat /sys/module/usbcore/parameters/old_scheme_first N # lsusb -v -d 22f0:0008~ | grep bConfiguration # lsusb -v -d 22f0:0008~ | grep bConfiguration bConfigurationValue 1 ## Here I turn offf and on again # lsusb -v -d 22f0:0008~ | grep bConfiguration bConfigurationValue 1
It looks like Linux is unable to discover all possible configurations using new scheme. BTW, do I understand `old_scheme_first` correctly? Linux will try *both* old and new scheme but only the order changes? Then in which cas does the other scheme is tried?
It's a little unfair to say that the kernel is unable to discover all the configurations. It's more accurate to say that the device tells the kernel there is only one configuration. Yes, the kernel tries both initialization schemes if necessary, changing from one scheme to the other if the first scheme doesn't work. old_scheme_first merely determines which scheme gets tried first.
> It's a little unfair to say that the kernel is unable to discover all the configurations I didn't meant to undermine the work of the kernel devs, I'm sorry. > the kernel tries both initialization schemes if necessary, changing from one scheme to the other if the first scheme doesn't work. What do you mean by "*doesn't work*" here? Does discovering a configuration (but only one) counts as working? Is there a way for me to try to replicate bith scheme steps manually?
The two schemes are methods for initializing the device. This happens before the configuration information is transferred, because the kernel can't communicate with the device until it has been initialized. The scheme works if the kernel is able to communicate without getting any errors. If the device then says it has only one configuration, the kernel will believe it. While it is possible in theory to replicate the initialization schemes manually, in practice it would be very difficult and it would require a large amount of programming. If you want to experiment with the schemes, by far the easiest way is to patch the kernel to make it do what you want. For example, you could change the kernel so that when it encounters a device with the Xone:23C's vendor and product IDs, it sets the number of configurations to 2. Then it would ask the device to transfer the information for both configs. But most likely the device would refuse to send the information for the second config, because it is still in its single-configuration mode.
OK. Is there anything left we can try to improve the situation without resorting to use the `usbcore.old_scheme_first=1` kernel param?
I can't think of anything else to try. Except maybe to get some helpful information from the manufacturer.
Created attachment 306707 [details] Working patch with old_scheme_first set to N So I did what you suggested and got this code that works. Turns out the device expects to be provided an adress before being requested a descriptor. I don't know what to do about it though…
(Working means it detects the correct number of possible configurations with new scheme but that code breaks the USB protocol on my computer)
There isn't really anything we can do to help. We can't change the existing behavior very much without running the risk that a lot of other devices will stop working. One thing we could do is create a special case that would add extra handling for the Xone:23C. But the kernel can't tell that the device is an Xone:23C before asking for the device descriptor, so that won't help. I still wonder how Windows manages to make the device work. The packet captures from Wireshark don't show everything that's going on.
Created attachment 306709 [details] Second try to capture USB packets on Windows with Wireshark Ok, I really think I messed up the first Wireshark capture and I captured something else. This capture seems to make much more sense as I can see the device identify itself as an Allen&Heath product. Tell me if t provides more useful informations.
I think I can see from this capture that it still declares `bConfigurationValue` == 1 but also declares several interfaces in the GET DESCRIPTOR Response CONFIRURATION packet of size 322. What does it declare here?
The really important thing is bNumConfigurations. If it is set to 1 then the device doesn't make config 2 available, but if it is set to 2 then the device does make config 2 available (even if the computer decides to use config 1). The configuration descriptor includes four interfaces. Interface 0 is the audio control interface; it describes two USB terminals (one in, one out) and two audio terminals (one in, one out). It also says that the input terminals each have 2 channels (regular stereo). Interfaces 1 and 2 are for audio streaming. Interface 1 is the USB-out connection; it runs at 48000 Hz with 24-bit samples, it can be synchronized to a clock on the device, and it can also operate in a vendor-specific way. Interface 2 is the USB-in connection; it also runs at 48000 Hz with 24-bit samples and it also has a vendor-specific alternate setting. Interface 3 is for MIDI. As far as I can see, you aren't using it. The packet capture shows the computer issuing a few vendor-specific requests. I have no way to know what they mean, but they involve getting data from the device, not sending data to the device. So they probably don't affect the way the device operates. The thing we really need to know is how the Windows driver tells the device to switch to configuration 2. I haven't seen anything in the packet captures that show how it does this. (However, the most recent capture shows that at the 361-second mark, the computer deconfigures the device and the sets it back to configuration 1. I can't tell why that happened.) Or maybe the Windows driver uses the vendor-specific alternate settings rather than the standard USB audio class settings. The packet captures don't show the computer telling the device which alternate setting to use. This must happen, because the default setting uses no bandwidth and transfers no audio data, but it doesn't show up in the packet captures. (It does show up in the usbmon traces.)
One thing you could try is to submit a help request on the Allen & Heath web site. They might be able to provide some useful information.