static void read_char_helper(guint8 status, const guint8 *rpdu, guint16 rlen, gpointer user_data) { struct read_long_data *long_read = user_data; size_t buflen; uint8_t *buf = g_attrib_get_buffer(long_read->attrib, &buflen); guint16 plen; guint id; if (status != 0 || rlen < buflen) goto done; long_read->buffer = g_malloc(rlen); if (long_read->buffer == NULL) { status = ATT_ECODE_INSUFF_RESOURCES; goto done; } memcpy(long_read->buffer, rpdu, rlen); long_read->size = rlen; plen = enc_read_blob_req(long_read->handle, rlen - 1, buf, buflen); id = g_attrib_send(long_read->attrib, long_read->id, buf, plen, read_blob_helper, long_read, read_long_destroy); if (id != 0) { __sync_fetch_and_add(&long_read->ref, 1); return; } status = ATT_ECODE_IO; done: long_read->func(status, rpdu, rlen, long_read->user_data); }
static void read_char_helper(guint8 status, const guint8 *rpdu, guint16 rlen, gpointer user_data) { struct read_long_data *long_read = user_data; int buflen; uint8_t *buf = g_attrib_get_buffer(long_read->attrib, &buflen); guint16 plen; guint id; if (status != 0 || rlen < buflen) goto done; long_read->buffer = g_malloc(rlen); if (long_read->buffer == NULL) goto done; memcpy(long_read->buffer, rpdu, rlen); long_read->size = rlen; plen = enc_read_blob_req(long_read->handle, rlen - 1, buf, buflen); id = g_attrib_send(long_read->attrib, long_read->id, ATT_OP_READ_BLOB_REQ, buf, plen, read_blob_helper, long_read, read_long_destroy); if (id != 0) { g_atomic_int_inc(&long_read->ref); return; } status = ATT_ECODE_IO; done: long_read->func(status, rpdu, rlen, long_read->user_data); }
static void read_blob_helper(guint8 status, const guint8 *rpdu, guint16 rlen, gpointer user_data) { struct read_long_data *long_read = user_data; uint8_t *buf; int buflen; guint8 *tmp; guint16 plen; guint id; if (status != 0 || rlen == 1) { status = 0; goto done; } tmp = g_try_realloc(long_read->buffer, long_read->size + rlen - 1); if (tmp == NULL) { status = ATT_ECODE_INSUFF_RESOURCES; goto done; } memcpy(&tmp[long_read->size], &rpdu[1], rlen - 1); long_read->buffer = tmp; long_read->size += rlen - 1; buf = g_attrib_get_buffer(long_read->attrib, &buflen); if (rlen < buflen) goto done; plen = enc_read_blob_req(long_read->handle, long_read->size - 1, buf, buflen); id = g_attrib_send(long_read->attrib, long_read->id, ATT_OP_READ_BLOB_REQ, buf, plen, read_blob_helper, long_read, read_long_destroy); if (id != 0) { g_atomic_int_inc(&long_read->ref); return; } status = ATT_ECODE_IO; done: long_read->func(status, long_read->buffer, long_read->size, long_read->user_data); }
guint gatt_read_char(GAttrib *attrib, uint16_t handle, uint16_t offset, GAttribResultFunc func, gpointer user_data) { uint8_t *buf; int buflen; guint16 plen; guint id; struct read_long_data *long_read; long_read = g_try_new0(struct read_long_data, 1); if (long_read == NULL) return 0; long_read->attrib = attrib; long_read->func = func; long_read->user_data = user_data; long_read->handle = handle; buf = g_attrib_get_buffer(attrib, &buflen); if (offset > 0) { plen = enc_read_blob_req(long_read->handle, offset, buf, buflen); id = g_attrib_send(attrib, 0, ATT_OP_READ_BLOB_REQ, buf, plen, read_blob_helper, long_read, read_long_destroy); } else { plen = enc_read_req(handle, buf, buflen); id = g_attrib_send(attrib, 0, ATT_OP_READ_REQ, buf, plen, read_char_helper, long_read, read_long_destroy); } if (id == 0) g_free(long_read); else { g_atomic_int_inc(&long_read->ref); long_read->id = id; } return id; }
guint gatt_read_char_single(GAttrib *attrib, uint16_t handle, uint16_t offset, GAttribResultFunc func, gpointer user_data) { uint8_t *buf; size_t buflen; guint16 plen; guint id; struct read_data *read; read = g_try_new0(struct read_data, 1); if (read == NULL) return 0; read->attrib = g_attrib_ref(attrib); read->func = func; read->user_data = user_data; read->handle = handle; read->offset = offset; buf = g_attrib_get_buffer(attrib, &buflen); if (!offset) plen = enc_read_req(handle, buf, buflen); else plen = enc_read_blob_req(handle, offset, buf, buflen); id = g_attrib_send(attrib, 0, buf, plen, read_char_helper, read, read_destroy); if (id == 0) { g_attrib_unref(read->attrib); g_free(read); } else { __sync_fetch_and_add(&read->ref, 1); read->id = id; } return id; }