Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RTL8822CE] SCO with msbc codec enabled requires source code patching to deliver audio to headset #637

Closed
yegor-alexeyev opened this issue May 28, 2023 · 4 comments · Fixed by #638

Comments

@yegor-alexeyev
Copy link

yegor-alexeyev commented May 28, 2023

Problem

I have laptop with RTL8822CE chip(integrated wifi with bluetooth).
Also I have headset Avantree Aria Pro 2.
There is no sound played on a headset when msbc codec is turned on.

Receiving msbc data works fine though, I am able to hear audio received from headset microphone.

What I did to fix the issue. Using btmon I looked at the packet sizes which are delievered from MCU(direction which works fine).
They happened to be 72 bytes long. After that I used this value in the existing "USB adjusted SCO MTU" hack:

diff --git a/src/hci.c b/src/hci.c
index d30c50f..a32fd9c 100644
--- a/src/hci.c
+++ b/src/hci.c
@@ -138,7 +138,7 @@ unsigned int hci_sco_get_mtu(int sco_fd, int hci_type) {
        if ((hci_type & 0x0F) == HCI_USB) {
                options.mtu = 48;
                if (voice.setting == BT_VOICE_TRANSPARENT)
-                       options.mtu = 24;
+                       options.mtu = 72;
                debug("USB adjusted SCO MTU: %d: %u", sco_fd, options.mtu);
        }

This worked!
I hope this report could be helpful to prepare a generic fix to this problem.
Ask if you need more information.

Reproduction steps

start blualsa service using command:

/usr/bin/bluealsa --codec=msbc -p hfp-ag"

connect bluetooth headset, and try play audio to the connected headset:

aplay -D pcm.bluealsa sample.wav"

Expected behaviour: sound could be heard from the headset.
Observed behaviour: No sound, only comfort noise.

Setup

Arch linux, kernel version 6.1.8-arch1-1
bluealsa version: v4.1.0-dirty (commit 165e15b)
bluez version: 5.66-1
aplay version: aplay: version 1.2.8 by Jaroslav Kysela

audio source: blueetooth MCU: RTL8822CE (integrated wifi with bluetooth, bluetooth is accessed through usb interface).
audio sink side: Avantree Aria Pro 2 headset

@borine
Copy link
Collaborator

borine commented May 28, 2023

See issue #622

We cannot simply change the mSBC mtu size for all adapters to be 72 bytes, because that value is specific to Realtek USB devices - and if you use a value bigger than 24 bytes with some USB adapters (for example my own QCA USB device) then it causes a hard lockup in the driver which requires a forced reboot to recover from. So we need a way to select different mtu values for different adapters. Right now the only known "safe" value that does not break any adapters is 24 bytes. However, as you have discovered, that value does not work with Realtek USB adapters nor some Intel M.2 adapters, but at least it does not break them.

@yegor-alexeyev yegor-alexeyev changed the title [RTL8822CE] SCO with msbc codec enables requires source code patching to deliver audio to headset [RTL8822CE] SCO with msbc codec enabled requires source code patching to deliver audio to headset May 28, 2023
@yegor-alexeyev
Copy link
Author

yegor-alexeyev commented May 29, 2023

There is one thing I don't understand. When I turn on msbc mode and start playing I can see that altconf=3 is chosen in MCU

yegor@huawei /sys/bus/usb/devices/usb3/3-3/3-3:1.1 cat /sys/bus/usb/devices/usb3/3-3/3-3:1.1/bAlternateSetting 
18:04:43
 3

But according to the output of lsusb, this altconfig has wMaxPacketSize = 1x 25 bytes

This does not match 72 bytes in options.mtu value. How does it work?

@borine
Copy link
Collaborator

borine commented May 29, 2023

How does it work?

The 72 bytes written by the application to the SCO scoket are sent to the HCI driver which adds a 3-byte header, so each application write actually results in 75 bytes being sent to the btusb driver. The btusb driver then creates a URB with 3 packets of 25 bytes each.

This appears to be very wasteful of USB bandwidth, as 72 bytes of mSBC represents 9ms of audio, but 3 USB packets only takes 3ms to transfer from host to controller. My knowledge of USB is very limited, so I don't know whether the unused 6ms bandwidth per 9ms elapsed time are wasted or are re-allocated to some other endpoint.

Compare this with a device that uses Alt-1. The application writes 24 bytes to the socket, and the HCI driver adds its 3 byte header, resulting in 27 bytes sent to USB. The btusb driver again creates a URB with 3 packets, this time 9 bytes each (wMaxPacketSize == 9 for Alt-1). Now 24 bytes mSBC == 3ms audio, and USB transfers 3 packets in 3ms. So all the available bandwidth is used, which with my limited understanding appears to be far more efficient. But for whatever reason btusb chooses Alt-3 for Realtek (and only Realtek at present) and the only way to change that is to patch the kernel code.

@yegor-alexeyev
Copy link
Author

Confirming, it works now without patching. Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants