Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH BlueZ 1/2] gatt: Add confirmation callback
@ 2018-03-19 12:44 Luiz Augusto von Dentz
  2018-03-19 12:44 ` [PATCH BlueZ 2/2] gatt: Properly handle service changes when offline Luiz Augusto von Dentz
  2018-03-22 14:55 ` [PATCH BlueZ 1/2] gatt: Add confirmation callback Szymon Janc
  0 siblings, 2 replies; 3+ messages in thread
From: Luiz Augusto von Dentz @ 2018-03-19 12:44 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This replaces indicate flag with confirmation callback to enable
setting custom callback if necessary.
---
 src/gatt-database.c | 33 ++++++++++++++++++++-------------
 1 file changed, 20 insertions(+), 13 deletions(-)

diff --git a/src/gatt-database.c b/src/gatt-database.c
index 9a33ae7f9..82f376568 100644
--- a/src/gatt-database.c
+++ b/src/gatt-database.c
@@ -956,8 +956,8 @@ struct notify {
 	uint16_t handle, ccc_handle;
 	const uint8_t *value;
 	uint16_t len;
-	bool indicate;
-	GDBusProxy *proxy;
+	bt_gatt_server_conf_func_t conf;
+	void *user_data;
 };
 
 static void conf_cb(void *user_data)
@@ -983,7 +983,7 @@ static void send_notification_to_device(void *data, void *user_data)
 	if (!ccc)
 		return;
 
-	if (!ccc->value[0] || (notify->indicate && !(ccc->value[0] & 0x02)))
+	if (!ccc->value[0] || (notify->conf && !(ccc->value[0] & 0x02)))
 		return;
 
 	device = btd_adapter_get_device(notify->database->adapter,
@@ -1003,7 +1003,7 @@ static void send_notification_to_device(void *data, void *user_data)
 	 * TODO: If the device is not connected but bonded, send the
 	 * notification/indication when it becomes connected.
 	 */
-	if (!notify->indicate) {
+	if (!notify->conf) {
 		DBG("GATT server sending notification");
 		bt_gatt_server_send_notification(server,
 					notify->handle, notify->value,
@@ -1013,8 +1013,8 @@ static void send_notification_to_device(void *data, void *user_data)
 
 	DBG("GATT server sending indication");
 	bt_gatt_server_send_indication(server, notify->handle, notify->value,
-							notify->len, conf_cb,
-							notify->proxy, NULL);
+						notify->len, notify->conf,
+						notify->user_data, NULL);
 
 	return;
 
@@ -1027,10 +1027,16 @@ 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 len, uint16_t ccc_handle,
-					bool indicate, GDBusProxy *proxy)
+					bt_gatt_server_conf_func_t conf,
+					void *user_data)
 {
 	struct notify notify;
 
@@ -1041,8 +1047,8 @@ static void send_notification_to_devices(struct btd_gatt_database *database,
 	notify.ccc_handle = ccc_handle;
 	notify.value = value;
 	notify.len = len;
-	notify.indicate = indicate;
-	notify.proxy = proxy;
+	notify.conf = conf;
+	notify.user_data = user_data;
 
 	queue_foreach(database->device_states, send_notification_to_device,
 								&notify);
@@ -1073,7 +1079,7 @@ static void send_service_changed(struct btd_gatt_database *database,
 	put_le16(end, value + 2);
 
 	send_notification_to_devices(database, handle, value, sizeof(value),
-							ccc_handle, true, NULL);
+					ccc_handle, service_changed_conf, NULL);
 }
 
 static void gatt_db_service_added(struct gatt_db_attribute *attrib,
@@ -1948,8 +1954,8 @@ static bool pipe_io_read(struct io *io, void *user_data)
 				gatt_db_attribute_get_handle(chrc->attrib),
 				buf, bytes_read,
 				gatt_db_attribute_get_handle(chrc->ccc),
-				chrc->props & BT_GATT_CHRC_PROP_INDICATE,
-				chrc->proxy);
+				chrc->props & BT_GATT_CHRC_PROP_INDICATE ?
+				conf_cb : NULL, chrc->proxy);
 
 	return true;
 }
@@ -2225,7 +2231,8 @@ static void property_changed_cb(GDBusProxy *proxy, const char *name,
 				gatt_db_attribute_get_handle(chrc->attrib),
 				value, len,
 				gatt_db_attribute_get_handle(chrc->ccc),
-				chrc->props & BT_GATT_CHRC_PROP_INDICATE, proxy);
+				chrc->props & BT_GATT_CHRC_PROP_INDICATE ?
+				conf_cb : NULL, proxy);
 }
 
 static bool database_add_ccc(struct external_service *service,
-- 
2.14.3


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH BlueZ 2/2] gatt: Properly handle service changes when offline
  2018-03-19 12:44 [PATCH BlueZ 1/2] gatt: Add confirmation callback Luiz Augusto von Dentz
@ 2018-03-19 12:44 ` Luiz Augusto von Dentz
  2018-03-22 14:55 ` [PATCH BlueZ 1/2] gatt: Add confirmation callback Szymon Janc
  1 sibling, 0 replies; 3+ messages in thread
From: Luiz Augusto von Dentz @ 2018-03-19 12:44 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

If remote peer is disconnected the indication shall be cached so when
the peer connects again it receives the changes.
---
 src/device.c        |  9 ++++--
 src/gatt-database.c | 89 ++++++++++++++++++++++++++++++++++++++++++++---------
 src/gatt-database.h |  2 ++
 3 files changed, 83 insertions(+), 17 deletions(-)

diff --git a/src/device.c b/src/device.c
index 7c7196ca1..bf5441543 100644
--- a/src/device.c
+++ b/src/device.c
@@ -4825,8 +4825,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;
@@ -4839,6 +4842,8 @@ static void gatt_server_init(struct btd_device *device, struct gatt_db *db)
 		error("Failed to initialize bt_gatt_server");
 
 	bt_gatt_server_set_debug(device->server, gatt_debug, NULL, NULL);
+
+	btd_gatt_database_att_connected(database, device->att);
 }
 
 static bool local_counter(uint32_t *sign_cnt, void *user_data)
@@ -4938,7 +4943,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
diff --git a/src/gatt-database.c b/src/gatt-database.c
index 82f376568..92d0cd248 100644
--- a/src/gatt-database.c
+++ b/src/gatt-database.c
@@ -155,12 +155,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,
@@ -273,6 +283,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);
 }
 
@@ -951,15 +967,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;
-};
-
 static void conf_cb(void *user_data)
 {
 	GDBusProxy *proxy = user_data;
@@ -971,6 +978,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);
+}
+
 static void send_notification_to_device(void *data, void *user_data)
 {
 	struct device_state *device_state = data;
@@ -996,6 +1038,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;
 	}
 
@@ -1027,13 +1070,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)
@@ -3080,3 +3118,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;
+}
diff --git a/src/gatt-database.h b/src/gatt-database.h
index 0d9106b11..0da33f604 100644
--- a/src/gatt-database.h
+++ b/src/gatt-database.h
@@ -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);
-- 
2.14.3


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH BlueZ 1/2] gatt: Add confirmation callback
  2018-03-19 12:44 [PATCH BlueZ 1/2] gatt: Add confirmation callback Luiz Augusto von Dentz
  2018-03-19 12:44 ` [PATCH BlueZ 2/2] gatt: Properly handle service changes when offline Luiz Augusto von Dentz
@ 2018-03-22 14:55 ` Szymon Janc
  1 sibling, 0 replies; 3+ messages in thread
From: Szymon Janc @ 2018-03-22 14:55 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth

Hi Luiz,

On Monday, 19 March 2018 13:44:26 CET Luiz Augusto von Dentz wrote:
> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
> 
> This replaces indicate flag with confirmation callback to enable
> setting custom callback if necessary.
> ---
>  src/gatt-database.c | 33 ++++++++++++++++++++-------------
>  1 file changed, 20 insertions(+), 13 deletions(-)
> 
> diff --git a/src/gatt-database.c b/src/gatt-database.c
> index 9a33ae7f9..82f376568 100644
> --- a/src/gatt-database.c
> +++ b/src/gatt-database.c
> @@ -956,8 +956,8 @@ struct notify {
>  	uint16_t handle, ccc_handle;
>  	const uint8_t *value;
>  	uint16_t len;
> -	bool indicate;
> -	GDBusProxy *proxy;
> +	bt_gatt_server_conf_func_t conf;
> +	void *user_data;
>  };
> 
>  static void conf_cb(void *user_data)
> @@ -983,7 +983,7 @@ static void send_notification_to_device(void *data, void
> *user_data) if (!ccc)
>  		return;
> 
> -	if (!ccc->value[0] || (notify->indicate && !(ccc->value[0] & 0x02)))
> +	if (!ccc->value[0] || (notify->conf && !(ccc->value[0] & 0x02)))
>  		return;
> 
>  	device = btd_adapter_get_device(notify->database->adapter,
> @@ -1003,7 +1003,7 @@ static void send_notification_to_device(void *data,
> void *user_data) * TODO: If the device is not connected but bonded, send
> the
>  	 * notification/indication when it becomes connected.
>  	 */
> -	if (!notify->indicate) {
> +	if (!notify->conf) {
>  		DBG("GATT server sending notification");
>  		bt_gatt_server_send_notification(server,
>  					notify->handle, notify->value,
> @@ -1013,8 +1013,8 @@ static void send_notification_to_device(void *data,
> void *user_data)
> 
>  	DBG("GATT server sending indication");
>  	bt_gatt_server_send_indication(server, notify->handle, notify->value,
> -							notify->len, conf_cb,
> -							notify->proxy, NULL);
> +						notify->len, notify->conf,
> +						notify->user_data, NULL);
> 
>  	return;
> 
> @@ -1027,10 +1027,16 @@ 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 len, uint16_t ccc_handle,
> -					bool indicate, GDBusProxy *proxy)
> +					bt_gatt_server_conf_func_t conf,
> +					void *user_data)
>  {
>  	struct notify notify;
> 
> @@ -1041,8 +1047,8 @@ static void send_notification_to_devices(struct
> btd_gatt_database *database, notify.ccc_handle = ccc_handle;
>  	notify.value = value;
>  	notify.len = len;
> -	notify.indicate = indicate;
> -	notify.proxy = proxy;
> +	notify.conf = conf;
> +	notify.user_data = user_data;
> 
>  	queue_foreach(database->device_states, send_notification_to_device,
>  								&notify);
> @@ -1073,7 +1079,7 @@ static void send_service_changed(struct
> btd_gatt_database *database, put_le16(end, value + 2);
> 
>  	send_notification_to_devices(database, handle, value, sizeof(value),
> -							ccc_handle, true, NULL);
> +					ccc_handle, service_changed_conf, NULL);
>  }
> 
>  static void gatt_db_service_added(struct gatt_db_attribute *attrib,
> @@ -1948,8 +1954,8 @@ static bool pipe_io_read(struct io *io, void
> *user_data) gatt_db_attribute_get_handle(chrc->attrib),
>  				buf, bytes_read,
>  				gatt_db_attribute_get_handle(chrc->ccc),
> -				chrc->props & BT_GATT_CHRC_PROP_INDICATE,
> -				chrc->proxy);
> +				chrc->props & BT_GATT_CHRC_PROP_INDICATE ?
> +				conf_cb : NULL, chrc->proxy);
> 
>  	return true;
>  }
> @@ -2225,7 +2231,8 @@ static void property_changed_cb(GDBusProxy *proxy,
> const char *name, gatt_db_attribute_get_handle(chrc->attrib),
>  				value, len,
>  				gatt_db_attribute_get_handle(chrc->ccc),
> -				chrc->props & BT_GATT_CHRC_PROP_INDICATE, proxy);
> +				chrc->props & BT_GATT_CHRC_PROP_INDICATE ?
> +				conf_cb : NULL, proxy);
>  }
> 
>  static bool database_add_ccc(struct external_service *service,

Both patches applied, thanks.

-- 
pozdrawiam
Szymon Janc



^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2018-03-22 14:55 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-03-19 12:44 [PATCH BlueZ 1/2] gatt: Add confirmation callback Luiz Augusto von Dentz
2018-03-19 12:44 ` [PATCH BlueZ 2/2] gatt: Properly handle service changes when offline Luiz Augusto von Dentz
2018-03-22 14:55 ` [PATCH BlueZ 1/2] gatt: Add confirmation callback Szymon Janc

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox