arkq / bluez-alsa

Bluetooth Audio ALSA Backend
MIT License
854 stars 188 forks source link

No sound with HFP with USB BCM20702A1 adapter #400

Closed xyzzy42 closed 1 year ago

xyzzy42 commented 3 years ago

I'm using a BCM20702A1 USB BT interface attempting to get HFP working on some Bose QC-35 headphones. A2DP is working, but aplay with SCO just produces silence of the appropriate length. The bluealsa log doesn't indicate any errors. arecord never receives any data and hangs.

I've tested with another BT adapter, BCM4345C5, which is connected over a UART (with wifi on sdio) and that does work in HFP mode, both playback and recording. Audio quality is vastly improved over a Macbook Air mid-2012 that doesn't seem to support wide band voice in HFP.

It seems like this is very similar to #258, but that was fixed with a commit to configure broadcom adapters to use the hci interface for audio instead of an I2S interface. It does appear that the code in fix is active:

bluealsa: D: sco.c:166: Checking Broadcom internal SCO routing
bluealsa: D: sco.c:172: Current SCO interface setup: 1 2 0 1 1
bluealsa: D: sco.c:200: Created SCO dispatcher [ba-sco-dispatch]: hci0

Once SCO playback is started, I get these messages from the kernel:

Bluetooth: hci0: Device does not support ALT setting 6
Bluetooth: hci0: urb 00000000a9df4129 submission failed (90)
Bluetooth: hci0: urb 00000000a9df4129 submission failed (90)
Bluetooth: hci0: sending frame failed (-90)

The last two messages then repeat constantly.

xyzzy42 commented 3 years ago

It might be possible that this USB BT adapter just doesn't support mSBC. Apparently ALT mode 6 is supposed to be used for mSBC over USB.

I disabled mSBC support in bluealsa, and then this time I remember to run the recompiled src/bluealsa instead of the system installed bluealsa. With only 8kHz CVSD sound available, it worked. Audio quality is poor of course.

It would be nice if there was a way to discover if the BT adapter can do WBS or not. I also see a hack to get a realtek chipset to use alt1 for mSBC. Perhaps that can work.

Doesn't really seem like a bluealsa bug, unless those -90 errors are making there way back to bluealsa and it is ignoring them.

xyzzy42 commented 3 years ago

Hacking the btusb driver to use alt1 instead of alt6 was able to produce audio!

But it sounds bad. Too loud and with a hiss in the background. It sounds better with the correctly functioning bt adapter. So I suspect there is still some problem.

borine commented 3 years ago

Bluetooth: hci0: Device does not support ALT setting 6

Yes, that requirement for USB was introduced in Linux 5.8 - see https://github.com/Arkq/bluez-alsa/issues/343

The Bluetooth Core spec does require Alt6 for mSBC : it is the only way to get correct SCO timing on isochronous links with USB. Previously the btusb module was completely unaware of mSBC, so USB adapters gave very poor mSBC audio quality as SCO packets were fragmented or dropped. Not all USB adapters have Alt6 implemented. I too have a BCM20702A1 adapter and can confirm that it does not have Alt6.

Unfortunately, bluealsa would need to be modified to use mSBC with kernels >= 5.8; at present it uses the wrong socket MTU (24 bytes). It should be 60 bytes. It is not a trivial change because btusb does not provide a "capabilities" API so I don't know how bluealsa can determine whether mSBC support is available or not. Trying to deduce from the reported kernel version/revision is just not reliable.

xyzzy42 commented 3 years ago

Is it not possible to use another alt setting? There is now a patch from Realtek that uses alt 1 for one of their devices in the kernel.

For socket MTU, there is a pending patch from chromeos that provides a ioctl to get the MTU from SCO socket. Would that solve the problem?

borine commented 3 years ago

In the Bluetooth Core Specification, Volume 4, section 2.1.1, Table 2.1: USB Primary firmware interface and endpoint settings, the "Recommended" Host Controller endpoint setting for mSBC voice is Alternate 6. So hardware manufacturers that follow the recommendations will use that. Its possible that a specific Realtek adapter ignores that recommendation, but it would then require a vendor-specific "quirk" in the driver for correct communication between the driver and the firmware. I think that in general, a USB BT adapter will require the driver to use Alternate Setting 6 for correct timing of mSBC SCO packets across the HCI. Adapters that do not implement Alt6 are not (in general) capable of supporting mSBC.

The chromeos patch looks promising. The Linux btusb module currently reports either the controller buffer size or a fixed "quirk" value of 64 for the socket MTU. Neither is usefui to an application. An application needs to know the USB mtu (48 for CVSD, 60 for mSBC) and it would appear on a quick reading of the patch you link above that it will (finally!) implement that.

I'm not sure that the application will yet be correctly informed when mSBC is not available, but at least when it is available then the correct MTU of 60 will be reported. In addition, the correct MTU of 48 for CVSD should also be reported and that would simplify the coding for bluealsa (and pulseaudio).

So possibly proper Linux support for USB mSBC is coming soon (hurrah), But at present (IMHO) the best advice for bluealsa is to use only CVSD on USB adapters. UART adapters should work quite well with mSBC (but bluealsa still lacks packet-loss-concealment, so requires an error-free bluetooth baseband link for glitch-free audio).

xyzzy42 commented 3 years ago

it would then require a vendor-specific "quirk" in the driver for correct communication between the driver and the firmware.

That would be the quirk flag BTUSB_USE_ALT1_FOR_WBS that is set for Realtek adapters.

But my real question was why settings other than alt 6 can't work. Isn't it possible to use multiple smaller packets to achieve the necessary data rate?

xyzzy42 commented 3 years ago

It would be nice if there was a way with the ALSA device specification to select NBS and CVSD even if WBS is supported, in cases where it doesn't work. Yes one can recompile with mSBC disabled, but a runtime select per device would be nice. Especially for people who just install a distro package.

arkq commented 3 years ago

There is runtime selection, but without any convenient tool. You can use D-Bus call directly. Do as follows:

gdbus call --system -d org.bluealsa \
  -o /org/bluealsa/hci0/dev_1C_48_F9_9D_81_5C/hfpag/source \
  -m org.bluealsa.PCM1.SelectCodec CVSD '{}'

Correct object path you can find by issuing this:

gdbus call --system -d org.bluealsa -o /org/bluealsa -m org.bluealsa.Manager1.GetPCMs

The list of available codecs query with:

gdbus call --system -d org.bluealsa \
  -o /org/bluealsa/hci0/dev_1C_48_F9_9D_81_5C/hfpag/source \
  -m org.bluealsa.PCM1.GetCodecs

Reference: https://github.com/Arkq/bluez-alsa/blob/master/doc/bluealsa-api.txt#L44

borine commented 3 years ago

But my real question was why settings other than alt 6 can't work. Isn't it possible to use multiple smaller packets to achieve the necessary data rate?

well, they can work, as evidenced by Realtek, but it requires cooperation from the firmware which is invariably a proprietary binary blob.

USB isochronous links are "clocked" at 1 millisecond. How much data can be packed into a single transfer depends on the allocated bandwidth for the endpoint, which in turn is determined by the "Alternate" setting. The examples in the Bluetooth Core spec section referenced in previous comment explain the consequences for SCO quite well. If you read the spec and do the math, you find that Alt-1 gives 24 bytes per HCI packet, Alt-6 gives 60 bytes.

Now it just happens that an mSBC frame is 60 bytes, so Alt-6 is the most efficient choice and is recommended by the Bluetooth SIG.

Now imagine you choose Alt-1. You have to fragment 60 bytes into chunks of 24 bytes. If the controller has a large enough buffer, it can read 5 USB frames (120 bytes of payload) and assemble them into 2 mSBC frames. If the buffer is not large enough (a typical value for USB adapters that do not have Alt-6 is just 64 bytes) then it will fail. Maybe Realtek use large buffers, or maybe they implement a circular buffer. I don't know. But I do know from experience that using a socket MTU of 24 for mSBC with USB adapters and Alternate 1 does give extremely poor results; and using a larger MTU can cause the driver and/or firmware to lock up completely.

xyzzy42 commented 3 years ago

So the issue is that the firmware, only implementing up to alt 5 with 49 byte packets, probably does not have a buffer large enough to assemble a full 60 byte mSBC frame nor the logic to assemble multiple iso slots into a single frame even if it did have the space.

The datasheet for the CYW20702 does have a section on WBS, but only over the PCM interface.

■ On-chip SmartAudio® technology: The CYW20702 can perform Subband-Codec (SBC) encoding and decoding of linear 16 bits at 16 kHz (256 kbps rate) transferred over the PCM bus.

I wonder if it would be possible to use non-transparent SCO mode to send PCM, as in CVSD, but get the chip to encode to mSBC? Or maybe that only works over the PCM interface. It would probably require some secret vendor specific command to enable.

arkq commented 3 years ago

It might be vendor specific, but BlueALSA already uses vendor specific HCI command to "fix" configuration for Boradcom chips. The same setup might work for Cypress, after Cypress acquired Broadcom (patch is not in the master branch, though). So, switching to PCM interface is not a problem. But then, where should I write PCM data? Where is this PCM interface exposed in Linux?

borine commented 3 years ago

The PCM interface is a separate hardware interface (different pins on the chip package) and not part of the USB interface. So for external plug-in USB adapters it is not accessible. With on-board designs it may be wired to some GPIO pins, in which case you would need an ALSA driver to present the chip to the kernel as a sound card. However, most PC designs, I think, do not connect these pins at all, so you would need a soldering iron to get access!

arkq commented 3 years ago

so you would need a soldering iron to get access!

Yeah, basically that was my point :)

xyzzy42 commented 3 years ago

In theory one could connect an I2S DAC or ADC directly to the PCM interface on the BT chip and transfer the audio directly without the CPU being needed. Maybe a BT headset does this, but I've never seen it done in a device I've worked on, which have all run Linux (or VxWorks). It takes more pins. You need a spare I2S interface on the SoC. Bitbanging I2S over a GPIO wouldn't be feasible in Linux, since the data and frame clock needs to be synced to the MCLK which is probably about 2-8 MHz and good luck bitbanging a 4 MHz clock in Linux.

Well, long ago one could do that in kernel space. But the GPIO layer has gotten a lot slower since then.

But my thought was not using the PCM interface, but rather the BRCM20702A's ability to do the mSBC encoding itself. Maybe it's possible to send uncompressed 16 kHz audio over a USB non-transparent SCO pipe and have it compressed in the chip.

xyzzy42 commented 3 years ago

If you read the spec and do the math, you find that Alt-1 gives 24 bytes per HCI packet, Alt-6 gives 60 bytes.

I've now read lots of specs, but I'm not finding this math. Alt-1 for 24 bytes appears to be derived from 9 bytes/packet 3 packets/frame - 3 bytes HCI header. I don't see where the 3 packet/frame comes from. The BRCM20702A is a FS device. Every spec I've seen seems to be clear that FS devices can request iso packets up to 1023 bytes and at most 1 packet per frame*. If it was a HS device, then it's allowed iso packets up to 1024 bytes and up to 3 packets per microframe.

Is that 24 byte MTU only applicable to HS "High Bandwidth" endpoints that allow 3 packets per microframe? And thus does not apply to the BRCM20702A.

If that's the case, then it seems like that ChromeOS patch isn't right, as it assumes 3 packets. It also seems like assuming the alt modes have the "recommended" sizes isn't really correct either and it should be checking the wMaxPacketSize field of the endpoint descriptor to get the real packet size and number limit.

xyzzy42 commented 3 years ago

I got it working on the BRCM20702A adapter.

btusb must be modified to place the adapter into an alt mode 1 or 2 for transparent SCO. blue-alsa must use a socket MTU of (packetsize * 3 - 3) bytes. In alt1 this results in 27 byte URBs that fit in exactly 3 alt-1 iso packets of 9 bytes. In alt2 it results in 51 bytes in 3 packets of 17 bytes. Then it works.

Audio sounds the same as mSBC with a UART based BT adapter. 16 KHz mono over WBS is considerable louder than the same audio, also 16 kHz, over A2DP(SBC), but perhaps that is an issue with the QC35's DSP or volume setting effect in A2DP vs HSP.

I tried other alt mode and mtu combinations, but everything else results in silence. I tried 15 bytes so it would take exactly 2 alt mode 1 packets and 33 bytes so it would take exactly 4, but like the holy hand grenade of antioch, four packets shalt thou not send, neither send thou two, excepting that thou then proceed to send three. I didn't try 42 bytes, as five packets is clearly right out.

Alt mode 2 works, again with the MTU set for exactly 3 packets.

In alt mode 3, a three packet MTU would be 72 bytes. This results in "bluealsa: E: SCO write error: Invalid argument" errors. I tried a 47 byte mtu, for 2 packets, but that just produces silence.

borine commented 3 years ago

@xyzzy42 I think that's an impressive piece of work. If there's any way you could persuade the btusb developers to take note and implement this upstream that would be a fantastic contribution.

xyzzy42 commented 3 years ago

I got another USB BT adapter, this one with a Realtek RTL8167B chip. One would think, since Realtek are the ones who provided the patch to try alt mode 1, that it would work, but no. This adapter is missing alt mode 6 too. In alt mode 1 it appears bluealsa must be configured to use a 24 byte MTU. Any other MTU results in no audio. There is sound, but it's very broken. Constantly stuttering. I can get alt 2 to produce sound with a 48 byte MTU, like with the brcm adapter, but the audio is even more broken up than with alt 1. There seems to be a bug with the adapter's driver that causes a kernel panic if the module is unloaded and reloaded. So I haven't tested it as much because it's such a pain.

I think I'll make a patch to make the fallback to alt 1 not realtek specific. It seems clear that the current code has no chance of working for adapters without alt 6. So far, all non-realtek adapters that do not support alt 6 do work with alt 1. Out of a sample size of one adapter. But it makes more sense to to me to have the logic be try alt 6, then try alt 1, and if an adapter is discovered that doesn't work that way, but does work another way, then make a quirk for that adapter.

borine commented 3 years ago

try alt 6, then try alt 1, and if an adapter is discovered that doesn't work that way, but does work another way, then make a quirk for that adapter.

I second that idea. It's just a shame that the original patch that introduced Alt-6 usage for Linux 5.8 didn't do it that way. If btusb would also report a SCO socket MTU that was useful to an application (i.e. the value(s) you have calculated) then I would be very happy :smiley:

xyzzy42 commented 3 years ago

Ordered two more BT USB adapters Friday, free Amazon delivery arrived Saturday, pretty impressive. Almost impossible to find out what chipset an adapter uses though. I want to find the elusive alt mode 6.

Realtek RTL8821C. Also no alt 6 support. Does work at alt 1 with 24 byte MTU. Unlike RTL8167B, sound is not all broken up.

And a CSR8510 adapter too. Same as above.

So out of two Realtek, one Broadcom, and one CSR adapter: zero support alt mode 6. All produce audio with 24 byte MTU at alt 1. One Realtek has bad sound, seems to be no way to fix it (short of adapter's fw).

I also see from btmon that SCO data RX occurs when using the alsa sink. I guess HFP can only do bidirectional sound? But what is interesting is that the packet size for RX appears to independent of the TX packet size. I wonder where this is set? Is it up the to bt adapter how it chooses to send the eSCO link's data over USB? If that's the case, then maybe it choosing 24 bytes for Rx is a good indication of what size should be used for TX too.

arkq commented 3 years ago

I also see from btmon that SCO data RX occurs when using the alsa sink. I guess HFP can only do bidirectional sound?

It all depends on the remote device logic. HFP/HSP is bidirectional, but headset or phone is not required to send any data. You can use two bluealsa-enabled devices to communicate to each other, and you might use only one direction at a time (if you like). But for the real case scenario, headset almost always sends microphone data, so if SCO link is established, you will get RX even though you are using ALSA in a playback mode.

But what is interesting is that the packet size for RX appears to independent of the TX packet size. I wonder where this is set? Is it up the to bt adapter how it chooses to send the eSCO link's data over USB? If that's the case, then maybe it choosing 24 bytes for Rx is a good indication of what size should be used for TX too.

Once I thought about such solution, but the problem is that RX is not guaranteed to be there. So, such a solution would be a heuristic at best.

borine commented 3 years ago

The patch https://lore.kernel.org/patchwork/patch/1265703/ is shown as "accepted" which I guess, means it will soon appear in the mainline kernel tree? So then it becomes a matter of applying BTUSB_USE_ALT1_FOR_WBS to the driver info for a particular device in order to get btusb to use Alt 1 for mSBC on that device instead of trying (and failing) with Alt 6. Hopefully It won't be too long before this flag is added to all appropriate devices. Then at least we should be back in the same state as before Alt 6 support was first introduced !

The patch https://lore.kernel.org/patchwork/patch/1303071/ is shown as "superseded". I don't know what that means, but I guess we will have to wait a little longer for that to be accepted. When it is, then SCO_OPTIONS (or the newer BT_SNDMTU/BT_RCVMTU) should reveal the correct MTU for the application to use.

So It seems that we are still in a waiting game for btusb to implement the functionality needed by SCO audio, but at least development is heading in the right direction now and hopefully 2021 will see the desired result.

xyzzy42 commented 3 years ago

The ALT1_FOR_WBS patch went into the kernel in v5.9-rc1, as commit 461f95f04f19, so it is already in 5.9 kernel. I think the quirk is unneeded. The patch is from Realtek, so by default they only want it to apply to Realtek hardware. They would not even ask, "Is this something that applies to all USB BT adapters?"

Superseded means a new series has replaced it. In this case, it is v3 of that series at (https://marc.info/?l=linux-bluetooth&m=159971791610689&w=2). For some reason I can't find that series on patchwork.

borine commented 3 years ago

I think the quirk is unneeded

            if (btusb_find_altsetting(data, 6)) {
                data->usb_alt6_packet_flow = true;
                new_alts = 6;
            } else if (test_bit(BTUSB_USE_ALT1_FOR_WBS, &data->flags)) {
                new_alts = 1;
            } else {
                bt_dev_err(hdev, "Device does not support ALT setting 6");
            }

My reading of the above is that without the quirk, btusb will report an error if the adapter does not support Alt6; with the quirk it will use Alt1 instead. So, I think, every adapter that is to use Alt1 for mSBC requires the quirk to be added in the driver info table.

In the revised second patch you have linked above, in addition to fixing the SCO MTU, the following hunk removes the need for the quirk to be included in the device_info table:

+       if (btusb_find_altsetting(data, 1)) {
            set_bit(BTUSB_USE_ALT1_FOR_WBS, &data->flags);
-       else
+           hdev->sco_mtu = hci_packet_size_usb_alt[1];
+       } else
            bt_dev_err(hdev, "Device does not support ALT setting 1");

So when/if that patch is accepted into mainline, bluealsa (and pulseaudio) will have what they need for mSBC on a USB bus.

The only outstanding issue is, how does an application know if that patch is applied to the running kernel?

arkq commented 3 years ago

The only outstanding issue is, how does an application know if that patch is applied to the running kernel?

I think that it will not be necessary to detect it. We might assume that for mSBC via USB, this patch is a prior requirement (hence kernel => x.x.x). If user knows, that the driver reports invalid MTU (kernel version is below this number and patch is not backported), there might be a command line flag to use fixed bluez-alsa built-in MTU.

jemershaw commented 3 years ago

I wanted to check to see if I'm experiencing the same issue. The profiles I am able to use are a2dp, hfp(mic) but hfp(speaker) doesn't play the audio.

When I try to play the sound clip using the command aplay -v -D bluealsa:DEV=...,PROFILE=sco sound.wav.

This is the output from bluealsa debug

bluealsa: D: ../../src/dbus.c:59: Called: org.bluealsa.Manager1.GetPCMs() on /org/bluealsa
bluealsa: D: ../../src/dbus.c:59: Called: org.bluealsa.PCM1.Open() on /org/bluealsa/hci1/dev_.../hfpag/sink
bluealsa: D: ../../src/ba-transport.c:976: New SCO link: ...: 20
bluealsa: D: ../../src/hci.c:132: SCO link socket MTU: 20: 64
bluealsa: D: ../../src/msbc.c:72: Initializing mSBC encoder/decoder
bluealsa: D: ../../src/ba-transport.c:801: PCM resumed: 16
bluealsa: D: ../../src/ba-transport.c:829: PCM drained: 16
bluealsa: D: ../../src/ba-transport.c:835: PCM dropped: 16
bluealsa: D: ../../src/ba-transport.c:835: PCM dropped: 16
bluealsa: D: ../../src/ba-transport.c:1018: Closing PCM: 16
bluealsa: D: ../../src/msbc.c:72: Initializing mSBC encoder/decoder
bluealsa: D: ../../src/msbc.c:72: Initializing mSBC encoder/decoder
bluealsa: D: ../../src/sco.c:328: Releasing SCO due to PCM inactivity
bluealsa: D: ../../src/ba-transport.c:994: Closing SCO: 20
bluealsa: D: ../../src/msbc.c:72: Initializing mSBC encoder/decoder

I also get this error code in the kernel.

[116266.433721] Bluetooth: hci1: SCO packet for unknown connection handle 42
[116266.433723] Bluetooth: hci1: SCO packet for unknown connection handle 42
[116349.282347] Bluetooth: hci1: SCO packet for unknown connection handle 42
[116349.282350] Bluetooth: hci1: SCO packet for unknown connection handle 42
[116349.282351] Bluetooth: hci1: SCO packet for unknown connection handle 42
[116349.282352] Bluetooth: hci1: SCO packet for unknown connection handle 42

Please let me know if you need any information to debug further.

xyzzy42 commented 3 years ago

What kernel version? Is the bluetooth adapter USB based?

Run lsusb -v, find your bluetooth adapter, and then look at the Interface Descriptors that appear under it, they have lines like these (only some lines shown):

    Interface Descriptor:
      bInterfaceNumber        1
      bAlternateSetting       1
      bInterfaceProtocol      1 Bluetooth
      Endpoint Descriptor:
          Transfer Type            Isochronous
        wMaxPacketSize     0x0009  1x 9 bytes

What's the highest AlternateSetting and MaxPacketSize it goes up to?

jemershaw commented 3 years ago

Thanks for the help!

I am running kernel version 5.4.0-56-generic and yes it is USB based I tried the onboard but it didn't support the mic codec I believe.

Here's the output for the AlternateSettings/MaxPacketSize.

Device Descriptor:
  Configuration Descriptor:
    Interface Descriptor:
      bAlternateSetting       0
      Endpoint Descriptor:
        wMaxPacketSize     0x0010  1x 16 bytes
      Endpoint Descriptor:
        wMaxPacketSize     0x0040  1x 64 bytes
      Endpoint Descriptor:
        wMaxPacketSize     0x0040  1x 64 bytes
    Interface Descriptor:
      bAlternateSetting       0
      Endpoint Descriptor:
        wMaxPacketSize     0x0000  1x 0 bytes
      Endpoint Descriptor:
        wMaxPacketSize     0x0000  1x 0 bytes
    Interface Descriptor:
      bAlternateSetting       1
      Endpoint Descriptor:
        wMaxPacketSize     0x0009  1x 9 bytes
      Endpoint Descriptor:
        wMaxPacketSize     0x0009  1x 9 bytes
    Interface Descriptor:
      bAlternateSetting       2
      Endpoint Descriptor:
        wMaxPacketSize     0x0011  1x 17 bytes
      Endpoint Descriptor:
        wMaxPacketSize     0x0011  1x 17 bytes
    Interface Descriptor:
      bAlternateSetting       3
      Endpoint Descriptor:
        wMaxPacketSize     0x0019  1x 25 bytes
      Endpoint Descriptor:
        wMaxPacketSize     0x0019  1x 25 bytes
    Interface Descriptor:
      bAlternateSetting       4
      Endpoint Descriptor:
        wMaxPacketSize     0x0021  1x 33 bytes
      Endpoint Descriptor:
        wMaxPacketSize     0x0021  1x 33 bytes
    Interface Descriptor:
      bAlternateSetting       5
      Endpoint Descriptor:
        wMaxPacketSize     0x0031  1x 49 bytes
      Endpoint Descriptor:
        wMaxPacketSize     0x0031  1x 49 bytes
jemershaw commented 3 years ago

It does seem like it is the same problem -- I just removed --enable-msbc and now when I record I'm able to hear using sco the playback is choppy but it works.

xyzzy42 commented 3 years ago

It's something different, as that kernel should not be trying to use alt mode 6. Though it is probably related to how the eSCO channel is used. Could be MTU related. What chip does the adapter use?

jemershaw commented 3 years ago

It is using CSR8510.

joakim-tjernlund commented 3 years ago

CSR may require an 5.9 kernel, https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/drivers/bluetooth/btusb.c?h=linux-5.9.y&id=cde1a8a992875a7479c4321b2a4a190c2e92ec2a

joakim-tjernlund commented 3 years ago

This one seems important for many USB BTs:

https://patchwork.kernel.org/project/bluetooth/patch/20201210012003.133000-1-tpiepho@gmail.com/

xyzzy42 commented 3 years ago

The latter is my patch to fix this, which doesn't seem to be taken up yet.

However, I think @jemershaw has a different problem.

  1. Kernel 5.4 should use alt 1, which works. It is kernel 5.8+ that is broken.
  2. The kernel 5.8+ bug should spam URB submission failures. It will use alt 0, which has a 0 byte max size, so every packet will be too big to send.
  3. CSR8510 should work. My "Sabrent" branded CSR8510 does.
  4. The apparent proper MTU is 24, and that is what current blue-alsa uses.

So it's something else. It could be related to the patch for kernel 5.9 for fake CSR8510 chips. Tracing both the bluetooth with btmon and usb with wireshark might help.

joakim-tjernlund commented 3 years ago

@xyzzy42 , I saw you discussing adding proper MTU support for ALT 1 vs. ALT 6 too. Do you have anything you can post ? Seems to be the last missing piece for USB BT mSBC on odd adapters.

xyzzy42 commented 3 years ago

I've yet to find a BT adapter that supports ALT 6. So what bluez-alsa does now by assuming 24 byte MTU should work most of the time. Someone else had created a patch, referenced in this thread earlier, to add the support needed for getting both alt1 and alt6 MTU detectable by bluez-alsa. But my understanding was that it had a flaw, where the alt mode choice was made, and the author has yet to rework it to fix that. So I don't think that has been re-submitted for 5.11 at this point. But unless you happen to have one of the alt 6 USB BT adapters, this isn't necessary.

joakim-tjernlund commented 3 years ago

But an app should not need know this and be able to trust MTU given by the kernel. Not all BT adapters are USB too

xyzzy42 commented 3 years ago

It doesn't seem to matter for UART based BT adapters, as they don't have to packetize the data over the UART link. I don't know about SDIO adapters, never seen one used.

Certainly the MTU should be reported correctly. But it appears the current behavior of bluez-alsa will almost always work once the bug in kernel 5.8+ is fixed.

joakim-tjernlund commented 3 years ago

There seems to be quite a few USB controllers gaining the BTUSB_WIDEBAND_SPEECH which I guess means HW mSBC but currently there is no way to select this mode. Any idea if one could patch the kernel to default to HW mSBC and user apps like bluealsa/pulseaudio would just use it automatically?

xyzzy42 commented 3 years ago

I've never seen documentation that explains the slightest bit about how one might get hardware mSBC on USB. The chip makers keep their firmware docs secret. Even when I worked on devices that had a Wifi/BT chip, we never got any documentation.

joakim-tjernlund commented 3 years ago

Seems like you ALT 1 patch has been accepted now, I don't see any stable keywords there so not sure it will make it to 5.10.x ?

xyzzy42 commented 3 years ago

No, it's not queued for 5.8 - 5.10 stable. Do you know of any bugs, besides this one I reported, about this? I could forward to stable but it would be better if there was already a Fedora/Debian/Ubuntu/Arch etc. bug report that this fixes.

joakim-tjernlund commented 3 years ago

I don't know of any other report. Best to forward to stable so all get this fix.

sheepdestroyer commented 3 years ago

@xyzzy42 As this patches fixes a regression, it should be marked as such and backported to stable trees.

https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/572 https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/568

progandy commented 3 years ago

@xyzzy42 The patch will be in 5.12 and has been backported to Linux 5.10.18 and 5.11.1 https://lore.kernel.org/lkml/161409305750190@kroah.com/ https://lore.kernel.org/lkml/1614088759150127@kroah.com/

Trent Piepho (1): Bluetooth: btusb: Always fallback to alt 1 for WBS

sgala commented 3 years ago

Just a FYI:

Thanks!

pv commented 3 years ago

bluetooth-next seems to have merged a patch that switches it to ALT 3, https://lore.kernel.org/linux-bluetooth/ca3adcf5fd1e7afa923f445d391aaa00f335c470.camel@iki.fi/T/#mc65bdf1658e19e511bb28dc604e21643eec5e054 This seems to break things... In principle one could now do

diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index a9855a2dd561..c73d372a9159 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -1763,9 +1763,11 @@ static void btusb_work(struct work_struct *work)
                        /* Because mSBC frames do not need to be aligned to the
                         * SCO packet boundary. If support the Alt 3, use the
                         * Alt 3 for HCI payload >= 60 Bytes let air packet
-                        * data satisfy 60 bytes.
+                        * data satisfy 60 bytes. USB Alt 3 support also needs
+                        * HFP transparent MTU >= 72 Bytes.
                         */
-                       if (new_alts == 1 && btusb_find_altsetting(data, 3))
+                       if (new_alts == 1 && btusb_find_altsetting(data, 3) &&
+                           hdev->sco_mtu >= 72)
                                new_alts = 3;
                }

to at least make sure the MTU is not smaller than the "packet size", but I suspect ALT3 should be behind a quirk, as it seems at least Intel 8087:07dc which has large enough mtu produces garbled audio output (but hard to be sure since the device has problems with pairing w/ current kernels/firmware, and also ALT1 no longer works on current kernels)...

pv commented 3 years ago

Patch: https://patchwork.kernel.org/project/bluetooth/patch/b86543908684cc6cd9afaf4de10fac7af1a49665.camel@iki.fi/

sayap commented 3 years ago

I use pipewire and have intel 8087:0a2b, and the patch above fixed the garbled audio issue when using msbc with kernel >=5.13.3. Thanks!

xyzzy42 commented 2 years ago

I've got access to a wideband BT+USB HCI sniffer for a bit and revisited this. The RTL8167B is the one adapter I have that didn't work.

It is being set to alt mode 3, 25 byte max packet size. Bluealsa is using: D: hci.c:141: USB adjusted SCO MTU: 28: 24. Each audio packet is sent on 2 USB frames. The first frame contains: Connection Handle 02 00

The 2nd frame is:

Probably not ideal here to be splitting the 24 bytes across two frames. The data is valid mSBC, which can be extracted from the USB HCI capture and sounds fine. As does the incoming audio also present in the USB capture. I didn't tell bluealsa to record, but the audio comes in anyway.

The bluetooth side is not correct. In the central/master to peripheral/slave slot, there is just a POLL packet. No data. In the following slot (peripheral -> center), there is a 2-EV3 packet with 60 bytes of data payload (65 bytes total size with header + CRC). These packets contain a valid incoming mSBC audio stream.

So for whatever reason the BT adapter has decided it's just not going to send the audio out on the air at all. Maybe it doesn't like how it's split across two USB frames. Or maybe there is some command to tell it to get audio from USB rather than an I2S PCM interface.