Re: [PATCH BlueZ] shared/gatt-client: always send ATT confirmations

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Javier,

On Sat, Aug 26, 2023 at 1:08 PM Javier de San Pedro
<dev.git@xxxxxxxxxxxxxx> wrote:
>
> 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;

Instead reversing the if logic here you could just use goto to where
we handle the confirmation.

>
>         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
>


-- 
Luiz Augusto von Dentz




[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux