Skip to content

Commit

Permalink
Fix mSBC MTU adjustment on Realtek USB adapters
Browse files Browse the repository at this point in the history
  • Loading branch information
borine authored and arkq committed Jun 1, 2023
1 parent 90cfbfa commit 142307d
Show file tree
Hide file tree
Showing 12 changed files with 41 additions and 11 deletions.
1 change: 1 addition & 0 deletions .github/spellcheck-wordlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ MPD
oFono
PipeWire
PulseAudio
Realtek
UPower

# Technical Words
Expand Down
5 changes: 5 additions & 0 deletions doc/bluealsa.8.rst
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,11 @@ OPTIONS
It will reduce the gap between playbacks caused by Bluetooth audio
transport acquisition.

--disable-realtek-usb-fix
Since Linux kernel 5.14 Realtek USB adapters have required **bluealsa** to
apply a fix for mSBC. This option disables that fix and may be necessary
when using an earlier kernel.

--a2dp-force-mono
Force monophonic sound for A2DP profile.

Expand Down
2 changes: 1 addition & 1 deletion src/ba-transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -887,7 +887,7 @@ static int transport_acquire_bt_sco(struct ba_transport *t) {

debug("New SCO link: %s: %d", batostr_(&d->addr), fd);

t->mtu_read = t->mtu_write = hci_sco_get_mtu(fd, d->a->hci.type);
t->mtu_read = t->mtu_write = hci_sco_get_mtu(fd, d->a);
t->bt_fd = fd;

return fd;
Expand Down
2 changes: 2 additions & 0 deletions src/bluealsa-config.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ struct ba_config config = {

.volume_init_level = 0,

.disable_realtek_usb_fix = false,

/* CVSD is a mandatory codec */
.hfp.codecs.cvsd = true,
#if ENABLE_MSBC
Expand Down
3 changes: 3 additions & 0 deletions src/bluealsa-config.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ struct ba_config {
/* the initial volume level */
int volume_init_level;

/* disable alt-3 MTU for mSBC with Realtek USB adapters */
bool disable_realtek_usb_fix;

struct {

/* available HFP codecs */
Expand Down
19 changes: 14 additions & 5 deletions src/hci.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
#include <bluetooth/hci_lib.h>
#include <bluetooth/sco.h>

#include "ba-adapter.h"
#include "bluealsa-config.h"
#include "shared/bluetooth.h"
#include "shared/log.h"

/**
Expand Down Expand Up @@ -110,10 +113,10 @@ int hci_sco_connect(int sco_fd, const bdaddr_t *ba, uint16_t voice) {
* Get read/write MTU for given SCO socket.
*
* @param sco_fd File descriptor of opened SCO socket.
* @param hci_type The type of the HCI returned by hci_devinfo().
* @param a The adapter associated with sco_fd.
* @return On success this function returns MTU value. Otherwise, 0 is returned and
* errno is set to indicate the error. */
unsigned int hci_sco_get_mtu(int sco_fd, int hci_type) {
unsigned int hci_sco_get_mtu(int sco_fd, struct ba_adapter *a) {

struct sco_options options = { 0 };
struct bt_voice voice = { 0 };
Expand All @@ -135,10 +138,16 @@ unsigned int hci_sco_get_mtu(int sco_fd, int hci_type) {

/* XXX: It seems, that the MTU value returned by kernel btusb driver
* is incorrect. */
if ((hci_type & 0x0F) == HCI_USB) {
if ((a->hci.type & 0x0F) == HCI_USB) {
options.mtu = 48;
if (voice.setting == BT_VOICE_TRANSPARENT)
options.mtu = 24;
if (voice.setting == BT_VOICE_TRANSPARENT) {
if (a->chip.manufacturer == 0)
hci_get_version(a->hci.dev_id, &a->chip);
if (!config.disable_realtek_usb_fix && a->chip.manufacturer == BT_COMPID_REALTEK)
options.mtu = 72;
else
options.mtu = 24;
}
debug("USB adjusted SCO MTU: %d: %u", sco_fd, options.mtu);
}

Expand Down
5 changes: 4 additions & 1 deletion src/hci.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
#include <bluetooth/hci.h> /* IWYU pragma: keep */
#include <bluetooth/hci_lib.h>

#include "ba-adapter.h"

int hci_get_version(int dev_id, struct hci_version *ver);

/**
Expand All @@ -36,7 +38,8 @@ int hci_get_version(int dev_id, struct hci_version *ver);

int hci_sco_open(int dev_id);
int hci_sco_connect(int sco_fd, const bdaddr_t *ba, uint16_t voice);
unsigned int hci_sco_get_mtu(int sco_fd, int hci_type);

unsigned int hci_sco_get_mtu(int sco_fd, struct ba_adapter *a);

#define BT_BCM_PARAM_ROUTING_PCM 0x0
#define BT_BCM_PARAM_ROUTING_TRANSPORT 0x1
Expand Down
6 changes: 6 additions & 0 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ int main(int argc, char **argv) {
{ "codec", required_argument, NULL, 'c' },
{ "initial-volume", required_argument, NULL, 17 },
{ "keep-alive", required_argument, NULL, 8 },
{ "disable-realtek-usb-fix", no_argument, NULL, 21 },
{ "a2dp-force-mono", no_argument, NULL, 6 },
{ "a2dp-force-audio-cd", no_argument, NULL, 7 },
{ "a2dp-volume", no_argument, NULL, 9 },
Expand Down Expand Up @@ -204,6 +205,7 @@ int main(int argc, char **argv) {
" -c, --codec=NAME\t\tset enabled BT audio codecs\n"
" --initial-volume=NUM\t\tinitial volume level [0-100]\n"
" --keep-alive=SEC\t\tkeep Bluetooth transport alive\n"
" --disable-realtek-usb-fix\tdisable fix for mSBC on Realtek USB\n"
" --a2dp-force-mono\t\ttry to force monophonic sound\n"
" --a2dp-force-audio-cd\t\ttry to force 44.1 kHz sampling\n"
" --a2dp-volume\t\t\tnative volume control by default\n"
Expand Down Expand Up @@ -379,6 +381,10 @@ int main(int argc, char **argv) {
config.keep_alive_time = atof(optarg) * 1000;
break;

case 21 /* --disable-realtek-usb-fix */ :
config.disable_realtek_usb_fix = true;
break;

case 6 /* --a2dp-force-mono */ :
config.a2dp.force_mono = true;
break;
Expand Down
5 changes: 2 additions & 3 deletions src/ofono.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
#include <unistd.h>

#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>

#include <gio/gio.h>
Expand Down Expand Up @@ -129,7 +128,7 @@ static int ofono_acquire_bt_sco(struct ba_transport *t) {
#endif

t->bt_fd = fd;
t->mtu_read = t->mtu_write = hci_sco_get_mtu(fd, t->d->a->hci.type);
t->mtu_read = t->mtu_write = hci_sco_get_mtu(fd, t->d->a);
ba_transport_set_codec(t, codec);

debug("New oFono SCO link (codec: %#x): %d", codec, fd);
Expand Down Expand Up @@ -820,7 +819,7 @@ static void ofono_agent_new_connection(GDBusMethodInvocation *inv, void *userdat
debug("New oFono SCO link (codec: %#x): %d", codec, fd);

t->bt_fd = fd;
t->mtu_read = t->mtu_write = hci_sco_get_mtu(fd, t->d->a->hci.type);
t->mtu_read = t->mtu_write = hci_sco_get_mtu(fd, t->d->a);
ba_transport_set_codec(t, codec);

pthread_mutex_unlock(&t->bt_fd_mtx);
Expand Down
2 changes: 1 addition & 1 deletion src/sco.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ static void *sco_dispatcher_thread(struct ba_adapter *a) {
pthread_mutex_lock(&t->bt_fd_mtx);

t->bt_fd = fd;
t->mtu_read = t->mtu_write = hci_sco_get_mtu(fd, a->hci.type);
t->mtu_read = t->mtu_write = hci_sco_get_mtu(fd, a);
fd = -1;

pthread_mutex_unlock(&t->bt_fd_mtx);
Expand Down
1 change: 1 addition & 0 deletions src/shared/bluetooth.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#define BT_COMPID_BROADCOM 0x000F
#define BT_COMPID_APPLE 0x004C
#define BT_COMPID_APT 0x004F
#define BT_COMPID_REALTEK 0x005D
#define BT_COMPID_SAMSUNG_ELEC 0x0075
#define BT_COMPID_QUALCOMM_TECH 0x00D7
#define BT_COMPID_SONY 0x012D
Expand Down
1 change: 1 addition & 0 deletions test/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ test_utils_SOURCES = \
../src/shared/log.c \
../src/shared/nv.c \
../src/shared/rt.c \
../src/bluealsa-config.c \
../src/hci.c \
../src/utils.c \
test-utils.c
Expand Down

0 comments on commit 142307d

Please sign in to comment.