gattrib: Add support for listening for events for specific handles

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.
This commit is contained in:
Vinicius Costa Gomes 2012-10-10 20:55:53 -03:00 committed by Johan Hedberg
parent 9b8871db95
commit 0f92869a3b
11 changed files with 52 additions and 24 deletions

View File

@ -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);

View File

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

View File

@ -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);

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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) {

View File

@ -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);

View File

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

View File

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

View File

@ -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);

View File

@ -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);