I noticed after upgrading 5.66->5.68 that Bluez was no longer sending confirmations (ATT opcode 0x1E) in response to indication opcodes (0x1D). Commit fde32ff9c9c0 ("shared/gatt-client: Allow registering with NULL callback") added an early return to the notify_cb function when the current client's notify_list is empty. However, in this case, we will also not send the confirmation back. This breaks protocol. The devices I have generally respond to this by stopping any new indications until ~15sec timeout or disconnection. As far as I can see, when using D-Bus API all notify handlers are always added on client clones, never on the 'root' client itself (the one with !client->parent), so for the root client the notify_list is always empty, making this issue very easy to trigger using D-Bus GATT API. Ensure that we always send the confirmation, even if notify_list is empty. Fixes: fde32ff9c9c0 ("shared/gatt-client: Allow registering with NULL callback") --- src/shared/gatt-client.c | 57 ++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c index efc013a20..56ecc6a8f 100644 --- a/src/shared/gatt-client.c +++ b/src/shared/gatt-client.c @@ -2230,45 +2230,46 @@ static void notify_cb(struct bt_att_chan *chan, uint8_t opcode, void *user_data) { struct bt_gatt_client *client = user_data; - struct value_data data; - - if (queue_isempty(client->notify_list)) - return; bt_gatt_client_ref(client); - memset(&data, 0, sizeof(data)); + if (!queue_isempty(client->notify_list)) { + struct value_data data; - if (opcode == BT_ATT_OP_HANDLE_NFY_MULT) { - while (length >= 4) { - data.handle = get_le16(pdu); - length -= 2; - pdu += 2; + memset(&data, 0, sizeof(data)); - data.len = get_le16(pdu); - length -= 2; - pdu += 2; + if (opcode == BT_ATT_OP_HANDLE_NFY_MULT) { + while (length >= 4) { + data.handle = get_le16(pdu); + length -= 2; + pdu += 2; - if (data.len > length) - data.len = length; + data.len = get_le16(pdu); + length -= 2; + pdu += 2; - data.data = pdu; + if (data.len > length) + data.len = length; - queue_foreach(client->notify_list, notify_handler, - &data); + data.data = pdu; - length -= data.len; - pdu += data.len; - } - } else { - data.handle = get_le16(pdu); - length -= 2; - pdu += 2; + queue_foreach(client->notify_list, + notify_handler, &data); - data.len = length; - data.data = pdu; + length -= data.len; + pdu += data.len; + } + } else { + data.handle = get_le16(pdu); + length -= 2; + pdu += 2; + + data.len = length; + data.data = pdu; - queue_foreach(client->notify_list, notify_handler, &data); + queue_foreach(client->notify_list, + notify_handler, &data); + } } if (opcode == BT_ATT_OP_HANDLE_IND && !client->parent) -- 2.41.0