Re: [PATCH BlueZ v3 1/7] shared/gatt-client: Fix handling of services

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

 



Hi,

On Thu, Mar 19, 2015 at 4:21 PM, Luiz Augusto von Dentz
<luiz.dentz@xxxxxxxxx> wrote:
> From: Luiz Augusto von Dentz <luiz.von.dentz@xxxxxxxxx>
>
> Remote services may contain gaps between their handles so they need to be
> inserted in a proper position.
> ---
> v2: Fix gatt_db_get_attribute to work with non-sequential handles
> v3: Fix gatt_db_service_foreach_desc to work with non-sequential handles
>
>  src/shared/gatt-client.c |   8 ++-
>  src/shared/gatt-db.c     | 147 +++++++++++++++++++++++++++++++++++++----------
>  src/shared/gatt-db.h     |  17 ++++++
>  3 files changed, 139 insertions(+), 33 deletions(-)
>
> diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c
> index f33d8c9..3e28c6e 100644
> --- a/src/shared/gatt-client.c
> +++ b/src/shared/gatt-client.c
> @@ -588,7 +588,8 @@ static bool discover_descs(struct discovery_op *op, bool *discovering)
>         *discovering = false;
>
>         while ((chrc_data = queue_pop_head(op->pending_chrcs))) {
> -               attr = gatt_db_service_add_characteristic(op->cur_svc,
> +               attr = gatt_db_service_insert_characteristic(op->cur_svc,
> +                                                       chrc_data->value_handle,
>                                                         &chrc_data->uuid, 0,
>                                                         chrc_data->properties,
>                                                         NULL, NULL, NULL);
> @@ -679,8 +680,9 @@ static void discover_descs_cb(bool success, uint8_t att_ecode,
>                                                 "handle: 0x%04x, uuid: %s",
>                                                 handle, uuid_str);
>
> -               attr = gatt_db_service_add_descriptor(op->cur_svc, &uuid, 0,
> -                                                       NULL, NULL, NULL);
> +               attr = gatt_db_service_insert_descriptor(op->cur_svc, handle,
> +                                                       &uuid, 0, NULL, NULL,
> +                                                       NULL);
>                 if (!attr)
>                         goto failed;
>
> diff --git a/src/shared/gatt-db.c b/src/shared/gatt-db.c
> index eb81372..2b2090c 100644
> --- a/src/shared/gatt-db.c
> +++ b/src/shared/gatt-db.c
> @@ -158,6 +158,7 @@ static void attribute_destroy(struct gatt_db_attribute *attribute)
>  }
>
>  static struct gatt_db_attribute *new_attribute(struct gatt_db_service *service,
> +                                                       uint16_t handle,
>                                                         const bt_uuid_t *type,
>                                                         const uint8_t *val,
>                                                         uint16_t len)
> @@ -169,6 +170,7 @@ static struct gatt_db_attribute *new_attribute(struct gatt_db_service *service,
>                 return NULL;
>
>         attribute->service = service;
> +       attribute->handle = handle;
>         attribute->uuid = *type;
>         attribute->value_len = len;
>         if (len) {
> @@ -371,6 +373,7 @@ static bool le_to_uuid(const uint8_t *src, size_t len, bt_uuid_t *uuid)
>  }
>
>  static struct gatt_db_service *gatt_db_service_create(const bt_uuid_t *uuid,
> +                                                       uint16_t handle,
>                                                         bool primary,
>                                                         uint16_t num_handles)
>  {
> @@ -399,7 +402,8 @@ static struct gatt_db_service *gatt_db_service_create(const bt_uuid_t *uuid,
>
>         len = uuid_to_le(uuid, value);
>
> -       service->attributes[0] = new_attribute(service, type, value, len);
> +       service->attributes[0] = new_attribute(service, handle, type, value,
> +                                                                       len);
>         if (!service->attributes[0]) {
>                 gatt_db_service_destroy(service);
>                 return NULL;
> @@ -533,7 +537,7 @@ struct gatt_db_attribute *gatt_db_insert_service(struct gatt_db *db,
>         if (!find_insert_loc(db, handle, handle + num_handles - 1, &after))
>                 return NULL;
>
> -       service = gatt_db_service_create(uuid, primary, num_handles);
> +       service = gatt_db_service_create(uuid, handle, primary, num_handles);
>
>         if (!service)
>                 return NULL;
> @@ -663,8 +667,9 @@ static void set_attribute_data(struct gatt_db_attribute *attribute,
>         attribute->user_data = user_data;
>  }
>
> -struct gatt_db_attribute *
> -gatt_db_service_add_characteristic(struct gatt_db_attribute *attrib,
> +static struct gatt_db_attribute *
> +service_insert_characteristic(struct gatt_db_service *service,
> +                                       uint16_t handle,
>                                         const bt_uuid_t *uuid,
>                                         uint32_t permissions,
>                                         uint8_t properties,
> @@ -672,35 +677,38 @@ gatt_db_service_add_characteristic(struct gatt_db_attribute *attrib,
>                                         gatt_db_write_t write_func,
>                                         void *user_data)
>  {
> -       struct gatt_db_service *service;
>         uint8_t value[MAX_CHAR_DECL_VALUE_LEN];
>         uint16_t len = 0;
>         int i;
>
> -       if (!attrib)
> +       /* Check if handle is in within service range */
> +       if (handle && handle <= service->attributes[0]->handle)
>                 return NULL;
>
> -       service = attrib->service;
> -
>         i = get_attribute_index(service, 1);
>         if (!i)
>                 return NULL;
>
> +       if (!handle)
> +               handle = get_handle_at_index(service, i - 1) + 2;
> +
>         value[0] = properties;
>         len += sizeof(properties);
> +
>         /* We set handle of characteristic value, which will be added next */
> -       put_le16(get_handle_at_index(service, i - 1) + 2, &value[1]);
> +       put_le16(handle, &value[1]);
>         len += sizeof(uint16_t);
>         len += uuid_to_le(uuid, &value[3]);
>
> -       service->attributes[i] = new_attribute(service, &characteristic_uuid,
> -                                                               value, len);
> +       service->attributes[i] = new_attribute(service, handle - 1,
> +                                                       &characteristic_uuid,
> +                                                       value, len);
>         if (!service->attributes[i])
>                 return NULL;
>
> -       attribute_update(service, i++);
> +       i++;
>
> -       service->attributes[i] = new_attribute(service, uuid, NULL, 0);
> +       service->attributes[i] = new_attribute(service, handle, uuid, NULL, 0);
>         if (!service->attributes[i]) {
>                 free(service->attributes[i - 1]);
>                 return NULL;
> @@ -709,37 +717,109 @@ gatt_db_service_add_characteristic(struct gatt_db_attribute *attrib,
>         set_attribute_data(service->attributes[i], read_func, write_func,
>                                                         permissions, user_data);
>
> -       return attribute_update(service, i);
> +       return service->attributes[i];
>  }
>
>  struct gatt_db_attribute *
> -gatt_db_service_add_descriptor(struct gatt_db_attribute *attrib,
> +gatt_db_service_insert_characteristic(struct gatt_db_attribute *attrib,
> +                                       uint16_t handle,
>                                         const bt_uuid_t *uuid,
>                                         uint32_t permissions,
> +                                       uint8_t properties,
>                                         gatt_db_read_t read_func,
>                                         gatt_db_write_t write_func,
>                                         void *user_data)
>  {
> -       struct gatt_db_service *service;
> -       int i;
> +       if (!attrib || !handle)
> +               return NULL;
>
> +       return service_insert_characteristic(attrib->service, handle, uuid,
> +                                               permissions, properties,
> +                                               read_func, write_func,
> +                                               user_data);
> +}
> +
> +struct gatt_db_attribute *
> +gatt_db_service_add_characteristic(struct gatt_db_attribute *attrib,
> +                                       const bt_uuid_t *uuid,
> +                                       uint32_t permissions,
> +                                       uint8_t properties,
> +                                       gatt_db_read_t read_func,
> +                                       gatt_db_write_t write_func,
> +                                       void *user_data)
> +{
>         if (!attrib)
>                 return NULL;
>
> -       service = attrib->service;
> +       return service_insert_characteristic(attrib->service, 0, uuid,
> +                                               permissions, properties,
> +                                               read_func, write_func,
> +                                               user_data);
> +}
> +
> +static struct gatt_db_attribute *
> +service_insert_descriptor(struct gatt_db_service *service,
> +                                       uint16_t handle,
> +                                       const bt_uuid_t *uuid,
> +                                       uint32_t permissions,
> +                                       gatt_db_read_t read_func,
> +                                       gatt_db_write_t write_func,
> +                                       void *user_data)
> +{
> +       int i;
>
>         i = get_attribute_index(service, 0);
>         if (!i)
>                 return NULL;
>
> -       service->attributes[i] = new_attribute(service, uuid, NULL, 0);
> +       /* Check if handle is in within service range */
> +       if (handle && handle <= service->attributes[0]->handle)
> +               return NULL;
> +
> +       if (!handle)
> +               handle = get_handle_at_index(service, i - 1) + 1;
> +
> +       service->attributes[i] = new_attribute(service, handle, uuid, NULL, 0);
>         if (!service->attributes[i])
>                 return NULL;
>
>         set_attribute_data(service->attributes[i], read_func, write_func,
>                                                         permissions, user_data);
>
> -       return attribute_update(service, i);
> +       return service->attributes[i];
> +}
> +
> +struct gatt_db_attribute *
> +gatt_db_service_insert_descriptor(struct gatt_db_attribute *attrib,
> +                                       uint16_t handle,
> +                                       const bt_uuid_t *uuid,
> +                                       uint32_t permissions,
> +                                       gatt_db_read_t read_func,
> +                                       gatt_db_write_t write_func,
> +                                       void *user_data)
> +{
> +       if (!attrib || !handle)
> +               return NULL;
> +
> +       return service_insert_descriptor(attrib->service, handle, uuid,
> +                                       permissions, read_func, write_func,
> +                                       user_data);
> +}
> +
> +struct gatt_db_attribute *
> +gatt_db_service_add_descriptor(struct gatt_db_attribute *attrib,
> +                                       const bt_uuid_t *uuid,
> +                                       uint32_t permissions,
> +                                       gatt_db_read_t read_func,
> +                                       gatt_db_write_t write_func,
> +                                       void *user_data)
> +{
> +       if (!attrib)
> +               return NULL;
> +
> +       return service_insert_descriptor(attrib->service, 0, uuid,
> +                                       permissions, read_func, write_func,
> +                                       user_data);
>  }
>
>  struct gatt_db_attribute *
> @@ -781,7 +861,7 @@ gatt_db_service_add_included(struct gatt_db_attribute *attrib,
>         if (!index)
>                 return NULL;
>
> -       service->attributes[index] = new_attribute(service,
> +       service->attributes[index] = new_attribute(service, 0,
>                                                         &included_service_uuid,
>                                                         value, len);
>         if (!service->attributes[index])
> @@ -1184,7 +1264,13 @@ void gatt_db_service_foreach_desc(struct gatt_db_attribute *attrib,
>         service = attrib->service;
>
>         /* Start from the attribute following the value handle */
> -       i = attrib->handle - service->attributes[0]->handle + 2;
> +       for (i = 0; i < service->num_handles; i++) {
> +               if (service->attributes[i] == attrib) {
> +                       i += 2;
> +                       break;
> +               }
> +       }
> +
>         for (; i < service->num_handles; i++) {
>                 attr = service->attributes[i];
>                 if (!attr)
> @@ -1222,7 +1308,7 @@ struct gatt_db_attribute *gatt_db_get_attribute(struct gatt_db *db,
>                                                         uint16_t handle)
>  {
>         struct gatt_db_service *service;
> -       uint16_t service_handle;
> +       int i;
>
>         if (!db || !handle)
>                 return NULL;
> @@ -1232,14 +1318,15 @@ struct gatt_db_attribute *gatt_db_get_attribute(struct gatt_db *db,
>         if (!service)
>                 return NULL;
>
> -       service_handle = service->attributes[0]->handle;
> +       for (i = 0; i < service->num_handles; i++) {
> +               if (!service->attributes[i])
> +                       continue;
>
> -       /*
> -        * We can safely get attribute from attributes array with offset,
> -        * because find_service_for_handle() check if given handle is
> -        * in service range.
> -        */
> -       return service->attributes[handle - service_handle];
> +               if (service->attributes[i]->handle == handle)
> +                       return service->attributes[i];
> +       }
> +
> +       return NULL;
>  }
>
>  static bool find_service_with_uuid(const void *data, const void *user_data)
> diff --git a/src/shared/gatt-db.h b/src/shared/gatt-db.h
> index 74b37bc..96cceb9 100644
> --- a/src/shared/gatt-db.h
> +++ b/src/shared/gatt-db.h
> @@ -67,6 +67,15 @@ gatt_db_service_add_characteristic(struct gatt_db_attribute *attrib,
>                                         gatt_db_read_t read_func,
>                                         gatt_db_write_t write_func,
>                                         void *user_data);
> +struct gatt_db_attribute *
> +gatt_db_service_insert_characteristic(struct gatt_db_attribute *attrib,
> +                                       uint16_t handle,
> +                                       const bt_uuid_t *uuid,
> +                                       uint32_t permissions,
> +                                       uint8_t properties,
> +                                       gatt_db_read_t read_func,
> +                                       gatt_db_write_t write_func,
> +                                       void *user_data);
>
>  struct gatt_db_attribute *
>  gatt_db_service_add_descriptor(struct gatt_db_attribute *attrib,
> @@ -75,6 +84,14 @@ gatt_db_service_add_descriptor(struct gatt_db_attribute *attrib,
>                                         gatt_db_read_t read_func,
>                                         gatt_db_write_t write_func,
>                                         void *user_data);
> +struct gatt_db_attribute *
> +gatt_db_service_insert_descriptor(struct gatt_db_attribute *attrib,
> +                                       uint16_t handle,
> +                                       const bt_uuid_t *uuid,
> +                                       uint32_t permissions,
> +                                       gatt_db_read_t read_func,
> +                                       gatt_db_write_t write_func,
> +                                       void *user_data);
>
>  struct gatt_db_attribute *
>  gatt_db_service_add_included(struct gatt_db_attribute *attrib,
> --
> 2.1.0

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