Order of batt_io_value_cb() and batt_io_ccc_written_cb() may be reverse. This causes device to appear with 0% or missing battery percentage, because batt->percentage is set on the ignored update so the initial update is lost. Fix by saving new initial value, if battery is not registered. Also downgrade warning to debug message. Also check data length before parsing it. Log (Sony Linkbuds S): src/shared/att.c:can_read_data() (chan 0x7c31eea05c50) ATT PDU received: 0x1b profiles/battery/battery.c:parse_battery_level() Battery Level updated: 87% profiles/battery/battery.c:parse_battery_level() Trying to update an unregistered battery src/battery.c:btd_battery_register() path = /org/bluez/hci1/dev_CF_D2_4D_EE_A2_1A src/battery.c:btd_battery_register() registered Battery object: /org/bluez/hci1/dev_CF_D2_4D_EE_A2_1A profiles/battery/battery.c:batt_io_ccc_written_cb() Battery Level: notification enabled --- profiles/battery/battery.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/profiles/battery/battery.c b/profiles/battery/battery.c index 5be78ab14..2f5be48e9 100644 --- a/profiles/battery/battery.c +++ b/profiles/battery/battery.c @@ -91,16 +91,19 @@ static void batt_reset(struct batt *batt) static void parse_battery_level(struct batt *batt, const uint8_t *value) { - uint8_t percentage; + uint8_t percentage = value[0]; + + DBG("Battery Level updated: %d%%", percentage); + + if (!batt->battery) { + free(batt->initial_value); + batt->initial_value = util_memdup(value, 1); + DBG("Battery not yet registered"); + return; + } - percentage = value[0]; if (batt->percentage != percentage) { batt->percentage = percentage; - DBG("Battery Level updated: %d%%", percentage); - if (!batt->battery) { - warn("Trying to update an unregistered battery"); - return; - } btd_battery_update(batt->battery, batt->percentage); } } @@ -111,6 +114,8 @@ static void batt_io_value_cb(uint16_t value_handle, const uint8_t *value, struct batt *batt = user_data; if (value_handle == batt->batt_level_io_handle) { + if (!length) + return; parse_battery_level(batt, value); } else { g_assert_not_reached(); -- 2.50.1