Re: [PATCH BlueZ] shared/gatt-client: Fix not removing services that had disappeared

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

 



Hi,

On Wed, May 24, 2017 at 1:54 PM, Luiz Augusto von Dentz
<luiz.dentz@xxxxxxxxx> wrote:
> From: Luiz Augusto von Dentz <luiz.von.dentz@xxxxxxxxx>
>
> If a service cannot be found in the middle of the database the current
> logic don't clear its range leaving it still active which cause upper
> layer to its attributes are still available.
>
> In order to fix the code now loads existing services into the pending
> list and remove the services left at the end of the discovery:
>
> src/device.c:gatt_debug() Primary services found: 2
> src/device.c:gatt_debug() start: 0x0001, end: 0x0005, uuid: 00001800-0000-1000-8000-00805f9b34fb
> src/device.c:gatt_debug() start: 0x0100, end: 0x0104, uuid: 0000180a-0000-1000-8000-00805f9b34fb
> src/device.c:gatt_debug() Secondary service discovery failed. ATT ECODE: 0x0a
> src/device.c:gatt_debug() Characteristics found: 2
> src/device.c:gatt_debug() start: 0x0101, end: 0x0102, value: 0x0102, props: 0x02, uuid: 00002a24-0000-1
> src/device.c:gatt_debug() start: 0x0103, end: 0x0104, value: 0x0104, props: 0x02, uuid: 00002a29-0000-1
> src/device.c:gatt_debug() service disappeared: start 0x0006 end 0x000a
> src/device.c:gatt_service_removed() start: 0x0006, end: 0x000a
> ---
>  src/shared/gatt-client.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 63 insertions(+), 1 deletion(-)
>
> diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c
> index 7557600..b8f70c8 100644
> --- a/src/shared/gatt-client.c
> +++ b/src/shared/gatt-client.c
> @@ -323,6 +323,7 @@ struct discovery_op {
>         uint16_t last;
>         uint16_t svc_first;
>         uint16_t svc_last;
> +       unsigned int db_id;
>         int ref_count;
>         discovery_op_complete_func_t complete_func;
>         discovery_op_fail_func_t failure_func;
> @@ -330,6 +331,9 @@ struct discovery_op {
>
>  static void discovery_op_free(struct discovery_op *op)
>  {
> +       if (op->db_id > 0)
> +               gatt_db_unregister(op->client->db, op->db_id);
> +
>         queue_destroy(op->pending_svcs, NULL);
>         queue_destroy(op->pending_chrcs, free);
>         queue_destroy(op->ext_prop_desc, NULL);
> @@ -339,6 +343,30 @@ static void discovery_op_free(struct discovery_op *op)
>  static void discovery_op_complete(struct discovery_op *op, bool success,
>                                                                 uint8_t err)
>  {
> +       const struct queue_entry *svc;
> +
> +       /*
> +        * Unregister remove callback so it is not called when clearing unused
> +        * range.
> +        */
> +       gatt_db_unregister(op->client->db, op->db_id);
> +       op->db_id = 0;
> +
> +       /* Remove services pending */
> +       for (svc = queue_get_entries(op->pending_svcs); svc; svc = svc->next) {
> +               struct gatt_db_attribute *attr = svc->data;
> +               uint16_t start, end;
> +
> +               gatt_db_attribute_get_service_data(attr, &start, &end,
> +                                                       NULL, NULL);
> +
> +               util_debug(op->client->debug_callback, op->client->debug_data,
> +                               "service disappeared: start 0x%04x end 0x%04x",
> +                               start, end);
> +
> +               gatt_db_remove_service(op->client->db, attr);
> +       }
> +
>         /* Reset remaining range */
>         if (op->last != UINT16_MAX)
>                 gatt_db_clear_range(op->client->db, op->last + 1, UINT16_MAX);
> @@ -347,6 +375,22 @@ static void discovery_op_complete(struct discovery_op *op, bool success,
>         op->complete_func(op, success, err);
>  }
>
> +static void discovery_load_services(struct gatt_db_attribute *attr,
> +                                                       void *user_data)
> +{
> +       struct discovery_op *op = user_data;
> +
> +       queue_push_tail(op->pending_svcs, attr);
> +}
> +
> +static void discovery_service_changed(struct gatt_db_attribute *attr,
> +                                                       void *user_data)
> +{
> +       struct discovery_op *op = user_data;
> +
> +       queue_remove(op->pending_svcs, attr);
> +}
> +
>  static struct discovery_op *discovery_op_create(struct bt_gatt_client *client,
>                                 uint16_t start, uint16_t end,
>                                 discovery_op_complete_func_t complete_func,
> @@ -365,6 +409,19 @@ static struct discovery_op *discovery_op_create(struct bt_gatt_client *client,
>         op->end = end;
>         op->last = gatt_db_isempty(client->db) ? 0 : UINT16_MAX;
>
> +       /* Load existing services as pending */
> +       gatt_db_foreach_service_in_range(client->db, NULL,
> +                                        discovery_load_services, op,
> +                                        start, end);
> +
> +       /*
> +        * Services are only added when set active in which case they are no
> +        * longer pending so it is safe to remove either way.
> +        */
> +       op->db_id = gatt_db_register(client->db, discovery_service_changed,
> +                                               discovery_service_changed,
> +                                               op, NULL);
> +
>         return op;
>  }
>
> @@ -840,7 +897,9 @@ static void discovery_found_service(struct discovery_op *op,
>                         op->svc_first = start;
>                 if (op->svc_last < end)
>                         op->svc_last = end;
> -       }
> +       } else
> +               /* Remove from pending if active */
> +               queue_remove(op->pending_svcs, attr);
>
>         /* Update last handle */
>         if (end > op->last)
> @@ -916,6 +975,9 @@ static void discover_secondary_cb(bool success, uint8_t att_ecode,
>         }
>
>  next:
> +       if (queue_isempty(op->pending_svcs))
> +               goto done;
> +
>         client->discovery_req = bt_gatt_discover_included_services(client->att,
>                                                         op->svc_first,
>                                                         op->svc_last,
> --
> 2.9.4
>

Applied.

-- 
Luiz Augusto von Dentz
--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[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