guint g_attrib_send(GAttrib *attrib, guint id, guint8 opcode, const guint8 *pdu, guint16 len, GAttribResultFunc func, gpointer user_data, GDestroyNotify notify) { struct command *c; c = g_try_new0(struct command, 1); if (c == NULL) return 0; c->opcode = opcode; c->expected = opcode2expected(opcode); c->pdu = g_malloc(len); memcpy(c->pdu, pdu, len); c->len = len; c->func = func; c->user_data = user_data; c->notify = notify; if (id) { c->id = id; g_queue_push_head(attrib->queue, c); } else { c->id = ++attrib->next_cmd_id; g_queue_push_tail(attrib->queue, c); } if (g_queue_get_length(attrib->queue) == 1) wake_up_sender(attrib); return c->id; }
guint g_attrib_send(GAttrib *attrib, guint id, const guint8 *pdu, guint16 len, GAttribResultFunc func, gpointer user_data, GDestroyNotify notify) { struct command *c; GQueue *queue; uint8_t opcode; if (attrib->stale) return 0; c = g_try_new0(struct command, 1); if (c == NULL) return 0; opcode = pdu[0]; c->opcode = opcode; c->expected = opcode2expected(opcode); c->pdu = g_malloc(len); memcpy(c->pdu, pdu, len); c->len = len; c->func = func; c->user_data = user_data; c->notify = notify; if (is_response(opcode)) queue = attrib->responses; else queue = attrib->requests; if (id) { c->id = id; if (!is_response(opcode)) g_queue_push_head(queue, c); else /* Don't re-order responses even if an ID is given */ g_queue_push_tail(queue, c); } else { c->id = ++attrib->next_cmd_id; g_queue_push_tail(queue, c); } /* * If a command was added to the queue and it was empty before, wake up * the sender. If the sender was already woken up by the second queue, * wake_up_sender will just return. */ if (g_queue_get_length(queue) == 1) wake_up_sender(attrib); return c->id; }
static gboolean received_data(GIOChannel *io, GIOCondition cond, gpointer data) { struct _GAttrib *attrib = data; struct command *cmd = NULL; GSList *l; uint8_t buf[512], status; gsize len; GIOStatus iostat; gboolean qempty; if (attrib->timeout_watch > 0) { g_source_remove(attrib->timeout_watch); attrib->timeout_watch = 0; } if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) { attrib->read_watch = 0; return FALSE; } memset(buf, 0, sizeof(buf)); iostat = g_io_channel_read_chars(io, (gchar *) buf, sizeof(buf), &len, NULL); if (iostat != G_IO_STATUS_NORMAL) { status = ATT_ECODE_IO; goto done; } 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)) evt->func(buf, len, evt->user_data); } if (is_response(buf[0]) == FALSE) return TRUE; cmd = g_queue_pop_head(attrib->queue); if (cmd == NULL) { /* Keep the watch if we have events to report */ return attrib->events != NULL; } if (buf[0] == ATT_OP_ERROR) { status = buf[4]; goto done; } if (cmd->expected != buf[0]) { status = ATT_ECODE_IO; goto done; } status = 0; done: qempty = attrib->queue == NULL || g_queue_is_empty(attrib->queue); if (cmd) { if (cmd->func) cmd->func(status, buf, len, cmd->user_data); command_destroy(cmd); } if (!qempty) wake_up_sender(attrib); return TRUE; }
static gboolean received_data(GIOChannel *io, GIOCondition cond, gpointer data) { struct _GAttrib *attrib = data; struct command *cmd = NULL; GSList *l; uint8_t buf[512], status; gsize len; GIOStatus iostat; if (attrib->stale) return FALSE; if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) { struct command *c; while ((c = g_queue_pop_head(attrib->requests))) { if (c->func) c->func(ATT_ECODE_IO, NULL, 0, c->user_data); command_destroy(c); } attrib->read_watch = 0; return FALSE; } memset(buf, 0, sizeof(buf)); iostat = g_io_channel_read_chars(io, (char *) buf, sizeof(buf), &len, NULL); if (iostat != G_IO_STATUS_NORMAL) { status = ATT_ECODE_IO; goto done; } for (l = attrib->events; l; l = l->next) { struct event *evt = l->data; if (match_event(evt, buf, len)) evt->func(buf, len, evt->user_data); } if (!is_response(buf[0])) return TRUE; if (attrib->timeout_watch > 0) { g_source_remove(attrib->timeout_watch); attrib->timeout_watch = 0; } cmd = g_queue_pop_head(attrib->requests); if (cmd == NULL) { /* Keep the watch if we have events to report */ return attrib->events != NULL; } if (buf[0] == ATT_OP_ERROR) { status = buf[4]; goto done; } if (cmd->expected != buf[0]) { status = ATT_ECODE_IO; goto done; } status = 0; done: if (!g_queue_is_empty(attrib->requests) || !g_queue_is_empty(attrib->responses)) wake_up_sender(attrib); if (cmd) { if (cmd->func) cmd->func(status, buf, len, cmd->user_data); command_destroy(cmd); } return TRUE; }