bluez5: add and use quirk for broken mic HW volume

Some headsets emit AT+VGM even though +VGM commands do not actually
adjust the recording volume.
This commit is contained in:
Pauli Virtanen 2021-06-21 21:10:42 +03:00
parent 4899b75410
commit 9d38d375d2
4 changed files with 21 additions and 6 deletions

View file

@ -129,6 +129,7 @@ struct rfcomm {
char* path;
bool has_volume;
struct rfcomm_volume volumes[SPA_BT_VOLUME_ID_TERM];
unsigned int broken_mic_hw_volume:1;
#ifdef HAVE_BLUEZ_5_BACKEND_HFP_NATIVE
unsigned int slc_configured:1;
unsigned int codec_negotiation_supported:1;
@ -331,7 +332,8 @@ static bool rfcomm_hsp_ag(struct spa_source *source, char* buf)
}
} else if (sscanf(buf, "AT+VGM=%d", &gain) == 1) {
if (gain <= SPA_BT_VOLUME_HS_MAX) {
rfcomm_emit_volume_changed(rfcomm, SPA_BT_VOLUME_ID_RX, gain);
if (!rfcomm->broken_mic_hw_volume)
rfcomm_emit_volume_changed(rfcomm, SPA_BT_VOLUME_ID_RX, gain);
rfcomm_send_reply(source, "OK");
} else {
rfcomm_send_reply(source, "ERROR");
@ -619,7 +621,7 @@ static bool rfcomm_hfp_ag(struct spa_source *source, char* buf)
/*
* Determine device volume control. Some headsets only support control of
* TX volume, but not RX, even if they have a microphone. Determine this
* separately based on whether we also get AT+VGS/AT+VGM.
* separately based on whether we also get AT+VGS/AT+VGM, and quirks.
*/
rfcomm->has_volume = (features & SPA_BT_HFP_HF_FEATURE_REMOTE_VOLUME_CONTROL);
@ -753,7 +755,8 @@ static bool rfcomm_hfp_ag(struct spa_source *source, char* buf)
spa_bt_device_emit_codec_switched(rfcomm->device, 0);
} else if (sscanf(buf, "AT+VGM=%u", &gain) == 1) {
if (gain <= SPA_BT_VOLUME_HS_MAX) {
rfcomm_emit_volume_changed(rfcomm, SPA_BT_VOLUME_ID_RX, gain);
if (!rfcomm->broken_mic_hw_volume)
rfcomm_emit_volume_changed(rfcomm, SPA_BT_VOLUME_ID_RX, gain);
rfcomm_send_reply(source, "OK");
} else {
spa_log_debug(backend->log, NAME": RFCOMM receive unsupported VGM gain: %s", buf);
@ -1659,6 +1662,15 @@ static DBusHandlerResult profile_new_connection(DBusConnection *conn, DBusMessag
rfcomm->hf_state = hfp_hf_brsf;
}
if (rfcomm_volume_enabled(rfcomm) && (profile == SPA_BT_PROFILE_HFP_HF || profile == SPA_BT_PROFILE_HSP_HS)) {
uint32_t device_features;
if (spa_bt_quirks_get_features(backend->quirks, d->adapter, d, &device_features) == 0) {
rfcomm->broken_mic_hw_volume = !(device_features & SPA_BT_FEATURE_HW_VOLUME_MIC);
if (rfcomm->broken_mic_hw_volume)
spa_log_debug(backend->log, NAME": microphone HW volume disabled by quirk");
}
}
if ((r = dbus_message_new_method_return(m)) == NULL)
goto fail_need_memory;
if (!dbus_connection_send(conn, r, NULL))

View file

@ -671,7 +671,8 @@ enum spa_bt_feature {
SPA_BT_FEATURE_MSBC_ALT1 = (1 << 1),
SPA_BT_FEATURE_MSBC_ALT1_RTL = (1 << 2),
SPA_BT_FEATURE_HW_VOLUME = (1 << 3),
SPA_BT_FEATURE_SBC_XQ = (1 << 4),
SPA_BT_FEATURE_HW_VOLUME_MIC = (1 << 4),
SPA_BT_FEATURE_SBC_XQ = (1 << 5),
};
struct spa_bt_quirks;

View file

@ -75,6 +75,7 @@ static enum spa_bt_feature parse_feature(const char *str)
{ "msbc-alt1", SPA_BT_FEATURE_MSBC_ALT1 },
{ "msbc-alt1-rtl", SPA_BT_FEATURE_MSBC_ALT1_RTL },
{ "hw-volume", SPA_BT_FEATURE_HW_VOLUME },
{ "hw-volume-mic", SPA_BT_FEATURE_HW_VOLUME_MIC },
{ "sbc-xq", SPA_BT_FEATURE_SBC_XQ },
};
size_t i;

View file

@ -10,7 +10,8 @@
# msbc "standard" mSBC (60 byte tx packet)
# msbc-alt1 USB adapters with mSBC in ALT1 setting (24 byte tx packet)
# msbc-alt1-rtl Realtek USB adapters with mSBC in ALT1 setting (24 byte tx packet)
# hw-volume AVRCP absolute volume support
# hw-volume AVRCP and HSP/HFP hardware volume support
# hw-volume-mic Functional HSP/HFP microphone volume support
# sbc-xq "nonstandard" SBC codec setting with better sound quality
# (XXX: the SBC-XQ per-device setting doesn't have effect yet)
#
@ -25,7 +26,7 @@ bluez5.features.device = [
# - product-id
# - version-id
{ name = "Air 1 Plus" },
{ name = "Air 1 Plus", no-features = [ hw-volume-mic ] },
{ name = "AirPods", no-features = [ msbc-alt1, msbc-alt1-rtl ] },
{ name = "AirPods Pro", no-features = [ msbc-alt1, msbc-alt1-rtl ] },
{ name = "AXLOIE Goin", no-features = [ msbc-alt1, msbc-alt1-rtl ] },