From f87942027f5776e3f24e2ea60ed659ea38b8308f Mon Sep 17 00:00:00 2001 From: Zsombor Welker Date: Sat, 7 Aug 2021 23:34:09 +0200 Subject: [PATCH] bluez5: report HF indicator 2 based battery status HF indicator 2 (see [assigned-numbers], Hands-Free Profile) is able to report battery percentage at 1% intervals (in range [0, 100]), contrary to the `+XAPL` `+IPHONEACCEV` extension which only supports 10% increments. This does not guarantee increased granularity however, as peers may still be limited to imprecise battery measurements internally or round to coarser percentages. Supporting both additionally broadens the range of devices for which PW can report its battery level. [assigned-numbers]: https://www.bluetooth.com/specifications/assigned-numbers/ --- spa/plugins/bluez5/backend-native.c | 28 ++++++++++++++++++++++++++++ spa/plugins/bluez5/defs.h | 6 ++++++ 2 files changed, 34 insertions(+) diff --git a/spa/plugins/bluez5/backend-native.c b/spa/plugins/bluez5/backend-native.c index d10fbdf2c..fd9bdeee6 100644 --- a/spa/plugins/bluez5/backend-native.c +++ b/spa/plugins/bluez5/backend-native.c @@ -654,6 +654,8 @@ static bool rfcomm_hfp_ag(struct spa_source *source, char* buf) unsigned int gain; unsigned int len; unsigned int selected_codec; + unsigned int indicator; + unsigned int indicator_value; if (sscanf(buf, "AT+BRSF=%u", &features) == 1) { unsigned int ag_features = SPA_BT_HFP_AG_FEATURE_NONE; @@ -692,6 +694,7 @@ static bool rfcomm_hfp_ag(struct spa_source *source, char* buf) } /* send reply to HF with the features supported by Audio Gateway (=computer) */ + ag_features |= SPA_BT_HFP_AG_FEATURE_HF_INDICATORS; rfcomm_send_reply(rfcomm, "+BRSF: %u", ag_features); rfcomm_send_reply(rfcomm, "OK"); } else if (strncmp(buf, "AT+BAC=", 7) == 0) { @@ -810,6 +813,31 @@ static bool rfcomm_hfp_ag(struct spa_source *source, char* buf) spa_log_debug(backend->log, NAME": RFCOMM receive unsupported VGS gain: %s", buf); rfcomm_send_reply(rfcomm, "ERROR"); } + } else if (strncmp(buf, "AT+BIND=", 8) == 0) { + // BIND=... should return a comma separated list of indicators and + // 2 should be among the other numbers telling that battery charge + // is supported + rfcomm_send_reply(rfcomm, "OK"); + } else if (strncmp(buf, "AT+BIND=?", 9) == 0) { + rfcomm_send_reply(rfcomm, "+BIND: (2)"); + rfcomm_send_reply(rfcomm, "OK"); + } else if (strncmp(buf, "AT+BIND?", 8) == 0) { + rfcomm_send_reply(rfcomm, "+BIND: 2,1"); + rfcomm_send_reply(rfcomm, "OK"); + } else if (sscanf(buf, "AT+BIEV=%u,%u", &indicator, &indicator_value) == 2) { + if (indicator == SPA_BT_HFP_HF_INDICATOR_BATTERY_LEVEL) { + // Battery level is reported in range 0-100 + spa_log_debug(backend->log, NAME": battery level: %u%%", indicator_value); + + if (indicator_value <= 100) { + // TODO: report without Battery Provider (using props) + spa_bt_device_report_battery_level(rfcomm->device, indicator_value); + } else { + spa_log_warn(backend->log, NAME": battery HF indicator %u outside of range [0, 100]: %u", indicator, indicator_value); + } + } else { + spa_log_warn(backend->log, NAME": unknown HF indicator: %u", indicator); + } } else if (strncmp(buf, "AT+XAPL=", 8) == 0) { // We expect battery status only (bitmask 10) rfcomm_send_reply(rfcomm, "+XAPL: iPhone,2"); diff --git a/spa/plugins/bluez5/defs.h b/spa/plugins/bluez5/defs.h index c2323fdd6..090b84851 100644 --- a/spa/plugins/bluez5/defs.h +++ b/spa/plugins/bluez5/defs.h @@ -256,6 +256,12 @@ enum spa_bt_hfp_hf_feature { SPA_BT_HFP_HF_FEATURE_ESCO_S4 = (1 << 9), }; +/* https://btprodspecificationrefs.blob.core.windows.net/assigned-numbers/Assigned%20Number%20Types/Hands-Free%20Profile.pdf */ +enum spa_bt_hfp_hf_indicator { + SPA_BT_HFP_HF_INDICATOR_ENHANCED_SAFETY = 1, + SPA_BT_HFP_HF_INDICATOR_BATTERY_LEVEL = 2, +}; + enum spa_bt_hfp_sdp_hf_features { SPA_BT_HFP_SDP_HF_FEATURE_NONE = (0), SPA_BT_HFP_SDP_HF_FEATURE_ECNR = (1 << 0),