gatt-client : Simplify service / characteristic discovery 00/136500/1
authorSeungyoun Ju <sy39.ju@samsung.com>
Mon, 5 Jun 2017 02:33:39 +0000 (11:33 +0900)
committerSeungyoun Ju <sy39.ju@samsung.com>
Fri, 30 Jun 2017 04:12:27 +0000 (13:12 +0900)
[Problem] N/A
[Cause & Measure] Simplify service / characteristic discovery
[Checking Method] Make GATT connection

. When remote device has 41 attributes
  - Before patch : 5.431658167 secs
  - After patch : 3.921924167 secs

. Below upstream commits are imported by this patch.

commit a39cd38a3db73b1d2d78370b7c678ac47f560c13
Author: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Date:   Tue May 9 12:59:16 2017 +0300
    shared/gatt-client: Simplify characteristics discovery

commit 82c7e0365702e343d6dad0baa23bdff59be27b0c
Author: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Date:   Tue May 9 12:47:40 2017 +0300
    shared/gatt-db: Add gatt_db_insert_descriptor

commit 87abac457f4e2037c2cd6e4f30384e2ab4fa662b
Author: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Date:   Mon May 8 20:18:25 2017 +0300
    shared/gatt-db: Add gatt_db_insert_characteristic

commit f78146f96fb254e43d3d003ddcdf97983cf764f1
Author: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Date:   Mon May 8 16:52:05 2017 +0300
    shared/gatt-client: Simplify included discovery

commit 0c9f030b1b3c8cf96feb9f702c5b925a1dc9ea69
Author: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Date:   Mon May 8 16:00:46 2017 +0300
    shared/gatt-db: Add gatt_db_insert_included

commit 7aaa6c893aa89a61d20460e1ab89ac419435c3a1
Author: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Date:   Mon May 8 15:48:02 2017 +0300
    shared/gatt-client: Insert included attribute with handle

commit 108336ee3e68f3e71b2229aee83a7d03e0cde618
Author: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Date:   Mon May 8 15:33:26 2017 +0300
    shared/gatt-db: Add gatt_db_service_insert_included

commit ba07a8bfc07a744081b3d7df51803cad9062aa8c
Author: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Date:   Mon May 8 13:46:30 2017 +0300
    shared/gatt-db: Add gatt_db_get_service

Change-Id: I1bd68ff4a498ae3da56225533df31ec18221ffde

src/shared/gatt-client.c
src/shared/gatt-db.c
src/shared/gatt-db.h

index 9f4e075..65cc2b0 100644 (file)
@@ -341,12 +341,13 @@ struct discovery_op {
        struct bt_gatt_client *client;
        struct queue *pending_svcs;
        struct queue *pending_chrcs;
-       struct queue *svcs;
        struct gatt_db_attribute *cur_svc;
        bool success;
        uint16_t start;
        uint16_t end;
        uint16_t last;
+       uint16_t svc_first;
+       uint16_t svc_last;
        int ref_count;
        discovery_op_complete_func_t complete_func;
        discovery_op_fail_func_t failure_func;
@@ -356,7 +357,6 @@ static void discovery_op_free(struct discovery_op *op)
 {
        queue_destroy(op->pending_svcs, NULL);
        queue_destroy(op->pending_chrcs, free);
-       queue_destroy(op->svcs, NULL);
        free(op);
 }
 
@@ -405,7 +405,6 @@ static struct discovery_op *discovery_op_create(struct bt_gatt_client *client,
        op = new0(struct discovery_op, 1);
        op->pending_svcs = queue_new();
        op->pending_chrcs = queue_new();
-       op->svcs = queue_new();
        op->client = client;
        op->complete_func = complete_func;
        op->failure_func = failure_func;
@@ -457,7 +456,7 @@ static void discover_incl_cb(bool success, uint8_t att_ecode,
        struct discovery_op *op = user_data;
        struct bt_gatt_client *client = op->client;
        struct bt_gatt_iter iter;
-       struct gatt_db_attribute *attr, *tmp;
+       struct gatt_db_attribute *attr;
        uint16_t handle, start, end;
        uint128_t u128;
        bt_uuid_t uuid;
@@ -473,11 +472,6 @@ static void discover_incl_cb(bool success, uint8_t att_ecode,
                goto failed;
        }
 
-       /* Get the currently processed service */
-       attr = op->cur_svc;
-       if (!attr)
-               goto failed;
-
        if (!result || !bt_gatt_iter_init(&iter, result))
                goto failed;
 
@@ -502,12 +496,12 @@ static void discover_incl_cb(bool success, uint8_t att_ecode,
                                "handle: 0x%04x, start: 0x%04x, end: 0x%04x,"
                                "uuid: %s", handle, start, end, uuid_str);
 
-               tmp = gatt_db_get_attribute(client->db, start);
-               if (!tmp)
+               attr = gatt_db_get_attribute(client->db, start);
+               if (!attr)
                        goto failed;
 
-               tmp = gatt_db_service_add_included(attr, tmp);
-               if (!tmp)
+               attr = gatt_db_insert_included(client->db, handle, attr);
+               if (!attr)
                        goto failed;
 
                /*
@@ -516,62 +510,23 @@ static void discover_incl_cb(bool success, uint8_t att_ecode,
                 * these entries, the correct handle must be assigned to the new
                 * attribute.
                 */
-               if (gatt_db_attribute_get_handle(tmp) != handle)
+               if (gatt_db_attribute_get_handle(attr) != handle)
                        goto failed;
        }
 
 next:
-       /* Move on to the next service */
-       attr = queue_pop_head(op->pending_svcs);
-       if (!attr) {
-               /*
-                * We have processed all include definitions. Move on to
-                * characteristics.
-                */
-               attr = queue_pop_head(op->svcs);
-               if (!attr)
-                       goto failed;
-
-               if (!gatt_db_attribute_get_service_handles(attr, &start, &end))
-                       goto failed;
-
-               op->cur_svc = attr;
-
-               client->discovery_req = bt_gatt_discover_characteristics(
-                                                       client->att,
-                                                       start, end,
+       client->discovery_req = bt_gatt_discover_characteristics(client->att,
+                                                       op->svc_first,
+                                                       op->svc_last,
                                                        discover_chrcs_cb,
                                                        discovery_op_ref(op),
                                                        discovery_op_unref);
-               if (client->discovery_req)
-                       return;
-
-               util_debug(client->debug_callback, client->debug_data,
-                               "Failed to start characteristic discovery");
-               discovery_op_unref(op);
-               goto failed;
-       }
-
-       queue_push_tail(op->svcs, attr);
-       op->cur_svc = attr;
-       if (!gatt_db_attribute_get_service_handles(attr, &start, &end))
-               goto failed;
-
-       if (start == end)
-               goto next;
-
-       client->discovery_req = bt_gatt_discover_included_services(client->att,
-                                                       start, end,
-                                                       discover_incl_cb,
-                                                       discovery_op_ref(op),
-                                                       discovery_op_unref);
        if (client->discovery_req)
                return;
 
        util_debug(client->debug_callback, client->debug_data,
-                                       "Failed to start included discovery");
+                               "Failed to start characteristic discovery");
        discovery_op_unref(op);
-
 failed:
        discovery_op_complete(op, false, att_ecode);
 }
@@ -598,7 +553,10 @@ 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_insert_characteristic(op->cur_svc,
+               struct gatt_db_attribute *svc;
+               uint16_t start, end;
+
+               attr = gatt_db_insert_characteristic(client->db,
                                                        chrc_data->value_handle,
                                                        &chrc_data->uuid, 0,
                                                        chrc_data->properties,
@@ -615,6 +573,25 @@ static bool discover_descs(struct discovery_op *op, bool *discovering)
                                                        chrc_data->value_handle)
                        goto failed;
 
+               /* Adjust current service */
+               svc = gatt_db_get_service(client->db, chrc_data->value_handle);
+               if (op->cur_svc != svc) {
+                       queue_remove(op->pending_svcs, svc);
+
+                       /* Done with the current service */
+                       gatt_db_service_set_active(op->cur_svc, true);
+                       op->cur_svc = svc;
+               }
+
+               gatt_db_attribute_get_service_handles(svc, &start, &end);
+
+               /*
+                * Ajust end_handle in case the next chrc is not within the
+                * same service.
+                */
+               if (chrc_data->end_handle > end)
+                       chrc_data->end_handle = end;
+
                /*
                 * check for descriptors presence, before initializing the
                 * desc_handle and avoid integer overflow during desc_handle
@@ -624,6 +601,7 @@ static bool discover_descs(struct discovery_op *op, bool *discovering)
                        free(chrc_data);
                        continue;
                }
+
                desc_start = chrc_data->value_handle + 1;
 
                client->discovery_req = bt_gatt_discover_descriptors(
@@ -661,7 +639,7 @@ static void discover_descs_cb(bool success, uint8_t att_ecode,
        struct bt_gatt_client *client = op->client;
        struct bt_gatt_iter iter;
        struct gatt_db_attribute *attr;
-       uint16_t handle, start, end;
+       uint16_t handle;
        uint128_t u128;
        bt_uuid_t uuid;
        char uuid_str[MAX_LEN_UUID_STR];
@@ -698,11 +676,15 @@ static void discover_descs_cb(bool success, uint8_t att_ecode,
                                                "handle: 0x%04x, uuid: %s",
                                                handle, uuid_str);
 
-               attr = gatt_db_service_insert_descriptor(op->cur_svc, handle,
+               attr = gatt_db_insert_descriptor(client->db, handle,
                                                        &uuid, 0, NULL, NULL,
                                                        NULL);
-               if (!attr)
+               if (!attr) {
+                       util_debug(client->debug_callback, client->debug_data,
+                               "Failed to insert descriptor at 0x%04x",
+                               handle);
                        goto failed;
+               }
 
                if (gatt_db_attribute_get_handle(attr) != handle)
                        goto failed;
@@ -718,30 +700,7 @@ next:
        /* Done with the current service */
        gatt_db_service_set_active(op->cur_svc, true);
 
-       attr = queue_pop_head(op->svcs);
-       if (!attr)
-               goto done;
-
-       if (!gatt_db_attribute_get_service_handles(attr, &start, &end))
-               goto failed;
-
-       if (start == end)
-               goto next;
-
-       /* Move on to the next service */
-       op->cur_svc = attr;
-
-       client->discovery_req = bt_gatt_discover_characteristics(client->att,
-                                                       start, end,
-                                                       discover_chrcs_cb,
-                                                       discovery_op_ref(op),
-                                                       discovery_op_unref);
-       if (client->discovery_req)
-               return;
-
-       util_debug(client->debug_callback, client->debug_data,
-                               "Failed to start characteristic discovery");
-       discovery_op_unref(op);
+       goto done;
 
 failed:
        success = false;
@@ -807,7 +766,6 @@ static void discover_chrcs_cb(bool success, uint8_t att_ecode,
        struct discovery_op *op = user_data;
        struct bt_gatt_client *client = op->client;
        struct bt_gatt_iter iter;
-       struct gatt_db_attribute *attr;
        struct chrc *chrc_data;
        uint16_t start, end, value;
        uint8_t properties;
@@ -828,7 +786,7 @@ static void discover_chrcs_cb(bool success, uint8_t att_ecode,
                goto done;
        }
 
-       if (!op->cur_svc || !result || !bt_gatt_iter_init(&iter, result))
+       if (!result || !bt_gatt_iter_init(&iter, result))
                goto failed;
 
        chrc_count = bt_gatt_result_characteristic_count(result);
@@ -884,30 +842,7 @@ next:
        /* Done with the current service */
        gatt_db_service_set_active(op->cur_svc, true);
 
-       attr = queue_pop_head(op->svcs);
-       if (!attr)
-               goto done;
-
-       if (!gatt_db_attribute_get_service_handles(attr, &start, &end))
-               goto failed;
-
-       if (start == end)
-               goto next;
-
-       /* Move on to the next service */
-       op->cur_svc = attr;
-
-       client->discovery_req = bt_gatt_discover_characteristics(client->att,
-                                                       start, end,
-                                                       discover_chrcs_cb,
-                                                       discovery_op_ref(op),
-                                                       discovery_op_unref);
-       if (client->discovery_req)
-               return;
-
-       util_debug(client->debug_callback, client->debug_data,
-                               "Failed to start characteristic discovery");
-       discovery_op_unref(op);
+       goto done;
 
 failed:
        success = false;
@@ -916,6 +851,26 @@ done:
        discovery_op_complete(op, success, att_ecode);
 }
 
+static void discovery_found_service(struct discovery_op *op,
+                                       struct gatt_db_attribute *attr,
+                                       uint16_t start, uint16_t end)
+{
+       /* Skip if service already active */
+       if (!gatt_db_service_get_active(attr)) {
+               queue_push_tail(op->pending_svcs, attr);
+
+               /* Update discovery range */
+               if (!op->svc_first || op->svc_first > start)
+                       op->svc_first = start;
+               if (op->svc_last < end)
+                       op->svc_last = end;
+       }
+
+       /* Update last handle */
+       if (end > op->last)
+               op->last = end;
+}
+
 static void discover_secondary_cb(bool success, uint8_t att_ecode,
                                                struct bt_gatt_result *result,
                                                void *user_data)
@@ -985,39 +940,14 @@ static void discover_secondary_cb(bool success, uint8_t att_ecode,
                        }
                }
 
-               /* Skip if service already active */
-               if (!gatt_db_service_get_active(attr))
-                       queue_push_tail(op->pending_svcs, attr);
-
-               /* Update last handle */
-               if (end > op->last)
-                       op->last = end;
+               /* Update pending list */
+               discovery_found_service(op, attr, start, end);
        }
 
 next:
-       /* Sequentially discover included services */
-       attr = queue_pop_head(op->pending_svcs);
-
-       /* Complete with success if queue is empty */
-       if (!attr) {
-               success = true;
-               goto done;
-       }
-
-       /*
-        * Store the service in the svcs queue to be reused during
-        * characteristics discovery later.
-        */
-       queue_push_tail(op->svcs, attr);
-       op->cur_svc = attr;
-
-       if (!gatt_db_attribute_get_service_handles(attr, &start, &end)) {
-               success = false;
-               goto done;
-       }
-
        client->discovery_req = bt_gatt_discover_included_services(client->att,
-                                                       start, end,
+                                                       op->svc_first,
+                                                       op->svc_last,
                                                        discover_incl_cb,
                                                        discovery_op_ref(op),
                                                        discovery_op_unref);
@@ -1103,13 +1033,8 @@ static void discover_primary_cb(bool success, uint8_t att_ecode,
                        }
                }
 
-               /* Skip if service already active */
-               if (!gatt_db_service_get_active(attr))
-                       queue_push_tail(op->pending_svcs, attr);
-
-               /* Update last handle */
-               if (end > op->last)
-                       op->last = end;
+               /* Update pending list */
+               discovery_found_service(op, attr, start, end);
        }
 
 secondary:
index 0126281..073bba6 100644 (file)
@@ -734,6 +734,28 @@ service_insert_characteristic(struct gatt_db_service *service,
 }
 
 struct gatt_db_attribute *
+gatt_db_insert_characteristic(struct gatt_db *db,
+                                       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 *attrib;
+
+       attrib = gatt_db_get_service(db, handle);
+       if (!attrib)
+               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_insert_characteristic(struct gatt_db_attribute *attrib,
                                        uint16_t handle,
                                        const bt_uuid_t *uuid,
@@ -803,6 +825,26 @@ service_insert_descriptor(struct gatt_db_service *service,
 }
 
 struct gatt_db_attribute *
+gatt_db_insert_descriptor(struct gatt_db *db,
+                                       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 *attrib;
+
+       attrib = gatt_db_get_service(db, handle);
+       if (!attrib)
+               return NULL;
+
+       return service_insert_descriptor(attrib->service, handle, uuid,
+                                       permissions, read_func, write_func,
+                                       user_data);
+}
+
+struct gatt_db_attribute *
 gatt_db_service_insert_descriptor(struct gatt_db_attribute *attrib,
                                        uint16_t handle,
                                        const bt_uuid_t *uuid,
@@ -835,19 +877,15 @@ gatt_db_service_add_descriptor(struct gatt_db_attribute *attrib,
                                        user_data);
 }
 
-struct gatt_db_attribute *
-gatt_db_service_add_included(struct gatt_db_attribute *attrib,
+static struct gatt_db_attribute *
+service_insert_included(struct gatt_db_service *service, uint16_t handle,
                                        struct gatt_db_attribute *include)
 {
-       struct gatt_db_service *service, *included;
+       struct gatt_db_service *included;
        uint8_t value[MAX_INCLUDED_VALUE_LEN];
        uint16_t included_handle, len = 0;
        int index;
 
-       if (!attrib || !include)
-               return NULL;
-
-       service = attrib->service;
        included = include->service;
 
        /* Adjust include to point to the first attribute */
@@ -874,7 +912,14 @@ gatt_db_service_add_included(struct gatt_db_attribute *attrib,
        if (!index)
                return NULL;
 
-       service->attributes[index] = new_attribute(service, 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, index - 1) + 1;
+
+       service->attributes[index] = new_attribute(service, handle,
                                                        &included_service_uuid,
                                                        value, len);
        if (!service->attributes[index])
@@ -890,6 +935,40 @@ gatt_db_service_add_included(struct gatt_db_attribute *attrib,
        return attribute_update(service, index);
 }
 
+struct gatt_db_attribute *
+gatt_db_service_add_included(struct gatt_db_attribute *attrib,
+                                       struct gatt_db_attribute *include)
+{
+       if (!attrib || !include)
+               return NULL;
+
+       return service_insert_included(attrib->service, 0, include);
+}
+
+struct gatt_db_attribute *
+gatt_db_service_insert_included(struct gatt_db_attribute *attrib,
+                               uint16_t handle,
+                               struct gatt_db_attribute *include)
+{
+       if (!attrib || !handle || !include)
+               return NULL;
+
+       return service_insert_included(attrib->service, handle, include);
+}
+
+struct gatt_db_attribute *
+gatt_db_insert_included(struct gatt_db *db, uint16_t handle,
+                       struct gatt_db_attribute *include)
+{
+       struct gatt_db_attribute *attrib;
+
+       attrib = gatt_db_get_service(db, handle);
+       if (!attrib)
+               return NULL;
+
+       return service_insert_included(attrib->service, handle, include);
+}
+
 bool gatt_db_service_set_active(struct gatt_db_attribute *attrib, bool active)
 {
        struct gatt_db_service *service;
@@ -1317,20 +1396,35 @@ static bool find_service_for_handle(const void *data, const void *user_data)
        return (start <= handle) && (handle <= end);
 }
 
-struct gatt_db_attribute *gatt_db_get_attribute(struct gatt_db *db,
+struct gatt_db_attribute *gatt_db_get_service(struct gatt_db *db,
                                                        uint16_t handle)
 {
        struct gatt_db_service *service;
-       int i;
 
        if (!db || !handle)
                return NULL;
 
        service = queue_find(db->services, find_service_for_handle,
-                                                       UINT_TO_PTR(handle));
+                                               UINT_TO_PTR(handle));
        if (!service)
                return NULL;
 
+       return service->attributes[0];
+}
+
+struct gatt_db_attribute *gatt_db_get_attribute(struct gatt_db *db,
+                                                       uint16_t handle)
+{
+       struct gatt_db_attribute *attrib;
+       struct gatt_db_service *service;
+       int i;
+
+       attrib = gatt_db_get_service(db, handle);
+       if (!attrib)
+               return NULL;
+
+       service = attrib->service;
+
        for (i = 0; i < service->num_handles; i++) {
                if (!service->attributes[i])
                        continue;
index f9044f1..e256d4a 100644 (file)
@@ -78,6 +78,25 @@ gatt_db_service_insert_characteristic(struct gatt_db_attribute *attrib,
                                        void *user_data);
 
 struct gatt_db_attribute *
+gatt_db_insert_characteristic(struct gatt_db *db,
+                                       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_insert_descriptor(struct gatt_db *db,
+                                       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_descriptor(struct gatt_db_attribute *attrib,
                                        const bt_uuid_t *uuid,
                                        uint32_t permissions,
@@ -94,8 +113,16 @@ gatt_db_service_insert_descriptor(struct gatt_db_attribute *attrib,
                                        void *user_data);
 
 struct gatt_db_attribute *
+gatt_db_insert_included(struct gatt_db *db, uint16_t handle,
+                       struct gatt_db_attribute *include);
+
+struct gatt_db_attribute *
 gatt_db_service_add_included(struct gatt_db_attribute *attrib,
                                        struct gatt_db_attribute *include);
+struct gatt_db_attribute *
+gatt_db_service_insert_included(struct gatt_db_attribute *attrib,
+                               uint16_t handle,
+                               struct gatt_db_attribute *include);
 
 bool gatt_db_service_set_active(struct gatt_db_attribute *attrib, bool active);
 bool gatt_db_service_get_active(struct gatt_db_attribute *attrib);
@@ -170,6 +197,9 @@ unsigned int gatt_db_register(struct gatt_db *db,
                                        gatt_db_destroy_func_t destroy);
 bool gatt_db_unregister(struct gatt_db *db, unsigned int id);
 
+struct gatt_db_attribute *gatt_db_get_service(struct gatt_db *db,
+                                                       uint16_t handle);
+
 struct gatt_db_attribute *gatt_db_get_attribute(struct gatt_db *db,
                                                        uint16_t handle);