linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH BlueZ 1/5] gattrib: Add support for listening for events for specific handles
@ 2012-10-10 23:55 Vinicius Costa Gomes
  2012-10-10 23:55 ` [PATCH BlueZ 2/5] scan: Use the per handle GATT event notifier Vinicius Costa Gomes
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Vinicius Costa Gomes @ 2012-10-10 23:55 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Vinicius Costa Gomes

We want only the profile that implements a service to be notified of
changes on that service. Before this patch, all the registered event
notifiers are being called.
---
Hi,

I am re-sending this series because, if it makes sense, it would be awesome
if it gets the "UPF treatment".

Cheers,


 attrib/client.c                    |  4 ++--
 attrib/gattrib.c                   | 33 ++++++++++++++++++++++++++++-----
 attrib/gattrib.h                   |  7 ++++---
 attrib/gatttool.c                  |  8 ++++----
 attrib/interactive.c               |  8 ++++----
 profiles/gatt/gas.c                |  1 +
 profiles/heartrate/heartrate.c     |  2 +-
 profiles/input/hog_device.c        |  5 +++--
 profiles/scanparam/scan.c          |  4 ++--
 profiles/thermometer/thermometer.c |  2 ++
 src/attrib-server.c                |  2 +-
 11 files changed, 52 insertions(+), 24 deletions(-)

diff --git a/attrib/client.c b/attrib/client.c
index 8b29cbb..cda5bc0 100644
--- a/attrib/client.c
+++ b/attrib/client.c
@@ -393,9 +393,9 @@ static void attio_connected(GAttrib *attrib, gpointer user_data)
 	gatt->attrib = g_attrib_ref(attrib);
 
 	g_attrib_register(gatt->attrib, ATT_OP_HANDLE_NOTIFY,
-					events_handler, gatt, NULL);
+			GATTRIB_ALL_HANDLES, events_handler, gatt, NULL);
 	g_attrib_register(gatt->attrib, ATT_OP_HANDLE_IND,
-					events_handler, gatt, NULL);
+			GATTRIB_ALL_HANDLES, events_handler, gatt, NULL);
 
 	g_slist_foreach(gatt->offline_chars, offline_char_write, attrib);
 
diff --git a/attrib/gattrib.c b/attrib/gattrib.c
index 0806101..309e58f 100644
--- a/attrib/gattrib.c
+++ b/attrib/gattrib.c
@@ -70,6 +70,7 @@ struct command {
 struct event {
 	guint id;
 	guint8 expected;
+	guint16 handle;
 	GAttribNotifyFunc func;
 	gpointer user_data;
 	GDestroyNotify notify;
@@ -357,6 +358,30 @@ static void wake_up_sender(struct _GAttrib *attrib)
 				can_write_data, attrib, destroy_sender);
 }
 
+static gboolean match_event(struct event *evt, const uint8_t *pdu, gsize len)
+{
+	guint16 handle;
+
+	if (evt->expected == GATTRIB_ALL_EVENTS)
+		return TRUE;
+
+	if (is_response(pdu[0]) == FALSE && evt->expected == GATTRIB_ALL_REQS)
+		return TRUE;
+
+	if (evt->expected == pdu[0] && evt->handle == GATTRIB_ALL_HANDLES)
+		return TRUE;
+
+	if (len < 3)
+		return FALSE;
+
+	handle = att_get_u16(&pdu[1]);
+
+	if (evt->expected == pdu[0] && evt->handle == handle)
+		return TRUE;
+
+	return FALSE;
+}
+
 static gboolean received_data(GIOChannel *io, GIOCondition cond, gpointer data)
 {
 	struct _GAttrib *attrib = data;
@@ -387,10 +412,7 @@ static gboolean received_data(GIOChannel *io, GIOCondition cond, gpointer data)
 	for (l = attrib->events; l; l = l->next) {
 		struct event *evt = l->data;
 
-		if (evt->expected == buf[0] ||
-				evt->expected == GATTRIB_ALL_EVENTS ||
-				(is_response(buf[0]) == FALSE &&
-						evt->expected == GATTRIB_ALL_REQS))
+		if (match_event(evt, buf, len))
 			evt->func(buf, len, evt->user_data);
 	}
 
@@ -645,7 +667,7 @@ gboolean g_attrib_set_mtu(GAttrib *attrib, int mtu)
 	return TRUE;
 }
 
-guint g_attrib_register(GAttrib *attrib, guint8 opcode,
+guint g_attrib_register(GAttrib *attrib, guint8 opcode, guint16 handle,
 				GAttribNotifyFunc func, gpointer user_data,
 				GDestroyNotify notify)
 {
@@ -657,6 +679,7 @@ guint g_attrib_register(GAttrib *attrib, guint8 opcode,
 		return 0;
 
 	event->expected = opcode;
+	event->handle = handle;
 	event->func = func;
 	event->user_data = user_data;
 	event->notify = notify;
diff --git a/attrib/gattrib.h b/attrib/gattrib.h
index bca966f..3fe92c7 100644
--- a/attrib/gattrib.h
+++ b/attrib/gattrib.h
@@ -30,6 +30,7 @@ extern "C" {
 
 #define GATTRIB_ALL_EVENTS 0xFF
 #define GATTRIB_ALL_REQS 0xFE
+#define GATTRIB_ALL_HANDLES 0x0000
 
 struct _GAttrib;
 typedef struct _GAttrib GAttrib;
@@ -60,9 +61,9 @@ gboolean g_attrib_cancel_all(GAttrib *attrib);
 gboolean g_attrib_set_debug(GAttrib *attrib,
 		GAttribDebugFunc func, gpointer user_data);
 
-guint g_attrib_register(GAttrib *attrib, guint8 opcode,
-		GAttribNotifyFunc func, gpointer user_data,
-					GDestroyNotify notify);
+guint g_attrib_register(GAttrib *attrib, guint8 opcode, guint16 handle,
+				GAttribNotifyFunc func, gpointer user_data,
+				GDestroyNotify notify);
 
 gboolean g_attrib_is_encrypted(GAttrib *attrib);
 
diff --git a/attrib/gatttool.c b/attrib/gatttool.c
index 252064d..2fe95c0 100644
--- a/attrib/gatttool.c
+++ b/attrib/gatttool.c
@@ -111,10 +111,10 @@ static gboolean listen_start(gpointer user_data)
 {
 	GAttrib *attrib = user_data;
 
-	g_attrib_register(attrib, ATT_OP_HANDLE_NOTIFY, events_handler,
-							attrib, NULL);
-	g_attrib_register(attrib, ATT_OP_HANDLE_IND, events_handler,
-							attrib, NULL);
+	g_attrib_register(attrib, ATT_OP_HANDLE_NOTIFY, GATTRIB_ALL_HANDLES,
+						events_handler, attrib, NULL);
+	g_attrib_register(attrib, ATT_OP_HANDLE_IND, GATTRIB_ALL_HANDLES,
+						events_handler, attrib, NULL);
 
 	return FALSE;
 }
diff --git a/attrib/interactive.c b/attrib/interactive.c
index 716e675..6030fb7 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -147,10 +147,10 @@ static void connect_cb(GIOChannel *io, GError *err, gpointer user_data)
 	}
 
 	attrib = g_attrib_new(iochannel);
-	g_attrib_register(attrib, ATT_OP_HANDLE_NOTIFY, events_handler,
-							attrib, NULL);
-	g_attrib_register(attrib, ATT_OP_HANDLE_IND, events_handler,
-							attrib, NULL);
+	g_attrib_register(attrib, ATT_OP_HANDLE_NOTIFY, GATTRIB_ALL_HANDLES,
+						events_handler, attrib, NULL);
+	g_attrib_register(attrib, ATT_OP_HANDLE_IND, GATTRIB_ALL_HANDLES,
+						events_handler, attrib, NULL);
 	set_state(STATE_CONNECTED);
 }
 
diff --git a/profiles/gatt/gas.c b/profiles/gatt/gas.c
index f873121..bb626e7 100644
--- a/profiles/gatt/gas.c
+++ b/profiles/gatt/gas.c
@@ -334,6 +334,7 @@ static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
 	}
 
 	gas->changed_ind = g_attrib_register(gas->attrib, ATT_OP_HANDLE_IND,
+						GATTRIB_ALL_HANDLES,
 						indication_cb, gas, NULL);
 
 	if (device_get_appearance(gas->device, &app) < 0) {
diff --git a/profiles/heartrate/heartrate.c b/profiles/heartrate/heartrate.c
index 94d4b8d..d9d6c03 100644
--- a/profiles/heartrate/heartrate.c
+++ b/profiles/heartrate/heartrate.c
@@ -544,7 +544,7 @@ static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
 	hr->attrib = g_attrib_ref(attrib);
 
 	hr->attionotid = g_attrib_register(hr->attrib, ATT_OP_HANDLE_NOTIFY,
-						notify_handler, hr, NULL);
+				GATTRIB_ALL_HANDLES, notify_handler, hr, NULL);
 
 	gatt_discover_char(hr->attrib, hr->svc_range->start, hr->svc_range->end,
 						NULL, discover_char_cb, hr);
diff --git a/profiles/input/hog_device.c b/profiles/input/hog_device.c
index a8cc568..52ebd95 100644
--- a/profiles/input/hog_device.c
+++ b/profiles/input/hog_device.c
@@ -612,8 +612,9 @@ static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
 	hogdev->attrib = g_attrib_ref(attrib);
 
 	hogdev->report_cb_id = g_attrib_register(hogdev->attrib,
-					ATT_OP_HANDLE_NOTIFY, report_value_cb,
-					hogdev, NULL);
+					ATT_OP_HANDLE_NOTIFY,
+					GATTRIB_ALL_HANDLES,
+					report_value_cb, hogdev, NULL);
 
 	if (hogdev->reports == NULL) {
 		gatt_discover_char(hogdev->attrib, prim->range.start,
diff --git a/profiles/scanparam/scan.c b/profiles/scanparam/scan.c
index e523df5..bbf646c 100644
--- a/profiles/scanparam/scan.c
+++ b/profiles/scanparam/scan.c
@@ -115,8 +115,8 @@ static void ccc_written_cb(guint8 status, const guint8 *pdu,
 	DBG("Scan Refresh: notification enabled");
 
 	scan->refresh_cb_id = g_attrib_register(scan->attrib,
-					ATT_OP_HANDLE_NOTIFY, refresh_value_cb,
-					user_data, NULL);
+				ATT_OP_HANDLE_NOTIFY, GATTRIB_ALL_HANDLES,
+				refresh_value_cb, user_data, NULL);
 }
 
 static void discover_descriptor_cb(guint8 status, const guint8 *pdu,
diff --git a/profiles/thermometer/thermometer.c b/profiles/thermometer/thermometer.c
index 4a79f99..4d1df1d 100644
--- a/profiles/thermometer/thermometer.c
+++ b/profiles/thermometer/thermometer.c
@@ -1191,8 +1191,10 @@ static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
 	t->attrib = g_attrib_ref(attrib);
 
 	t->attindid = g_attrib_register(t->attrib, ATT_OP_HANDLE_IND,
+							GATTRIB_ALL_HANDLES,
 							ind_handler, t, NULL);
 	t->attnotid = g_attrib_register(t->attrib, ATT_OP_HANDLE_NOTIFY,
+							GATTRIB_ALL_HANDLES,
 							notif_handler, t, NULL);
 	gatt_discover_char(t->attrib, t->svc_range->start, t->svc_range->end,
 					NULL, configure_thermometer_cb, t);
diff --git a/src/attrib-server.c b/src/attrib-server.c
index 7117fbe..ea27b13 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -1096,7 +1096,7 @@ guint attrib_channel_attach(GAttrib *attrib)
 
 	channel->attrib = g_attrib_ref(attrib);
 	channel->id = g_attrib_register(channel->attrib, GATTRIB_ALL_REQS,
-					channel_handler, channel, NULL);
+			GATTRIB_ALL_HANDLES, channel_handler, channel, NULL);
 
 	channel->cleanup_id = g_io_add_watch(io, G_IO_HUP, channel_watch_cb,
 								channel);
-- 
1.7.12.3


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

* [PATCH BlueZ 2/5] scan: Use the per handle GATT event notifier
  2012-10-10 23:55 [PATCH BlueZ 1/5] gattrib: Add support for listening for events for specific handles Vinicius Costa Gomes
@ 2012-10-10 23:55 ` Vinicius Costa Gomes
  2012-10-10 23:55 ` [PATCH BlueZ 3/5] hog: " Vinicius Costa Gomes
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Vinicius Costa Gomes @ 2012-10-10 23:55 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Vinicius Costa Gomes

---
 profiles/scanparam/scan.c | 15 ++-------------
 1 file changed, 2 insertions(+), 13 deletions(-)

diff --git a/profiles/scanparam/scan.c b/profiles/scanparam/scan.c
index bbf646c..09fbe1f 100644
--- a/profiles/scanparam/scan.c
+++ b/profiles/scanparam/scan.c
@@ -83,17 +83,6 @@ static void refresh_value_cb(const uint8_t *pdu, uint16_t len,
 						gpointer user_data)
 {
 	struct scan *scan = user_data;
-	uint16_t handle;
-
-	if (len < 4) { /* 1-byte opcode + 2-byte handle + refresh */
-		error("Malformed ATT notification");
-		return;
-	}
-
-	handle = att_get_u16(&pdu[1]);
-
-	if (handle != scan->refresh_handle)
-		return;
 
 	DBG("Server requires refresh: %d", pdu[3]);
 
@@ -115,8 +104,8 @@ static void ccc_written_cb(guint8 status, const guint8 *pdu,
 	DBG("Scan Refresh: notification enabled");
 
 	scan->refresh_cb_id = g_attrib_register(scan->attrib,
-				ATT_OP_HANDLE_NOTIFY, GATTRIB_ALL_HANDLES,
-				refresh_value_cb, user_data, NULL);
+				ATT_OP_HANDLE_NOTIFY, scan->refresh_handle,
+				refresh_value_cb, scan, NULL);
 }
 
 static void discover_descriptor_cb(guint8 status, const guint8 *pdu,
-- 
1.7.12.3


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

* [PATCH BlueZ 3/5] hog: Use the per handle GATT event notifier
  2012-10-10 23:55 [PATCH BlueZ 1/5] gattrib: Add support for listening for events for specific handles Vinicius Costa Gomes
  2012-10-10 23:55 ` [PATCH BlueZ 2/5] scan: Use the per handle GATT event notifier Vinicius Costa Gomes
@ 2012-10-10 23:55 ` Vinicius Costa Gomes
  2012-10-10 23:55 ` [PATCH BlueZ 4/5] heartrate: " Vinicius Costa Gomes
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Vinicius Costa Gomes @ 2012-10-10 23:55 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Vinicius Costa Gomes

---
 profiles/input/hog_device.c | 70 +++++++++++++++++++++++----------------------
 1 file changed, 36 insertions(+), 34 deletions(-)

diff --git a/profiles/input/hog_device.c b/profiles/input/hog_device.c
index 52ebd95..9ac7bd7 100644
--- a/profiles/input/hog_device.c
+++ b/profiles/input/hog_device.c
@@ -76,7 +76,6 @@ struct hog_device {
 	struct btd_device	*device;
 	GAttrib			*attrib;
 	guint			attioid;
-	guint			report_cb_id;
 	struct gatt_primary	*hog_primary;
 	GSList			*reports;
 	int			uhid_fd;
@@ -92,27 +91,18 @@ struct hog_device {
 struct report {
 	uint8_t			id;
 	uint8_t			type;
+	guint			notifyid;
 	struct gatt_char	*decl;
 	struct hog_device	*hogdev;
 };
 
-static gint report_handle_cmp(gconstpointer a, gconstpointer b)
-{
-	const struct report *report = a;
-	uint16_t handle = GPOINTER_TO_UINT(b);
-
-	return report->decl->value_handle - handle;
-}
-
 static void report_value_cb(const uint8_t *pdu, uint16_t len,
 							gpointer user_data)
 {
-	struct hog_device *hogdev = user_data;
+	struct report *report = user_data;
+	struct hog_device *hogdev = report->hogdev;
 	struct uhid_event ev;
 	uint16_t report_size = len - 3;
-	guint handle;
-	GSList *l;
-	struct report *report;
 	uint8_t *buf;
 
 	if (len < 3) { /* 1-byte opcode + 2-byte handle */
@@ -120,17 +110,6 @@ static void report_value_cb(const uint8_t *pdu, uint16_t len,
 		return;
 	}
 
-	handle = att_get_u16(&pdu[1]);
-
-	l = g_slist_find_custom(hogdev->reports, GUINT_TO_POINTER(handle),
-							report_handle_cmp);
-	if (!l) {
-		error("Invalid report");
-		return;
-	}
-
-	report = l->data;
-
 	memset(&ev, 0, sizeof(ev));
 	ev.type = UHID_INPUT;
 	ev.u.input.size = MIN(report_size, UHID_DATA_MAX);
@@ -154,22 +133,31 @@ static void report_value_cb(const uint8_t *pdu, uint16_t len,
 static void report_ccc_written_cb(guint8 status, const guint8 *pdu,
 					guint16 plen, gpointer user_data)
 {
+	struct report *report = user_data;
+	struct hog_device *hogdev = report->hogdev;
+
 	if (status != 0) {
 		error("Write report characteristic descriptor failed: %s",
 							att_ecode2str(status));
 		return;
 	}
 
+	report->notifyid = g_attrib_register(hogdev->attrib,
+					ATT_OP_HANDLE_NOTIFY,
+					report->decl->value_handle,
+					report_value_cb, report, NULL);
+
 	DBG("Report characteristic descriptor written: notifications enabled");
 }
 
 static void write_ccc(uint16_t handle, gpointer user_data)
 {
-	struct hog_device *hogdev = user_data;
+	struct report *report = user_data;
+	struct hog_device *hogdev = report->hogdev;
 	uint8_t value[] = { 0x01, 0x00 };
 
 	gatt_write_char(hogdev->attrib, handle, value, sizeof(value),
-					report_ccc_written_cb, hogdev);
+					report_ccc_written_cb, report);
 }
 
 static void report_reference_cb(guint8 status, const guint8 *pdu,
@@ -196,6 +184,7 @@ static void report_reference_cb(guint8 status, const guint8 *pdu,
 static void external_report_reference_cb(guint8 status, const guint8 *pdu,
 					guint16 plen, gpointer user_data);
 
+
 static void discover_descriptor_cb(guint8 status, const guint8 *pdu,
 					guint16 len, gpointer user_data)
 {
@@ -229,7 +218,7 @@ static void discover_descriptor_cb(guint8 status, const guint8 *pdu,
 		switch (uuid16) {
 		case GATT_CLIENT_CHARAC_CFG_UUID:
 			report = user_data;
-			write_ccc(handle, report->hogdev);
+			write_ccc(handle, report);
 			break;
 		case GATT_REPORT_REFERENCE:
 			report = user_data;
@@ -608,27 +597,37 @@ static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
 {
 	struct hog_device *hogdev = user_data;
 	struct gatt_primary *prim = hogdev->hog_primary;
+	GSList *l;
 
 	hogdev->attrib = g_attrib_ref(attrib);
 
-	hogdev->report_cb_id = g_attrib_register(hogdev->attrib,
-					ATT_OP_HANDLE_NOTIFY,
-					GATTRIB_ALL_HANDLES,
-					report_value_cb, hogdev, NULL);
-
 	if (hogdev->reports == NULL) {
 		gatt_discover_char(hogdev->attrib, prim->range.start,
 						prim->range.end, NULL,
 						char_discovered_cb, hogdev);
+		return;
+	}
+
+	for (l = hogdev->reports; l; l = l->next) {
+		struct report *r = l->data;
+
+		r->notifyid = g_attrib_register(hogdev->attrib,
+					ATT_OP_HANDLE_NOTIFY,
+					r->decl->value_handle,
+					report_value_cb, r, NULL);
 	}
 }
 
 static void attio_disconnected_cb(gpointer user_data)
 {
 	struct hog_device *hogdev = user_data;
+	GSList *l;
+
+	for (l = hogdev->reports; l; l = l->next) {
+		struct report *r = l->data;
 
-	g_attrib_unregister(hogdev->attrib, hogdev->report_cb_id);
-	hogdev->report_cb_id = 0;
+		g_attrib_unregister(hogdev->attrib, r->notifyid);
+	}
 
 	g_attrib_unref(hogdev->attrib);
 	hogdev->attrib = NULL;
@@ -652,6 +651,9 @@ static struct hog_device *hog_device_new(struct btd_device *device,
 static void report_free(void *data)
 {
 	struct report *report = data;
+	struct hog_device *hogdev = report->hogdev;
+
+	g_attrib_unregister(hogdev->attrib, report->notifyid);
 	g_free(report->decl);
 	g_free(report);
 }
-- 
1.7.12.3


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

* [PATCH BlueZ 4/5] heartrate: Use the per handle GATT event notifier
  2012-10-10 23:55 [PATCH BlueZ 1/5] gattrib: Add support for listening for events for specific handles Vinicius Costa Gomes
  2012-10-10 23:55 ` [PATCH BlueZ 2/5] scan: Use the per handle GATT event notifier Vinicius Costa Gomes
  2012-10-10 23:55 ` [PATCH BlueZ 3/5] hog: " Vinicius Costa Gomes
@ 2012-10-10 23:55 ` Vinicius Costa Gomes
  2012-10-10 23:55 ` [PATCH BlueZ 5/5] gas: Add " Vinicius Costa Gomes
  2012-10-11  6:57 ` [PATCH BlueZ 1/5] gattrib: Add support for listening for events for specific handles Johan Hedberg
  4 siblings, 0 replies; 6+ messages in thread
From: Vinicius Costa Gomes @ 2012-10-10 23:55 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Vinicius Costa Gomes

---
 profiles/heartrate/heartrate.c | 287 +++++++++++++++++++++--------------------
 1 file changed, 145 insertions(+), 142 deletions(-)

diff --git a/profiles/heartrate/heartrate.c b/profiles/heartrate/heartrate.c
index d9d6c03..871b74e 100644
--- a/profiles/heartrate/heartrate.c
+++ b/profiles/heartrate/heartrate.c
@@ -260,6 +260,150 @@ static void char_write_cb(guint8 status, const guint8 *pdu, guint16 len,
 	g_free(msg);
 }
 
+static void update_watcher(gpointer data, gpointer user_data)
+{
+	struct watcher *w = data;
+	struct measurement *m = user_data;
+	struct heartrate *hr = m->hr;
+	const gchar *path = device_get_path(hr->dev);
+	DBusMessageIter iter;
+	DBusMessageIter dict;
+	DBusMessage *msg;
+
+	msg = dbus_message_new_method_call(w->srv, w->path,
+			HEART_RATE_WATCHER_INTERFACE, "MeasurementReceived");
+	if (msg == NULL)
+		return;
+
+	dbus_message_iter_init_append(msg, &iter);
+
+	dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH , &path);
+
+	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+			DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+			DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
+			DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
+
+	dict_append_entry(&dict, "Value", DBUS_TYPE_UINT16, &m->value);
+
+	if (m->has_energy)
+		dict_append_entry(&dict, "Energy", DBUS_TYPE_UINT16,
+								&m->energy);
+
+	if (m->has_contact)
+		dict_append_entry(&dict, "Contact", DBUS_TYPE_BOOLEAN,
+								&m->contact);
+
+	if (m->num_interval > 0)
+		dict_append_array(&dict, "Interval", DBUS_TYPE_UINT16,
+						&m->interval, m->num_interval);
+
+	dbus_message_iter_close_container(&iter, &dict);
+
+	dbus_message_set_no_reply(msg, TRUE);
+	g_dbus_send_message(btd_get_dbus_connection(), msg);
+}
+
+static void process_measurement(struct heartrate *hr, const uint8_t *pdu,
+								uint16_t len)
+{
+	struct measurement m;
+	uint8_t flags;
+
+	flags = *pdu;
+
+	pdu++;
+	len--;
+
+	memset(&m, 0, sizeof(m));
+
+	if (flags & HR_VALUE_FORMAT) {
+		if (len < 2) {
+			error("Heart Rate Measurement field missing");
+			return;
+		}
+
+		m.value = att_get_u16(pdu);
+		pdu += 2;
+		len -= 2;
+	} else {
+		if (len < 1) {
+			error("Heart Rate Measurement field missing");
+			return;
+		}
+
+		m.value = *pdu;
+		pdu++;
+		len--;
+	}
+
+	if (flags & ENERGY_EXP_STATUS) {
+		if (len < 2) {
+			error("Energy Expended field missing");
+			return;
+		}
+
+		m.has_energy = TRUE;
+		m.energy = att_get_u16(pdu);
+		pdu += 2;
+		len -= 2;
+	}
+
+	if (flags & RR_INTERVAL) {
+		int i;
+
+		if (len == 0 || (len % 2 != 0)) {
+			error("RR-Interval field malformed");
+			return;
+		}
+
+		m.num_interval = len / 2;
+		m.interval = g_new(uint16_t, m.num_interval);
+
+		for (i = 0; i < m.num_interval; pdu += 2, i++)
+			m.interval[i] = att_get_u16(pdu);
+	}
+
+	if (flags & SENSOR_CONTACT_SUPPORT) {
+		m.has_contact = TRUE;
+		m.contact = !!(flags & SENSOR_CONTACT_DETECTED);
+	}
+
+	/* Notify all registered watchers */
+	m.hr = hr;
+	g_slist_foreach(hr->hradapter->watchers, update_watcher, &m);
+
+	g_free(m.interval);
+}
+
+static void notify_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
+{
+	struct heartrate *hr = user_data;
+
+	/* should be at least opcode (1b) + handle (2b) */
+	if (len < 3) {
+		error("Invalid PDU received");
+		return;
+	}
+
+	process_measurement(hr, pdu + 3, len - 3);
+}
+
+static void ccc_write_cb(guint8 status, const guint8 *pdu, guint16 len,
+							gpointer user_data)
+{
+	struct heartrate *hr = user_data;
+
+	if (status != 0) {
+		error("Enable measurement failed");
+		return;
+	}
+
+	hr->attionotid = g_attrib_register(hr->attrib, ATT_OP_HANDLE_NOTIFY,
+						hr->measurement_val_handle,
+						notify_handler, hr, NULL);
+}
+
 static void discover_ccc_cb(guint8 status, const guint8 *pdu,
 						guint16 len, gpointer user_data)
 {
@@ -291,7 +435,6 @@ static void discover_ccc_cb(guint8 status, const guint8 *pdu,
 
 		if (uuid == GATT_CLIENT_CHARAC_CFG_UUID) {
 			uint8_t value[2];
-			char *msg;
 
 			hr->measurement_ccc_handle = handle;
 
@@ -299,10 +442,9 @@ static void discover_ccc_cb(guint8 status, const guint8 *pdu,
 				break;
 
 			att_put_u16(GATT_CLIENT_CHARAC_CFG_NOTIF_BIT, value);
-			msg = g_strdup("Enable measurement");
 
 			gatt_write_char(hr->attrib, handle, value,
-					sizeof(value), char_write_cb, msg);
+					sizeof(value), ccc_write_cb, hr);
 
 			break;
 		}
@@ -399,142 +541,6 @@ static void disable_measurement(gpointer data, gpointer user_data)
 							char_write_cb, msg);
 }
 
-static void update_watcher(gpointer data, gpointer user_data)
-{
-	struct watcher *w = data;
-	struct measurement *m = user_data;
-	struct heartrate *hr = m->hr;
-	const gchar *path = device_get_path(hr->dev);
-	DBusMessageIter iter;
-	DBusMessageIter dict;
-	DBusMessage *msg;
-
-	msg = dbus_message_new_method_call(w->srv, w->path,
-			HEART_RATE_WATCHER_INTERFACE, "MeasurementReceived");
-	if (msg == NULL)
-		return;
-
-	dbus_message_iter_init_append(msg, &iter);
-
-	dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH , &path);
-
-	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
-			DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
-			DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
-			DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
-
-	dict_append_entry(&dict, "Value", DBUS_TYPE_UINT16, &m->value);
-
-	if (m->has_energy)
-		dict_append_entry(&dict, "Energy", DBUS_TYPE_UINT16,
-								&m->energy);
-
-	if (m->has_contact)
-		dict_append_entry(&dict, "Contact", DBUS_TYPE_BOOLEAN,
-								&m->contact);
-
-	if (m->num_interval > 0)
-		dict_append_array(&dict, "Interval", DBUS_TYPE_UINT16,
-						&m->interval, m->num_interval);
-
-	dbus_message_iter_close_container(&iter, &dict);
-
-	dbus_message_set_no_reply(msg, TRUE);
-	g_dbus_send_message(btd_get_dbus_connection(), msg);
-}
-
-static void process_measurement(struct heartrate *hr, const uint8_t *pdu,
-								uint16_t len)
-{
-	struct measurement m;
-	uint8_t flags;
-
-	flags = *pdu;
-
-	pdu++;
-	len--;
-
-	memset(&m, 0, sizeof(m));
-
-	if (flags & HR_VALUE_FORMAT) {
-		if (len < 2) {
-			error("Heart Rate Measurement field missing");
-			return;
-		}
-
-		m.value = att_get_u16(pdu);
-		pdu += 2;
-		len -= 2;
-	} else {
-		if (len < 1) {
-			error("Heart Rate Measurement field missing");
-			return;
-		}
-
-		m.value = *pdu;
-		pdu++;
-		len--;
-	}
-
-	if (flags & ENERGY_EXP_STATUS) {
-		if (len < 2) {
-			error("Energy Expended field missing");
-			return;
-		}
-
-		m.has_energy = TRUE;
-		m.energy = att_get_u16(pdu);
-		pdu += 2;
-		len -= 2;
-	}
-
-	if (flags & RR_INTERVAL) {
-		int i;
-
-		if (len == 0 || (len % 2 != 0)) {
-			error("RR-Interval field malformed");
-			return;
-		}
-
-		m.num_interval = len / 2;
-		m.interval = g_new(uint16_t, m.num_interval);
-
-		for (i = 0; i < m.num_interval; pdu += 2, i++)
-			m.interval[i] = att_get_u16(pdu);
-	}
-
-	if (flags & SENSOR_CONTACT_SUPPORT) {
-		m.has_contact = TRUE;
-		m.contact = !!(flags & SENSOR_CONTACT_DETECTED);
-	}
-
-	/* Notify all registered watchers */
-	m.hr = hr;
-	g_slist_foreach(hr->hradapter->watchers, update_watcher, &m);
-
-	g_free(m.interval);
-}
-
-static void notify_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
-{
-	struct heartrate *hr = user_data;
-	uint16_t handle;
-
-	/* should be at least opcode (1b) + handle (2b) */
-	if (len < 3) {
-		error("Invalid PDU received");
-		return;
-	}
-
-	handle = att_get_u16(pdu + 1);
-	if (handle != hr->measurement_val_handle) {
-		error("Unexpected handle: 0x%04x", handle);
-		return;
-	}
-
-	process_measurement(hr, pdu + 3, len - 3);
-}
-
 static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
 {
 	struct heartrate *hr = user_data;
@@ -543,9 +549,6 @@ static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
 
 	hr->attrib = g_attrib_ref(attrib);
 
-	hr->attionotid = g_attrib_register(hr->attrib, ATT_OP_HANDLE_NOTIFY,
-				GATTRIB_ALL_HANDLES, notify_handler, hr, NULL);
-
 	gatt_discover_char(hr->attrib, hr->svc_range->start, hr->svc_range->end,
 						NULL, discover_char_cb, hr);
 }
-- 
1.7.12.3


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

* [PATCH BlueZ 5/5] gas: Add the per handle GATT event notifier
  2012-10-10 23:55 [PATCH BlueZ 1/5] gattrib: Add support for listening for events for specific handles Vinicius Costa Gomes
                   ` (2 preceding siblings ...)
  2012-10-10 23:55 ` [PATCH BlueZ 4/5] heartrate: " Vinicius Costa Gomes
@ 2012-10-10 23:55 ` Vinicius Costa Gomes
  2012-10-11  6:57 ` [PATCH BlueZ 1/5] gattrib: Add support for listening for events for specific handles Johan Hedberg
  4 siblings, 0 replies; 6+ messages in thread
From: Vinicius Costa Gomes @ 2012-10-10 23:55 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Vinicius Costa Gomes

---
 profiles/gatt/gas.c | 72 +++++++++++++++++++++++++----------------------------
 1 file changed, 34 insertions(+), 38 deletions(-)

diff --git a/profiles/gatt/gas.c b/profiles/gatt/gas.c
index bb626e7..793a3af 100644
--- a/profiles/gatt/gas.c
+++ b/profiles/gatt/gas.c
@@ -166,39 +166,10 @@ done:
 	att_data_list_free(list);
 }
 
-static void ccc_written_cb(guint8 status, const guint8 *pdu, guint16 plen,
-							gpointer user_data)
-{
-	struct gas *gas = user_data;
-
-	if (status) {
-		error("Write Service Changed CCC failed: %s",
-						att_ecode2str(status));
-		return;
-	}
-
-	DBG("Service Changed indications enabled");
-
-	write_ctp_handle(adapter_get_address(device_get_adapter(gas->device)),
-					device_get_address(gas->device),
-					device_get_addr_type(gas->device),
-					GATT_CHARAC_SERVICE_CHANGED,
-					gas->changed_handle);
-}
-
-static void write_ccc(GAttrib *attrib, uint16_t handle, gpointer user_data)
-{
-	uint8_t value[2];
-
-	att_put_u16(GATT_CLIENT_CHARAC_CFG_IND_BIT, value);
-	gatt_write_char(attrib, handle, value, sizeof(value), ccc_written_cb,
-								user_data);
-}
-
 static void indication_cb(const uint8_t *pdu, uint16_t len, gpointer user_data)
 {
 	struct gas *gas = user_data;
-	uint16_t handle, start, end, olen;
+	uint16_t start, end, olen;
 	size_t plen;
 	uint8_t *opdu;
 
@@ -207,13 +178,9 @@ static void indication_cb(const uint8_t *pdu, uint16_t len, gpointer user_data)
 		return;
 	}
 
-	handle = att_get_u16(&pdu[1]);
 	start = att_get_u16(&pdu[3]);
 	end = att_get_u16(&pdu[5]);
 
-	if (handle != gas->changed_handle)
-		return;
-
 	DBG("Service Changed start: 0x%04X end: 0x%04X", start, end);
 
 	if (device_is_bonded(gas->device) == FALSE) {
@@ -229,6 +196,39 @@ static void indication_cb(const uint8_t *pdu, uint16_t len, gpointer user_data)
 	btd_device_gatt_set_service_changed(gas->device, start, end);
 }
 
+static void ccc_written_cb(guint8 status, const guint8 *pdu, guint16 plen,
+							gpointer user_data)
+{
+	struct gas *gas = user_data;
+
+	if (status) {
+		error("Write Service Changed CCC failed: %s",
+						att_ecode2str(status));
+		return;
+	}
+
+	DBG("Service Changed indications enabled");
+
+	gas->changed_ind = g_attrib_register(gas->attrib, ATT_OP_HANDLE_IND,
+						gas->changed_handle,
+						indication_cb, gas, NULL);
+
+	write_ctp_handle(adapter_get_address(device_get_adapter(gas->device)),
+					device_get_address(gas->device),
+					device_get_addr_type(gas->device),
+					GATT_CHARAC_SERVICE_CHANGED,
+					gas->changed_handle);
+}
+
+static void write_ccc(GAttrib *attrib, uint16_t handle, gpointer user_data)
+{
+	uint8_t value[2];
+
+	att_put_u16(GATT_CLIENT_CHARAC_CFG_IND_BIT, value);
+	gatt_write_char(attrib, handle, value, sizeof(value), ccc_written_cb,
+								user_data);
+}
+
 static void gatt_descriptors_cb(guint8 status, const guint8 *pdu, guint16 len,
 							gpointer user_data)
 {
@@ -333,10 +333,6 @@ static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
 		DBG("MTU Exchange: Requesting %d", imtu);
 	}
 
-	gas->changed_ind = g_attrib_register(gas->attrib, ATT_OP_HANDLE_IND,
-						GATTRIB_ALL_HANDLES,
-						indication_cb, gas, NULL);
-
 	if (device_get_appearance(gas->device, &app) < 0) {
 		bt_uuid_t uuid;
 
-- 
1.7.12.3


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

* Re: [PATCH BlueZ 1/5] gattrib: Add support for listening for events for specific handles
  2012-10-10 23:55 [PATCH BlueZ 1/5] gattrib: Add support for listening for events for specific handles Vinicius Costa Gomes
                   ` (3 preceding siblings ...)
  2012-10-10 23:55 ` [PATCH BlueZ 5/5] gas: Add " Vinicius Costa Gomes
@ 2012-10-11  6:57 ` Johan Hedberg
  4 siblings, 0 replies; 6+ messages in thread
From: Johan Hedberg @ 2012-10-11  6:57 UTC (permalink / raw)
  To: Vinicius Costa Gomes; +Cc: linux-bluetooth

Hi Vinicius,

On Wed, Oct 10, 2012, Vinicius Costa Gomes wrote:
> We want only the profile that implements a service to be notified of
> changes on that service. Before this patch, all the registered event
> notifiers are being called.
> ---
> Hi,
> 
> I am re-sending this series because, if it makes sense, it would be awesome
> if it gets the "UPF treatment".
> 
> Cheers,
> 
> 
>  attrib/client.c                    |  4 ++--
>  attrib/gattrib.c                   | 33 ++++++++++++++++++++++++++++-----
>  attrib/gattrib.h                   |  7 ++++---
>  attrib/gatttool.c                  |  8 ++++----
>  attrib/interactive.c               |  8 ++++----
>  profiles/gatt/gas.c                |  1 +
>  profiles/heartrate/heartrate.c     |  2 +-
>  profiles/input/hog_device.c        |  5 +++--
>  profiles/scanparam/scan.c          |  4 ++--
>  profiles/thermometer/thermometer.c |  2 ++
>  src/attrib-server.c                |  2 +-
>  11 files changed, 52 insertions(+), 24 deletions(-)

I went and applied this set too as it looks good. Thanks.

Johan

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

end of thread, other threads:[~2012-10-11  6:57 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-10-10 23:55 [PATCH BlueZ 1/5] gattrib: Add support for listening for events for specific handles Vinicius Costa Gomes
2012-10-10 23:55 ` [PATCH BlueZ 2/5] scan: Use the per handle GATT event notifier Vinicius Costa Gomes
2012-10-10 23:55 ` [PATCH BlueZ 3/5] hog: " Vinicius Costa Gomes
2012-10-10 23:55 ` [PATCH BlueZ 4/5] heartrate: " Vinicius Costa Gomes
2012-10-10 23:55 ` [PATCH BlueZ 5/5] gas: Add " Vinicius Costa Gomes
2012-10-11  6:57 ` [PATCH BlueZ 1/5] gattrib: Add support for listening for events for specific handles Johan Hedberg

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).