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); }
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_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 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_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 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); }
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"); }