diff options
author | Luiz Augusto von Dentz <luiz.von.dentz@intel.com> | 2018-03-02 14:27:48 +0200 |
---|---|---|
committer | himanshu <h.himanshu@samsung.com> | 2020-02-11 14:27:47 +0530 |
commit | 7598b46b1e6b8c65809bdbb8e78849c7c8bb4325 (patch) | |
tree | 0bff74a6a2e35af6ef209522f6404b3bf728a6ec /src | |
parent | 118786cae7874eeab7c6e42bdfa78290fd238491 (diff) | |
download | bluez-7598b46b1e6b8c65809bdbb8e78849c7c8bb4325.tar.gz bluez-7598b46b1e6b8c65809bdbb8e78849c7c8bb4325.tar.bz2 bluez-7598b46b1e6b8c65809bdbb8e78849c7c8bb4325.zip |
gatt: Implement Robust Caching handling for server
This detects when a client becomes change-unware returning
DB Out of Sync error when that happens.
Change-Id: I0377d966ac00fbb5e17b0f2b74c660ca72d71c83
Signed-off-by: himanshu <h.himanshu@samsung.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/device.c | 1 | ||||
-rw-r--r-- | src/gatt-database.c | 74 | ||||
-rwxr-xr-x | src/gatt-database.h | 4 |
3 files changed, 73 insertions, 6 deletions
diff --git a/src/device.c b/src/device.c index a5aafba9..c01821fe 100644 --- a/src/device.c +++ b/src/device.c @@ -7220,7 +7220,6 @@ static void gatt_server_init(struct btd_device *device, return; } #endif - btd_gatt_database_att_connected(database, device->att); } static bool local_counter(uint32_t *sign_cnt, void *user_data) diff --git a/src/gatt-database.c b/src/gatt-database.c index fe7fa270..ff157599 100644 --- a/src/gatt-database.c +++ b/src/gatt-database.c @@ -183,6 +183,8 @@ struct device_state { uint8_t bdaddr_type; unsigned int disc_id; uint8_t cli_feat[1]; + bool change_aware; + bool out_of_sync; struct queue *ccc_states; struct notify *pending; }; @@ -341,6 +343,7 @@ static void att_disconnected(int err, void *user_data) DBG(""); state->disc_id = 0; + state->out_of_sync = false; device = btd_adapter_find_device(state->db->adapter, &state->bdaddr, state->bdaddr_type); @@ -1294,10 +1297,13 @@ static void cli_feat_write_cb(struct gatt_db_attribute *attrib, /* Shall we reallocate the feat array if bigger? */ len = MIN(sizeof(state->cli_feat), len); while (len) { - state->cli_feat[len - 1] |= value[len -1]; + state->cli_feat[len - 1] |= value[len - 1]; len--; } + state->cli_feat[0] &= BT_GATT_CHRC_CLI_FEAT_ROBUST_CACHING; + state->change_aware = true; + done: gatt_db_attribute_write_result(attrib, id, ecode); } @@ -1309,12 +1315,22 @@ static void db_hash_read_cb(struct gatt_db_attribute *attrib, { struct btd_gatt_database *database = user_data; const uint8_t *hash; + struct device_state *state; + bdaddr_t bdaddr; + uint8_t bdaddr_type; DBG("Database Hash read"); hash = gatt_db_get_hash(database->db); gatt_db_attribute_read_result(attrib, id, 0, hash, 16); + + if (!get_dst_info(att, &bdaddr, &bdaddr_type)) + return; + + state = find_device_state(database, &bdaddr, bdaddr_type); + if (state) + state->change_aware = true; } static void populate_gatt_service(struct btd_gatt_database *database) @@ -1427,7 +1443,14 @@ static void conf_cb(void *user_data) static void service_changed_conf(void *user_data) { + struct device_state *state = user_data; + DBG(""); + + if (!state) + return; + + state->change_aware = true; } static void state_set_pending(struct device_state *state, struct notify *notify) @@ -1595,6 +1618,14 @@ static void send_notification_to_device(void *data, void *user_data) struct btd_device *device; struct bt_gatt_server *server; + if (notify->conf == service_changed_conf) { + if (device_state->cli_feat[0] & + BT_GATT_CHRC_CLI_FEAT_ROBUST_CACHING) { + device_state->change_aware = false; + notify->user_data = device_state; + } + } + ccc = find_ccc_state(device_state, notify->ccc_handle); if (!ccc) return; @@ -4016,6 +4047,40 @@ static const GDBusMethodTable manager_methods[] = { { } }; +static uint8_t server_authorize(struct bt_att *att, uint8_t opcode, + uint16_t handle, void *user_data) +{ + struct btd_gatt_database *database = user_data; + struct device_state *state; + bdaddr_t bdaddr; + uint8_t bdaddr_type; + + if (!get_dst_info(att, &bdaddr, &bdaddr_type)) + return 0; + + /* Skip if there is no device state */ + state = find_device_state(database, &bdaddr, bdaddr_type); + if (!state) + return 0; + + /* Skip if client doesn't support Robust Caching */ + if (!(state->cli_feat[0] & BT_GATT_CHRC_CLI_FEAT_ROBUST_CACHING)) + return 0; + + if (state->change_aware) + return 0; + + if (state->out_of_sync) { + state->out_of_sync = false; + state->change_aware = true; + return 0; + } + + state->out_of_sync = true; + + return BT_ATT_ERROR_DB_OUT_OF_SYNC; +} + struct btd_gatt_database *btd_gatt_database_new(struct btd_adapter *adapter) { struct btd_gatt_database *database; @@ -4106,9 +4171,10 @@ 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) +void btd_gatt_database_server_connected(struct btd_gatt_database *database, + struct bt_gatt_server *server) { + struct bt_att *att = bt_gatt_server_get_att(server); struct device_state *state; bdaddr_t bdaddr; uint8_t bdaddr_type; @@ -4116,6 +4182,8 @@ void btd_gatt_database_att_connected(struct btd_gatt_database *database, if (!get_dst_info(att, &bdaddr, &bdaddr_type)) return; + bt_gatt_server_set_authorize(server, server_authorize, database); + state = find_device_state(database, &bdaddr, bdaddr_type); if (!state || !state->pending) return; diff --git a/src/gatt-database.h b/src/gatt-database.h index a77a0fb2..154d3243 100755 --- a/src/gatt-database.h +++ b/src/gatt-database.h @@ -23,9 +23,9 @@ 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); void btd_gatt_database_att_disconnected(struct btd_gatt_database *database, struct btd_device *device); +void btd_gatt_database_server_connected(struct btd_gatt_database *database, + struct bt_gatt_server *server); void btd_gatt_database_restore_svc_chng_ccc(struct btd_gatt_database *database); |