* [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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.