static void find_included_cb(uint8_t status, const uint8_t *pdu, uint16_t len, gpointer user_data) { struct included_discovery *isd = user_data; uint16_t last_handle = isd->end_handle; unsigned int err = status; struct att_data_list *list; int i; if (err == ATT_ECODE_ATTR_NOT_FOUND) err = 0; if (status) goto done; list = dec_read_by_type_resp(pdu, len); if (list == NULL) { err = ATT_ECODE_IO; goto done; } if (list->len != 6 && list->len != 8) { err = ATT_ECODE_IO; att_data_list_free(list); goto done; } for (i = 0; i < list->num; i++) { struct gatt_included *incl; incl = included_from_buf(list->data[i], list->len); last_handle = incl->handle; /* 128 bit UUID, needs resolving */ if (list->len == 6) { resolve_included_uuid(isd, incl); continue; } isd->includes = g_slist_append(isd->includes, incl); } att_data_list_free(list); if (last_handle < isd->end_handle) find_included(isd, last_handle + 1); done: if (isd->err == 0) isd->err = err; isd_unref(isd); }
static void char_read_by_uuid_cb(guint8 status, const guint8 *pdu, guint16 plen, gpointer user_data) { struct att_data_list *list; int i; GString *s; if (status != 0) { error("Read characteristics by UUID failed: %s\n", att_ecode2str(status)); return; } list = dec_read_by_type_resp(pdu, plen); if (list == NULL) return; s = g_string_new(NULL); for (i = 0; i < list->num; i++) { uint8_t *value = list->data[i]; int j; g_string_printf(s, "handle: 0x%04x \t value: ", get_le16(value)); value += 2; for (j = 0; j < list->len - 2; j++, value++) g_string_append_printf(s, "%02x ", *value); rl_printf("%s\n", s->str); } att_data_list_free(list); g_string_free(s, TRUE); }
static void char_read_by_uuid_cb(guint8 status, const guint8 *pdu, guint16 plen, gpointer user_data) { struct att_data_list *list; int i; if (status != 0) { g_printerr("Read characteristics by UUID failed: %s\n", att_ecode2str(status)); goto done; } list = dec_read_by_type_resp(pdu, plen); if (list == NULL) goto done; for (i = 0; i < list->num; i++) { uint8_t *value = list->data[i]; int j; g_print("handle: 0x%04x \t value: ", get_le16(value)); value += 2; for (j = 0; j < list->len - 2; j++, value++) g_print("%02x ", *value); g_print("\n"); } att_data_list_free(list); done: g_main_loop_quit(event_loop); }
static void discover_descriptor_cb(guint8 status, const guint8 *pdu, guint16 len, gpointer user_data) { struct scan *scan = user_data; struct att_data_list *list; uint8_t *ptr; uint16_t uuid16, handle; uint8_t value[2]; uint8_t format; list = dec_find_info_resp(pdu, len, &format); if (list == NULL) return; if (format != ATT_FIND_INFO_RESP_FMT_16BIT) goto done; ptr = list->data[0]; handle = get_le16(ptr); uuid16 = get_le16(&ptr[2]); if (uuid16 != GATT_CLIENT_CHARAC_CFG_UUID) goto done; put_le16(GATT_CLIENT_CHARAC_CFG_NOTIF_BIT, value); gatt_write_char(scan->attrib, handle, value, sizeof(value), ccc_written_cb, user_data); done: att_data_list_free(list); }
void read_by_uuid_cb(guint8 status, const guint8 *pdu, guint16 plen, gpointer user_data) { struct att_data_list *list; GSList *bl_value_list = NULL; cb_ctx_t *cb_ctx = user_data; printf_dbg("[CB] IN read_by_uuid_cb\n"); if (status) { cb_ctx->cb_ret_val = BL_REQUEST_FAIL_ERROR; sprintf(cb_ctx->cb_ret_msg, "Read by uuid callback: Failure: %s\n", att_ecode2str(status)); goto error; } list = dec_read_by_type_resp(pdu, plen); if (list == NULL) { strcpy(cb_ctx->cb_ret_msg, "Read by uuid callback: Nothing found\n"); cb_ctx->cb_ret_val = BL_NO_ERROR; goto error; } for (int i = 0; i < list->num; i++) { bl_value_t *bl_value = bl_value_new(NULL, att_get_u16(list->data[i]), list->len - 2, list->data[i] + 2); if (bl_value == NULL) { cb_ctx->cb_ret_val = BL_MALLOC_ERROR; strcpy(cb_ctx->cb_ret_msg, "Read by uuid callback: Malloc error\n"); goto error; } // Add it to the value list if (bl_value_list == NULL) { bl_value_list = g_slist_alloc(); if (bl_value_list == NULL) { cb_ctx->cb_ret_val = BL_MALLOC_ERROR; strcpy(cb_ctx->cb_ret_msg, "Read by uuid callback: Malloc error\n"); goto error; } bl_value_list->data = bl_value; } else { bl_value_list = g_slist_append(bl_value_list, bl_value); } } att_data_list_free(list); cb_ctx->cb_ret_pointer = bl_value_list; cb_ctx->cb_ret_val = BL_NO_ERROR; goto exit; error: if (bl_value_list) bl_value_list_free(bl_value_list); exit: g_mutex_unlock(&cb_ctx->pending_cb_mtx); printf_dbg("[CB] OUT read_by_uuid_cb\n"); }
static void discover_ccc_cb(guint8 status, const guint8 *pdu, guint16 len, gpointer user_data) { struct heartrate *hr = user_data; struct att_data_list *list; uint8_t format; int i; if (status != 0) { error("Discover Heart Rate Measurement descriptors failed: %s", att_ecode2str(status)); return; } list = dec_find_info_resp(pdu, len, &format); if (list == NULL) return; if (format != ATT_FIND_INFO_RESP_FMT_16BIT) goto done; for (i = 0; i < list->num; i++) { uint8_t *value; uint16_t handle, uuid; char *msg; uint8_t attr_val[2]; value = list->data[i]; handle = att_get_u16(value); uuid = att_get_u16(value + 2); if (uuid != GATT_CLIENT_CHARAC_CFG_UUID) continue; hr->measurement_ccc_handle = handle; if (g_slist_length(hr->hradapter->watchers) == 0) { att_put_u16(0x0000, attr_val); msg = g_strdup("Disable measurement"); } else { att_put_u16(GATT_CLIENT_CHARAC_CFG_NOTIF_BIT, attr_val); msg = g_strdup("Enable measurement"); } gatt_write_char(hr->attrib, handle, attr_val, sizeof(attr_val), char_write_cb, msg); break; } done: att_data_list_free(list); }
static void discover_descriptor_cb(guint8 status, const guint8 *pdu, guint16 len, gpointer user_data) { struct report *report; struct hog_device *hogdev; struct att_data_list *list; uint8_t format; int i; if (status != 0) { error("Discover all characteristic descriptors failed: %s", att_ecode2str(status)); return; } list = dec_find_info_resp(pdu, len, &format); if (list == NULL) return; if (format != ATT_FIND_INFO_RESP_FMT_16BIT) goto done; for (i = 0; i < list->num; i++) { uint16_t uuid16, handle; uint8_t *value; value = list->data[i]; handle = att_get_u16(value); uuid16 = att_get_u16(&value[2]); switch (uuid16) { case GATT_CLIENT_CHARAC_CFG_UUID: report = user_data; write_ccc(handle, report->hogdev); break; case GATT_REPORT_REFERENCE: report = user_data; gatt_read_char(report->hogdev->attrib, handle, report_reference_cb, report); break; case GATT_EXTERNAL_REPORT_REFERENCE: hogdev = user_data; gatt_read_char(hogdev->attrib, handle, external_report_reference_cb, hogdev); break; } } done: att_data_list_free(list); }
static void char_desc_cb(guint8 status, const guint8 *pdu, guint16 plen, gpointer user_data) { struct att_data_list *list; guint8 format; int i; if (status != 0) { g_printerr("Discover all characteristic descriptors failed: " "%s\n", att_ecode2str(status)); goto done; } list = dec_find_info_resp(pdu, plen, &format); if (list == NULL) goto done; for (i = 0; i < list->num; i++) { char uuidstr[MAX_LEN_UUID_STR]; uint16_t handle; uint8_t *value; bt_uuid_t uuid; value = list->data[i]; handle = get_le16(value); if (format == ATT_FIND_INFO_RESP_FMT_16BIT) bt_uuid16_create(&uuid, get_le16(&value[2])); else { uint128_t u128; /* Converts from LE to BE byte order */ bswap_128(&value[2], &u128); bt_uuid128_create(&uuid, u128); } bt_uuid_to_string(&uuid, uuidstr, MAX_LEN_UUID_STR); g_print("handle = 0x%04x, uuid = %s\n", handle, uuidstr); } att_data_list_free(list); done: if (!opt_listen) g_main_loop_quit(event_loop); }
static void char_read_by_uuid_cb(guint8 status, const guint8 *pdu, guint16 plen, gpointer user_data) { struct characteristic_data *char_data = user_data; struct att_data_list *list; int i; if (status == ATT_ECODE_ATTR_NOT_FOUND && char_data->start != opt_start) goto done; if (status != 0) { g_printerr("Read characteristics by UUID failed: %s\n", att_ecode2str(status)); goto done; } list = dec_read_by_type_resp(pdu, plen); if (list == NULL) goto done; for (i = 0; i < list->num; i++) { uint8_t *value = list->data[i]; int j; char_data->start = att_get_u16(value) + 1; g_print("handle: 0x%04x \t value: ", att_get_u16(value)); value += 2; for (j = 0; j < list->len - 2; j++, value++) g_print("%02x ", *value); g_print("\n"); } att_data_list_free(list); gatt_read_char_by_uuid(char_data->attrib, char_data->start, char_data->end, opt_uuid, char_read_by_uuid_cb, char_data); return; done: g_free(char_data); g_main_loop_quit(event_loop); }
static void char_desc_cb(guint8 status, const guint8 *pdu, guint16 plen, gpointer user_data) { struct att_data_list *list; guint8 format; uint16_t handle = 0xffff; int i; if (status != 0) { resp_error(err_COMM_ERR); // Todo: status return; } list = dec_find_info_resp(pdu, plen, &format); if (list == NULL) { resp_error(err_NOT_FOUND); // Todo: what does this mean? return; } resp_begin(rsp_DESCRIPTORS); for (i = 0; i < list->num; i++) { char uuidstr[MAX_LEN_UUID_STR]; uint8_t *value; bt_uuid_t uuid; value = list->data[i]; handle = att_get_u16(value); if (format == 0x01) uuid = att_get_uuid16(&value[2]); else uuid = att_get_uuid128(&value[2]); bt_uuid_to_string(&uuid, uuidstr, MAX_LEN_UUID_STR); send_uint(tag_HANDLE, handle); send_str (tag_UUID, uuidstr); } resp_end(); att_data_list_free(list); if (handle != 0xffff && handle < end) gatt_discover_char_desc(attrib, handle + 1, end, char_desc_cb, NULL); }
static void gattlib_result_read_uuid_cb(guint8 status, const guint8 *pdu, guint16 len, gpointer user_data) { struct gattlib_result_read_uuid_t* gattlib_result = user_data; struct att_data_list *list; int i; if (status == ATT_ECODE_ATTR_NOT_FOUND) { goto done; } if (status != 0) { fprintf(stderr, "Read characteristics by UUID failed: %s\n", att_ecode2str(status)); goto done; } list = dec_read_by_type_resp(pdu, len); if (list == NULL) { goto done; } for (i = 0; i < list->num; i++) { uint8_t *value = list->data[i]; int j; value += 2; gattlib_result->buffer_len = list->len - 2; if (gattlib_result->callback) { gattlib_result->callback(value, gattlib_result->buffer_len); } else { memcpy(gattlib_result->buffer, value, MIN(gattlib_result->buffer_len, gattlib_result->buffer_max_len)); } } att_data_list_free(list); done: if (gattlib_result->callback) { free(gattlib_result); } else { gattlib_result->completed = TRUE; } }
static void char_read_by_uuid_cb(guint8 status, const guint8 *pdu, guint16 plen, gpointer user_data) { struct characteristic_data *char_data = user_data; struct att_data_list *list; int i; if (status == ATT_ECODE_ATTR_NOT_FOUND && char_data->start != char_data->orig_start) { printf("# TODO case in char_read_by_uuid_cb\n"); goto done; } if (status != 0) { resp_error(err_COMM_ERR); // Todo: status goto done; } list = dec_read_by_type_resp(pdu, plen); resp_begin(rsp_READ); if (list == NULL) goto nolist; for (i = 0; i < list->num; i++) { uint8_t *value = list->data[i]; int j; char_data->start = att_get_u16(value) + 1; send_uint(tag_HANDLE, att_get_u16(value)); send_data(value+2, list->len-2); // All the same length?? } att_data_list_free(list); nolist: resp_end(); done: g_free(char_data); }
static void char_desc_cb(guint8 status, const guint8 *pdu, guint16 plen, gpointer user_data) { struct att_data_list *list; guint8 format; int i; if (status != 0) { printf("Discover all characteristic descriptors failed: " "%s\n", att_ecode2str(status)); goto done; } list = dec_find_info_resp(pdu, plen, &format); if (list == NULL) goto done; printf("\n"); for (i = 0; i < list->num; i++) { char uuidstr[MAX_LEN_UUID_STR]; uint16_t handle; uint8_t *value; bt_uuid_t uuid; value = list->data[i]; handle = att_get_u16(value); if (format == 0x01) uuid = att_get_uuid16(&value[2]); else uuid = att_get_uuid128(&value[2]); bt_uuid_to_string(&uuid, uuidstr, MAX_LEN_UUID_STR); printf("handle: 0x%04x, uuid: %s\n", handle, uuidstr); } att_data_list_free(list); done: printf("\n%s", get_prompt()); fflush(stdout); }
static void char_read_by_uuid_cb(guint8 status, const guint8 *pdu, guint16 plen, gpointer user_data) { struct characteristic_data *char_data = user_data; struct att_data_list *list; int i; if (status == ATT_ECODE_ATTR_NOT_FOUND && char_data->start != char_data->orig_start) goto done; if (status != 0) { printf("Read characteristics by UUID failed: %s\n", att_ecode2str(status)); goto done; } list = dec_read_by_type_resp(pdu, plen); if (list == NULL) goto done; for (i = 0; i < list->num; i++) { uint8_t *value = list->data[i]; int j; char_data->start = att_get_u16(value) + 1; printf("\nhandle: 0x%04x \t value: ", att_get_u16(value)); value += 2; for (j = 0; j < list->len - 2; j++, value++) printf("%02x ", *value); printf("\n"); } att_data_list_free(list); done: printf("\n%s", get_prompt()); fflush(stdout); g_free(char_data); }
static void char_desc_cb(guint8 status, const guint8 *pdu, guint16 plen, gpointer user_data) { struct att_data_list *list; guint8 format; uint16_t handle = 0xffff; int i; if (status != 0) { rl_printf("Discover descriptors finished: %s\n", att_ecode2str(status)); return; } list = dec_find_info_resp(pdu, plen, &format); if (list == NULL) return; for (i = 0; i < list->num; i++) { char uuidstr[MAX_LEN_UUID_STR]; uint8_t *value; bt_uuid_t uuid; value = list->data[i]; handle = att_get_u16(value); if (format == 0x01) uuid = att_get_uuid16(&value[2]); else uuid = att_get_uuid128(&value[2]); bt_uuid_to_string(&uuid, uuidstr, MAX_LEN_UUID_STR); rl_printf("handle: 0x%04x, uuid: %s\n", handle, uuidstr); } att_data_list_free(list); if (handle != 0xffff && handle < end) gatt_discover_char_desc(attrib, handle + 1, end, char_desc_cb, NULL); }
static void char_discovered_cb(guint8 status, const guint8 *ipdu, guint16 iplen, gpointer user_data) { struct discover_char *dc = user_data; struct att_data_list *list; unsigned int i, err = 0; uint16_t last = 0; uint8_t type; /* We have all the characteristic now, lets send it up */ if (status == ATT_ECODE_ATTR_NOT_FOUND) { err = dc->characteristics ? 0 : status; goto done; } if (status) { err = status; goto done; } list = dec_read_by_type_resp(ipdu, iplen); if (list == NULL) { err = ATT_ECODE_IO; goto done; } if (list->len == 7) type = BT_UUID16; else type = BT_UUID128; for (i = 0; i < list->num; i++) { uint8_t *value = list->data[i]; struct gatt_char *chars; bt_uuid_t uuid128; last = get_le16(value); get_uuid128(type, &value[5], &uuid128); if (dc->uuid && bt_uuid_cmp(dc->uuid, &uuid128)) continue; chars = g_try_new0(struct gatt_char, 1); if (!chars) { att_data_list_free(list); err = ATT_ECODE_INSUFF_RESOURCES; goto done; } chars->handle = last; chars->properties = value[2]; chars->value_handle = get_le16(&value[3]); bt_uuid_to_string(&uuid128, chars->uuid, sizeof(chars->uuid)); dc->characteristics = g_slist_append(dc->characteristics, chars); } att_data_list_free(list); /* * If last handle is lower from previous start handle then it is smth * wrong. Let's stop search, otherwise we might enter infinite loop. */ if (last < dc->start) { err = ATT_ECODE_UNLIKELY; goto done; } dc->start = last + 1; if (last != 0 && (dc->start < dc->end)) { bt_uuid_t uuid; guint16 oplen; size_t buflen; uint8_t *buf; buf = g_attrib_get_buffer(dc->attrib, &buflen); bt_uuid16_create(&uuid, GATT_CHARAC_UUID); oplen = enc_read_by_type_req(dc->start, dc->end, &uuid, buf, buflen); if (oplen == 0) return; g_attrib_send(dc->attrib, dc->id, buf, oplen, char_discovered_cb, discover_char_ref(dc), discover_char_unref); return; } done: dc->cb(err, dc->characteristics, dc->user_data); }
static void find_included_cb(uint8_t status, const uint8_t *pdu, uint16_t len, gpointer user_data) { struct included_discovery *isd = user_data; uint16_t last_handle = isd->end_handle; unsigned int err = status; struct att_data_list *list; int i; if (err == ATT_ECODE_ATTR_NOT_FOUND) err = 0; if (status) goto done; list = dec_read_by_type_resp(pdu, len); if (list == NULL) { err = ATT_ECODE_IO; goto done; } if (list->len != 6 && list->len != 8) { err = ATT_ECODE_IO; att_data_list_free(list); goto done; } for (i = 0; i < list->num; i++) { struct gatt_included *incl; incl = included_from_buf(list->data[i], list->len); last_handle = incl->handle; /* 128 bit UUID, needs resolving */ if (list->len == 6) { resolve_included_uuid(isd, incl); continue; } isd->includes = g_slist_append(isd->includes, incl); } att_data_list_free(list); /* * If last handle is lower from previous start handle then it is smth * wrong. Let's stop search, otherwise we might enter infinite loop. */ if (last_handle < isd->start_handle) { isd->err = ATT_ECODE_UNLIKELY; goto done; } isd->start_handle = last_handle + 1; if (last_handle < isd->end_handle) find_included(isd, isd->start_handle); done: if (isd->err == 0) isd->err = err; }
static void primary_all_cb(guint8 status, const guint8 *ipdu, guint16 iplen, gpointer user_data) { struct discover_primary *dp = user_data; struct att_data_list *list; unsigned int i, err; uint16_t start, end; uint8_t type; if (status) { err = status == ATT_ECODE_ATTR_NOT_FOUND ? 0 : status; goto done; } list = dec_read_by_grp_resp(ipdu, iplen); if (list == NULL) { err = ATT_ECODE_IO; goto done; } if (list->len == 6) type = BT_UUID16; else if (list->len == 20) type = BT_UUID128; else { att_data_list_free(list); err = ATT_ECODE_INVALID_PDU; goto done; } for (i = 0, end = 0; i < list->num; i++) { const uint8_t *data = list->data[i]; struct gatt_primary *primary; bt_uuid_t uuid128; start = get_le16(&data[0]); end = get_le16(&data[2]); get_uuid128(type, &data[4], &uuid128); primary = g_try_new0(struct gatt_primary, 1); if (!primary) { att_data_list_free(list); err = ATT_ECODE_INSUFF_RESOURCES; goto done; } primary->range.start = start; primary->range.end = end; bt_uuid_to_string(&uuid128, primary->uuid, sizeof(primary->uuid)); dp->primaries = g_slist_append(dp->primaries, primary); } att_data_list_free(list); err = 0; /* * If last handle is lower from previous start handle then it is smth * wrong. Let's stop search, otherwise we might enter infinite loop. */ if (end < dp->start) { err = ATT_ECODE_UNLIKELY; goto done; } dp->start = end + 1; if (end != 0xffff) { size_t buflen; uint8_t *buf = g_attrib_get_buffer(dp->attrib, &buflen); guint16 oplen = encode_discover_primary(dp->start, 0xffff, NULL, buf, buflen); g_attrib_send(dp->attrib, dp->id, buf, oplen, primary_all_cb, discover_primary_ref(dp), discover_primary_unref); return; } done: dp->cb(err, dp->primaries, dp->user_data); }
static void desc_discovered_cb(guint8 status, const guint8 *ipdu, guint16 iplen, gpointer user_data) { struct discover_desc *dd = user_data; struct att_data_list *list; unsigned int i, err = 0; guint8 format; uint16_t last = 0xffff; uint8_t type; gboolean uuid_found = FALSE; if (status == ATT_ECODE_ATTR_NOT_FOUND) { err = dd->descriptors ? 0 : status; goto done; } if (status) { err = status; goto done; } list = dec_find_info_resp(ipdu, iplen, &format); if (!list) { err = ATT_ECODE_IO; goto done; } if (format == ATT_FIND_INFO_RESP_FMT_16BIT) type = BT_UUID16; else type = BT_UUID128; for (i = 0; i < list->num; i++) { uint8_t *value = list->data[i]; struct gatt_desc *desc; bt_uuid_t uuid128; last = get_le16(value); get_uuid128(type, &value[2], &uuid128); if (dd->uuid) { if (bt_uuid_cmp(dd->uuid, &uuid128)) continue; else uuid_found = TRUE; } desc = g_try_new0(struct gatt_desc, 1); if (!desc) { att_data_list_free(list); err = ATT_ECODE_INSUFF_RESOURCES; goto done; } bt_uuid_to_string(&uuid128, desc->uuid, sizeof(desc->uuid)); desc->handle = last; if (type == BT_UUID16) desc->uuid16 = get_le16(&value[2]); dd->descriptors = g_slist_append(dd->descriptors, desc); if (uuid_found) break; } att_data_list_free(list); /* * If last handle is lower from previous start handle then it is smth * wrong. Let's stop search, otherwise we might enter infinite loop. */ if (last < dd->start) { err = ATT_ECODE_UNLIKELY; goto done; } dd->start = last + 1; if (last < dd->end && !uuid_found) { guint16 oplen; size_t buflen; uint8_t *buf; buf = g_attrib_get_buffer(dd->attrib, &buflen); oplen = enc_find_info_req(dd->start, dd->end, buf, buflen); if (oplen == 0) return; g_attrib_send(dd->attrib, dd->id, buf, oplen, desc_discovered_cb, discover_desc_ref(dd), discover_desc_unref); return; } done: dd->cb(err, dd->descriptors, dd->user_data); }
static void descriptor_cb(guint8 status, const guint8 *pdu, guint16 plen, gpointer user_data) { struct query_data *current = user_data; struct gatt_service *gatt = current->gatt; struct characteristic *chr = current->chr; struct att_data_list *list; guint8 format; int i; INFO("%s status=%d",chr->path,status); if (status != 0) { chr->descriptor_count = 0; if (att_device_connected(gatt)) goto update; else goto done; } list = dec_find_info_resp(pdu, plen, &format); if (list == NULL) { INFO("%s no descriptors",chr->path); chr->descriptor_count = 0; goto update; } INFO("%s %d descriptors",chr->path,list->num); chr->descriptor_count = list->num; for (i = 0; i < list->num; i++) { guint16 handle; bt_uuid_t uuid; uint8_t *dinfo = list->data[i]; struct query_data *qfmt; guint ret = 0; handle = att_get_u16(dinfo); if (format == 0x01) { uuid = att_get_uuid16(&dinfo[2]); } else { /* Currently, only "user description" and "presentation * format" descriptors are used, and both have 16-bit * UUIDs. Therefore there is no need to support format * 0x02 yet. */ INFO("unkown format"); add_characteristic_descriptor(current,0x0000); continue; } qfmt = g_new0(struct query_data, 1); qfmt->gatt = current->gatt; qfmt->chr = current->chr; qfmt->handle = handle; if (uuid_desc16_cmp(&uuid, GATT_CHARAC_USER_DESC_UUID) == 0) { query_list_append(gatt, qfmt); ret = gatt_read_char(gatt->attrib, handle, 0, update_char_desc, qfmt); } else if (uuid_desc16_cmp(&uuid, GATT_CHARAC_FMT_UUID) == 0) { query_list_append(gatt, qfmt); ret = gatt_read_char(gatt->attrib, handle, 0, update_char_format, qfmt); } else if (uuid_desc16_cmp(&uuid, GATT_CLIENT_CHARAC_CFG_UUID) == 0) { query_list_append(gatt, qfmt); ret = gatt_read_char(gatt->attrib, handle, 0, update_char_client_conf, qfmt); } else if (uuid_desc16_cmp(&uuid, GATT_SERVER_CHARAC_CFG_UUID) == 0) { query_list_append(gatt, qfmt); ret = gatt_read_char(gatt->attrib, handle, 0, update_char_server_conf, qfmt); } else if (uuid_desc16_cmp(&uuid, GATT_CHARAC_EXT_PROPER_UUID) == 0) { query_list_append(gatt, qfmt); ret = gatt_read_char(gatt->attrib, handle, 0, update_char_ext_props, qfmt); } else g_free(qfmt); if (ret == 0) add_characteristic_descriptor(current,0x0000); } att_data_list_free(list); update: check_updated_characteristics(gatt); done: query_list_remove(gatt, current); g_free(current); }
static void primary_all_cb(guint8 status, const guint8 *ipdu, guint16 iplen, gpointer user_data) { struct discover_primary *dp = user_data; struct att_data_list *list; unsigned int i, err; uint16_t start, end; if (status) { err = status == ATT_ECODE_ATTR_NOT_FOUND ? 0 : status; goto done; } list = dec_read_by_grp_resp(ipdu, iplen); if (list == NULL) { err = ATT_ECODE_IO; goto done; } for (i = 0, end = 0; i < list->num; i++) { const uint8_t *data = list->data[i]; struct gatt_primary *primary; bt_uuid_t uuid; start = att_get_u16(&data[0]); end = att_get_u16(&data[2]); if (list->len == 6) { bt_uuid_t uuid16 = att_get_uuid16(&data[4]); bt_uuid_to_uuid128(&uuid16, &uuid); } else if (list->len == 20) { uuid = att_get_uuid128(&data[4]); } else { /* Skipping invalid data */ continue; } primary = g_try_new0(struct gatt_primary, 1); if (!primary) { att_data_list_free(list); err = ATT_ECODE_INSUFF_RESOURCES; goto done; } primary->range.start = start; primary->range.end = end; bt_uuid_to_string(&uuid, primary->uuid, sizeof(primary->uuid)); dp->primaries = g_slist_append(dp->primaries, primary); } att_data_list_free(list); err = 0; if (end != 0xffff) { size_t buflen; uint8_t *buf = g_attrib_get_buffer(dp->attrib, &buflen); guint16 oplen = encode_discover_primary(end + 1, 0xffff, NULL, buf, buflen); g_attrib_send(dp->attrib, 0, buf, oplen, primary_all_cb, dp, NULL); return; } done: dp->cb(dp->primaries, err, dp->user_data); discover_primary_free(dp); }
static void char_discovered_cb(guint8 status, const guint8 *ipdu, guint16 iplen, gpointer user_data) { struct discover_char *dc = user_data; struct att_data_list *list; unsigned int i, err = ATT_ECODE_ATTR_NOT_FOUND; uint16_t last = 0; if (status) { err = status; goto done; } list = dec_read_by_type_resp(ipdu, iplen); if (list == NULL) { err = ATT_ECODE_IO; goto done; } for (i = 0; i < list->num; i++) { uint8_t *value = list->data[i]; struct gatt_char *chars; bt_uuid_t uuid; last = att_get_u16(value); if (list->len == 7) { bt_uuid_t uuid16 = att_get_uuid16(&value[5]); bt_uuid_to_uuid128(&uuid16, &uuid); } else uuid = att_get_uuid128(&value[5]); if (dc->uuid && bt_uuid_cmp(dc->uuid, &uuid)) continue; chars = g_try_new0(struct gatt_char, 1); if (!chars) { err = ATT_ECODE_INSUFF_RESOURCES; goto done; } chars->handle = last; chars->properties = value[2]; chars->value_handle = att_get_u16(&value[3]); bt_uuid_to_string(&uuid, chars->uuid, sizeof(chars->uuid)); dc->characteristics = g_slist_append(dc->characteristics, chars); } att_data_list_free(list); if (last != 0 && (last + 1 < dc->end)) { bt_uuid_t uuid; guint16 oplen; size_t buflen; uint8_t *buf; buf = g_attrib_get_buffer(dc->attrib, &buflen); bt_uuid16_create(&uuid, GATT_CHARAC_UUID); oplen = enc_read_by_type_req(last + 1, dc->end, &uuid, buf, buflen); if (oplen == 0) return; g_attrib_send(dc->attrib, 0, buf, oplen, char_discovered_cb, dc, NULL); return; } done: err = (dc->characteristics ? 0 : err); dc->cb(dc->characteristics, err, dc->user_data); discover_char_free(dc); }
void char_desc_cb(guint8 status, const guint8 *pdu, guint16 plen, gpointer user_data) { struct att_data_list *list = NULL; guint8 format; uint16_t handle = 0xffff; int i; char uuid_str[MAX_LEN_UUID_STR]; uint8_t *value; printf_dbg("[CB] IN char_desc_cb\n"); if (status) { cb_ret_val = BL_REQUEST_FAIL_ERROR; sprintf(cb_ret_msg, "Characteristic descriptor " "callback: Failure: %s\n", att_ecode2str(status)); goto exit; } list = dec_find_info_resp(pdu, plen, &format); if (list == NULL) { cb_ret_val = BL_NO_ERROR; strcpy(cb_ret_msg, "Characteristic descriptor callback: Nothing found\n"); goto exit; } for (i = 0; i < list->num; i++) { bt_uuid_t uuid; value = list->data[i]; handle = att_get_u16(value); if (format == 0x01) uuid = att_get_uuid16(&value[2]); else uuid = att_get_uuid128(&value[2]); bt_uuid_to_string(&uuid, uuid_str, MAX_LEN_UUID_STR); if (strcmp(uuid_str, GATT_PRIM_SVC_UUID_STR) && strcmp(uuid_str, GATT_SND_SVC_UUID_STR) && strcmp(uuid_str, GATT_INCLUDE_UUID_STR) && strcmp(uuid_str, GATT_CHARAC_UUID_STR)) { bl_desc_t *bl_desc = bl_desc_new(uuid_str, handle); if (bl_desc == NULL) { cb_ret_val = BL_MALLOC_ERROR; strcpy(cb_ret_msg, "Characteristic descriptor callback: Malloc " "error\n"); goto exit; } if (bl_desc_list == NULL) { bl_desc_list = g_slist_alloc(); if (bl_desc_list == NULL) { cb_ret_val = BL_MALLOC_ERROR; strcpy(cb_ret_msg, "Characteristic descriptor callback: Malloc " "error\n"); goto exit; } bl_desc_list->data = bl_desc; } else { bl_desc_list = g_slist_append(bl_desc_list, bl_desc); } } else { printf_dbg("Reach end of descriptor list\n"); goto exit; } } if ((handle != 0xffff) && (handle < end_handle_cb)) { printf_dbg("[CB] OUT with asking for a new request\n"); if (gatt_discover_char_desc(attrib, handle + 1, end_handle_cb, char_desc_cb, NULL)) { goto next; } cb_ret_val = BL_SEND_REQUEST_ERROR; strcpy(cb_ret_msg, "Unable to send request\n"); } exit: if (bl_desc_list) { // Return what we got if we add something cb_ret_val = BL_NO_ERROR; cb_ret_pointer = bl_desc_list; } bl_desc_list = NULL; g_mutex_unlock(pending_callback); next: if (list) att_data_list_free(list); printf_dbg("[CB] OUT char_desc_cb\n"); }