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/
This commit is contained in:
Zsombor Welker 2021-08-07 23:34:09 +02:00 committed by Wim Taymans
parent f816f702a5
commit f87942027f
2 changed files with 34 additions and 0 deletions

View file

@ -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");

View file

@ -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),