summaryrefslogtreecommitdiff
path: root/attrib
diff options
context:
space:
mode:
authorLukasz Rymanowski <lukasz.rymanowski@tieto.com>2014-12-18 14:46:07 +0100
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2014-12-18 22:03:34 -0200
commitacc2f8ebbd6ce58586b365a39c2b437034f068e2 (patch)
tree36502cbfe555555ed5088a3ee9b60c013aff3e1e /attrib
parente5a4abf420b3ddca17c72d7f86a460bae7b112d9 (diff)
downloadbluez-acc2f8ebbd6ce58586b365a39c2b437034f068e2.tar.gz
attrib/gattrib: Add tracking all the internal request id
With this patch gattrib track all the pending request id's to bt_att. When doing g_attrib_cancel_all, only those own by gattrib will be canceled.
Diffstat (limited to 'attrib')
-rw-r--r--attrib/gattrib.c96
1 files changed, 43 insertions, 53 deletions
diff --git a/attrib/gattrib.c b/attrib/gattrib.c
index f986a775c..2fd06e6df 100644
--- a/attrib/gattrib.c
+++ b/attrib/gattrib.c
@@ -54,9 +54,13 @@ struct _GAttrib {
struct queue *track_ids;
};
+struct id_pair {
+ unsigned int org_id;
+ unsigned int pend_id;
+};
struct attrib_callbacks {
- unsigned int id;
+ struct id_pair *id;
GAttribResultFunc result_func;
GAttribNotifyFunc notify_func;
GDestroyNotify destroy_func;
@@ -65,20 +69,6 @@ struct attrib_callbacks {
uint16_t notify_handle;
};
-struct id_pair {
- unsigned int org_id;
- unsigned int pend_id;
-};
-
-
-static bool find_with_pend_id(const void *data, const void *user_data)
-{
- const struct id_pair *p = data;
- unsigned int pending = PTR_TO_UINT(user_data);
-
- return (p->pend_id == pending);
-}
-
static bool find_with_org_id(const void *data, const void *user_data)
{
const struct id_pair *p = data;
@@ -87,37 +77,22 @@ static bool find_with_org_id(const void *data, const void *user_data)
return (p->org_id == orig_id);
}
-static void remove_stored_ids(GAttrib *attrib, unsigned int pending_id)
-{
- struct id_pair *p;
-
- p = queue_remove_if(attrib->track_ids, find_with_pend_id,
- UINT_TO_PTR(pending_id));
-
- free(p);
-}
-
-static void store_id(GAttrib *attrib, unsigned int org_id,
+static struct id_pair *store_id(GAttrib *attrib, unsigned int org_id,
unsigned int pend_id)
{
struct id_pair *t;
- t = queue_find(attrib->track_ids, find_with_org_id,
- UINT_TO_PTR(org_id));
- if (t) {
- t->pend_id = pend_id;
- return;
- }
-
t = new0(struct id_pair, 1);
if (!t)
- return;
+ return NULL;
t->org_id = org_id;
t->pend_id = pend_id;
- if (!queue_push_tail(attrib->track_ids, t))
- free(t);
+ if (queue_push_tail(attrib->track_ids, t))
+ return t;
+
+ return NULL;
}
GAttrib *g_attrib_new(GIOChannel *io, guint16 mtu)
@@ -185,6 +160,9 @@ static void attrib_callbacks_destroy(void *data)
if (cb->destroy_func)
cb->destroy_func(cb->user_data);
+ if (queue_remove(cb->parent->track_ids, cb->id))
+ free(cb->id);
+
free(data);
}
@@ -291,8 +269,6 @@ static void attrib_callback_result(uint8_t opcode, const void *pdu,
if (cb->result_func)
cb->result_func(status, buf, length + 1, cb->user_data);
- remove_stored_ids(cb->parent, cb->id);
-
free(buf);
}
@@ -328,6 +304,7 @@ guint g_attrib_send(GAttrib *attrib, guint id, const guint8 *pdu, guint16 len,
struct attrib_callbacks *cb = NULL;
bt_att_response_func_t response_cb = NULL;
bt_att_destroy_func_t destroy_cb = NULL;
+ unsigned int pend_id;
if (!attrib)
return 0;
@@ -349,32 +326,36 @@ guint g_attrib_send(GAttrib *attrib, guint id, const guint8 *pdu, guint16 len,
}
- cb->id = bt_att_send(attrib->att, pdu[0], (void *) pdu + 1, len - 1,
+ pend_id = bt_att_send(attrib->att, pdu[0], (void *) pdu + 1, len - 1,
response_cb, cb, destroy_cb);
+ /*
+ * We store here pair as it is easier to handle it in response and in
+ * case where user request us to use specific id request - see below.
+ */
if (id == 0)
- return cb->id;
+ id = pend_id;
/*
* If user what us to use given id, lets keep track on that so we give
* user a possibility to cancel ongoing request.
*/
- store_id(attrib, id, cb->id);
+ if (cb)
+ cb->id = store_id(attrib, id, pend_id);
+
return id;
}
gboolean g_attrib_cancel(GAttrib *attrib, guint id)
{
struct id_pair *p;
- unsigned int pend_id;
if (!attrib)
return FALSE;
/*
- * Let's try to find actual pending request id on the tracking id queue.
- * If there is no such it means it is not tracked id and we can cancel
- * it.
+ * If request belongs to gattrib and is not yet done it has to be on
+ * the tracking id queue
*
* FIXME: It can happen that on the queue there is id_pair with
* given id which was provided by the user. In the same time it might
@@ -386,14 +367,21 @@ gboolean g_attrib_cancel(GAttrib *attrib, guint id)
*/
p = queue_remove_if(attrib->track_ids, find_with_org_id,
UINT_TO_PTR(id));
- if (p) {
- pend_id = p->pend_id;
- free(p);
- } else {
- pend_id = id;
- }
+ if (!p)
+ return FALSE;
+
+ id = p->pend_id;
+ free(p);
- return bt_att_cancel(attrib->att, pend_id);
+ return bt_att_cancel(attrib->att, id);
+}
+
+static void cancel_request(void *data, void *user_data)
+{
+ struct id_pair *p = data;
+ GAttrib *attrib = user_data;
+
+ bt_att_cancel(attrib->att, p->pend_id);
}
gboolean g_attrib_cancel_all(GAttrib *attrib)
@@ -401,9 +389,11 @@ gboolean g_attrib_cancel_all(GAttrib *attrib)
if (!attrib)
return FALSE;
+ /* Cancel only request which belongs to gattrib */
+ queue_foreach(attrib->track_ids, cancel_request, attrib);
queue_remove_all(attrib->track_ids, NULL, NULL, free);
- return bt_att_cancel_all(attrib->att);
+ return TRUE;
}
guint g_attrib_register(GAttrib *attrib, guint8 opcode, guint16 handle,