gatt: Properly handle service changes when offline 51/204951/1
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Mon, 19 Mar 2018 12:44:27 +0000 (14:44 +0200)
committerAmit Purwar <amit.purwar@samsung.com>
Fri, 26 Apr 2019 10:53:12 +0000 (16:23 +0530)
If remote peer is disconnected the indication shall be cached so when
the peer connects again it receives the changes.

Change-Id: Ic887ae4f56fdd80efa998e12f6d42f018ad7a6b3
Signed-off-by: Amit Purwar <amit.purwar@samsung.com>
src/device.c
src/gatt-database.c
src/gatt-database.h

index 5b7c0b9..5321f6e 100644 (file)
@@ -7054,8 +7054,11 @@ static void gatt_client_init(struct btd_device *device)
        btd_gatt_client_connected(device->client_dbus);
 }
 
-static void gatt_server_init(struct btd_device *device, struct gatt_db *db)
+static void gatt_server_init(struct btd_device *device,
+                               struct btd_gatt_database *database)
 {
+       struct gatt_db *db = btd_gatt_database_get_db(database);
+
        if (!db) {
                error("No local GATT database exists for this adapter");
                return;
@@ -7077,6 +7080,7 @@ static void gatt_server_init(struct btd_device *device, struct gatt_db *db)
                return;
        }
 #endif
+       btd_gatt_database_att_connected(database, device->att);
 }
 
 static bool local_counter(uint32_t *sign_cnt, void *user_data)
@@ -7225,7 +7229,7 @@ bool device_attach_att(struct btd_device *dev, GIOChannel *io)
                                                                dstaddr);
 
        gatt_client_init(dev);
-       gatt_server_init(dev, btd_gatt_database_get_db(database));
+       gatt_server_init(dev, database);
 
        /*
         * Remove the device from the connect_list and give the passive
index f704f3c..2ba6f15 100644 (file)
@@ -156,12 +156,22 @@ struct pending_op {
        struct iovec data;
 };
 
+struct notify {
+       struct btd_gatt_database *database;
+       uint16_t handle, ccc_handle;
+       uint8_t *value;
+       uint16_t len;
+       bt_gatt_server_conf_func_t conf;
+       void *user_data;
+};
+
 struct device_state {
        struct btd_gatt_database *db;
        bdaddr_t bdaddr;
        uint8_t bdaddr_type;
        unsigned int disc_id;
        struct queue *ccc_states;
+       struct notify *pending;
 };
 
 typedef uint8_t (*btd_gatt_database_ccc_write_t) (struct bt_att *att,
@@ -284,6 +294,12 @@ static void device_state_free(void *data)
        struct device_state *state = data;
 
        queue_destroy(state->ccc_states, free);
+
+       if (state->pending) {
+               free(state->pending->value);
+               free(state->pending);
+       }
+
        free(state);
 }
 
@@ -1132,15 +1148,6 @@ static void register_core_services(struct btd_gatt_database *database)
        populate_gatt_service(database);
 }
 
-struct notify {
-       struct btd_gatt_database *database;
-       uint16_t handle, ccc_handle;
-       const uint8_t *value;
-       uint16_t len;
-       bt_gatt_server_conf_func_t conf;
-       void *user_data;
-};
-
 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
 struct notify_indicate {
        struct btd_gatt_database *database;
@@ -1207,6 +1214,41 @@ static void conf_cb(void *user_data)
 
 }
 
+static void service_changed_conf(void *user_data)
+{
+       DBG("");
+}
+
+static void state_set_pending(struct device_state *state, struct notify *notify)
+{
+       uint16_t start, end, old_start, old_end;
+
+       if (notify->conf != service_changed_conf)
+               return;
+
+       if (state->pending) {
+               old_start = get_le16(state->pending->value);
+               old_end = get_le16(state->pending->value + 2);
+
+               start = get_le16(notify->value);
+               end = get_le16(notify->value + 2);
+
+               if (start < old_start)
+                       put_le16(start, state->pending->value);
+
+               if (end > old_end)
+                       put_le16(end, state->pending->value + 2);
+
+               return;
+       }
+
+       /* Copy notify contents to pending */
+       state->pending = new0(struct notify, 1);
+       memcpy(state->pending, notify, sizeof(*notify));
+       state->pending->value = malloc(notify->len);
+       memcpy(state->pending->value, notify->value, notify->len);
+}
+
 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
 static void conf_cb_tizen(void *user_data)
 {
@@ -1358,6 +1400,7 @@ static void send_notification_to_device(void *data, void *user_data)
        if (!server) {
                if (!device_is_paired(device, device_state->bdaddr_type))
                        goto remove;
+               state_set_pending(device_state, notify);
                return;
        }
 
@@ -1389,13 +1432,8 @@ remove:
        }
 }
 
-static void service_changed_conf(void *user_data)
-{
-       DBG("");
-}
-
 static void send_notification_to_devices(struct btd_gatt_database *database,
-                                       uint16_t handle, const uint8_t *value,
+                                       uint16_t handle, uint8_t *value,
                                        uint16_t len, uint16_t ccc_handle,
                                        bt_gatt_server_conf_func_t conf,
                                        void *user_data)
@@ -3708,3 +3746,24 @@ struct gatt_db *btd_gatt_database_get_db(struct btd_gatt_database *database)
 
        return database->db;
 }
+
+void btd_gatt_database_att_connected(struct btd_gatt_database *database,
+                                               struct bt_att *att)
+{
+       struct device_state *state;
+       bdaddr_t bdaddr;
+       uint8_t bdaddr_type;
+
+       if (!get_dst_info(att, &bdaddr, &bdaddr_type))
+               return;
+
+       state = find_device_state(database, &bdaddr, bdaddr_type);
+       if (!state || !state->pending)
+               return;
+
+       send_notification_to_device(state, state->pending);
+
+       free(state->pending->value);
+       free(state->pending);
+       state->pending = NULL;
+}
index 0d9106b..0da33f6 100755 (executable)
@@ -23,3 +23,5 @@ struct btd_gatt_database *btd_gatt_database_new(struct btd_adapter *adapter);
 void btd_gatt_database_destroy(struct btd_gatt_database *database);
 
 struct gatt_db *btd_gatt_database_get_db(struct btd_gatt_database *database);
+void btd_gatt_database_att_connected(struct btd_gatt_database *database,
+                                               struct bt_att *att);