[PATCH BlueZ 3/9] shared/gatt-client: Register "Service Changed" handler as part of init.

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

 



This patch changes shared/gatt-client so that a struct bt_gatt_client
registers a handler for indications from the "Service Changed" characteristic
at the end of its init sequence if the characteristic was discovered. The
handles for the Service Changed characteristic value and the GATT service are
stored during discovery.
---
 src/shared/gatt-client.c | 103 ++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 98 insertions(+), 5 deletions(-)

diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c
index d0c12df..1a6fd86 100644
--- a/src/shared/gatt-client.c
+++ b/src/shared/gatt-client.c
@@ -41,6 +41,9 @@
 
 #define UUID_BYTES (BT_GATT_UUID_SIZE * sizeof(uint8_t))
 
+#define GATT_SVC_UUID	0x1801
+#define SVC_CHNGD_UUID	0x2a05
+
 struct chrc_data {
 	/* The public characteristic entry. */
 	bt_gatt_characteristic_t chrc_external;
@@ -100,6 +103,14 @@ struct bt_gatt_client {
 	unsigned int notify_id, ind_id;
 	bool in_notify;
 	bool need_notify_cleanup;
+
+	/* Handles of the GATT Service and the Service Changed characteristic
+	 * value handle. These will have the value 0 if they are not present on
+	 * the remote peripheral.
+	 */
+	uint16_t gatt_svc_handle;
+	uint16_t svc_chngd_val_handle;
+	unsigned int svc_chngd_ind_id;
 };
 
 static bool service_list_add_service(struct service_list **head,
@@ -387,6 +398,10 @@ static void discover_chrcs_cb(bool success, uint8_t att_ecode,
 			goto done;
 		}
 
+		if (uuid_cmp(chrcs[i].chrc_external.uuid, SVC_CHNGD_UUID) == 0)
+			client->svc_chngd_val_handle =
+					chrcs[i].chrc_external.value_handle;
+
 		i++;
 	}
 
@@ -479,6 +494,9 @@ static void discover_primary_cb(bool success, uint8_t att_ecode,
 			success = false;
 			goto done;
 		}
+
+		if (uuid_cmp(uuid, GATT_SVC_UUID) == 0)
+			client->gatt_svc_handle = start;
 	}
 
 	/* Complete the process if the service list is empty */
@@ -544,20 +562,95 @@ static void exchange_mtu_cb(bool success, uint8_t att_ecode, void *user_data)
 	discovery_op_unref(op);
 }
 
+static void service_changed_cb(uint16_t value_handle, const uint8_t *value,
+					uint16_t length, void *user_data)
+{
+	struct bt_gatt_client *client = user_data;
+	uint16_t start, end;
+
+	if (value_handle != client->svc_chngd_val_handle || length != 4)
+		return;
+
+	start = get_le16(value);
+	end = get_le16(value + 2);
+
+	util_debug(client->debug_callback, client->debug_data,
+			"Service Changed received - start: 0x%04x end: 0x%04x",
+			start, end);
+
+	/* TODO: Process changed services */
+}
+
+static void service_changed_register_cb(unsigned int id, uint16_t att_ecode,
+								void *user_data)
+{
+	bool success;
+	struct bt_gatt_client *client = user_data;
+
+	if (!id || att_ecode) {
+		util_debug(client->debug_callback, client->debug_data,
+			"Failed to register handler for \"Service Changed\"");
+		success = false;
+		goto done;
+	}
+
+	client->svc_chngd_ind_id = id;
+	client->ready = true;
+	success = true;
+	util_debug(client->debug_callback, client->debug_data,
+			"Registered handler for \"Service Changed\": %u", id);
+
+done:
+	if (client->ready_callback)
+		client->ready_callback(success, att_ecode, client->ready_data);
+}
+
 static void init_complete(struct discovery_op *op, bool success,
 							uint8_t att_ecode)
 {
 	struct bt_gatt_client *client = op->client;
+	bool registered;
 
 	client->in_init = false;
 
-	if (success) {
-		client->svc_head = op->result_head;
-		client->svc_tail = op->result_tail;
+	if (!success)
+		goto fail;
+
+	client->svc_head = op->result_head;
+	client->svc_tail = op->result_tail;
+
+	if (!client->svc_chngd_val_handle) {
 		client->ready = true;
-	} else
-		service_list_clear(&op->result_head, &op->result_tail);
+		goto done;
+	}
+
+	/* Register an indication handler for the "Service Changed"
+	 * characteristic and report ready only if the handler is registered
+	 * successfully. Temporarily set "ready" to true so that we can register
+	 * the handler using the existing framework.
+	 */
+	client->ready = true;
+	registered = bt_gatt_client_register_notify(client,
+						client->svc_chngd_val_handle,
+						service_changed_register_cb,
+						service_changed_cb,
+						client, NULL);
+	client->ready = false;
+
+	if (registered)
+		return;
 
+	util_debug(client->debug_callback, client->debug_data,
+			"Failed to register handler for \"Service Changed\"");
+
+	client->svc_head = client->svc_tail = NULL;
+
+fail:
+	util_debug(client->debug_callback, client->debug_data,
+			"Failed to initialize gatt-client");
+	service_list_clear(&op->result_head, &op->result_tail);
+
+done:
 	if (client->ready_callback)
 		client->ready_callback(success, att_ecode, client->ready_data);
 }
-- 
2.1.0.rc2.206.gedb03e5

--
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