Ejemplo n.º 1
0
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);
}
Ejemplo n.º 2
0
Archivo: hog.c Proyecto: aguedes/bluez
static void report_reference_cb(guint8 status, const guint8 *pdu,
					guint16 plen, gpointer user_data)
{
	struct report *report = user_data;

	if (status != 0) {
		error("Read Report Reference descriptor failed: %s",
							att_ecode2str(status));
		return;
	}

	if (plen != 3) {
		error("Malformed ATT read response");
		return;
	}

	report->id = pdu[1];
	report->type = pdu[2];
	DBG("Report ID: 0x%02x Report type: 0x%02x", pdu[1], pdu[2]);

	/* Enable notifications only for Input Reports */
	if (report->type == HOG_REPORT_TYPE_INPUT)
		gatt_read_char(report->hog->attrib, report->ccc_handle,
							ccc_read_cb, report);
}
Ejemplo n.º 3
0
static void cmd_read_hnd(int argcp, char **argvp)
{
    int handle;

    if (conn_state != STATE_CONNECTED) {
        resp_error(err_BAD_STATE);
        return;
    }

    if (argcp < 2) {
        resp_error(err_BAD_PARAM);;
        return;
    }

    handle = strtohandle(argvp[1]);
    if (handle < 0) {
        resp_error(err_BAD_PARAM);;
        return;
    }

    if (argcp == 2) {
        gatt_read_char(attrib, handle, char_read_cb, attrib);
    } else {
        char *end;
        int offset = strtol(argvp[2], &end, 0);

        if (*end != '\0') {
            resp_error(err_BAD_PARAM);;
            return;
        }

        gatt_read_char_single(attrib, handle, offset, char_read_single_cb,
                            attrib);
    }
}
Ejemplo n.º 4
0
static void discover_char_cb(GSList *chars, guint8 status, gpointer user_data)
{
	struct heartrate *hr = user_data;

	if (status) {
		error("Discover HRS characteristics failed: %s",
							att_ecode2str(status));
		return;
	}

	for (; chars; chars = chars->next) {
		struct gatt_char *c = chars->data;

		if (g_strcmp0(c->uuid, HEART_RATE_MEASUREMENT_UUID) == 0) {
			struct gatt_char *c_next =
				(chars->next ? chars->next->data : NULL);

			hr->measurement_val_handle = c->value_handle;

			discover_measurement_ccc(hr, c, c_next);
		} else if (g_strcmp0(c->uuid, BODY_SENSOR_LOCATION_UUID) == 0) {
			DBG("Body Sensor Location supported");

			gatt_read_char(hr->attrib, c->value_handle,
						read_sensor_location_cb, hr);
		} else if (g_strcmp0(c->uuid,
					HEART_RATE_CONTROL_POINT_UUID) == 0) {
			DBG("Heart Rate Control Point supported");
			hr->hrcp_val_handle = c->value_handle;
		}
	}
}
Ejemplo n.º 5
0
static gboolean characteristics_read(gpointer user_data)
{
	GAttrib *attrib = user_data;

	if (opt_uuid != NULL) {
		struct characteristic_data *char_data;

		char_data = g_new(struct characteristic_data, 1);
		char_data->attrib = attrib;
		char_data->start = opt_start;
		char_data->end = opt_end;

		gatt_read_char_by_uuid(attrib, opt_start, opt_end, opt_uuid,
						char_read_by_uuid_cb, char_data);

		return FALSE;
	}

	if (opt_handle <= 0) {
		g_printerr("A valid handle is required\n");
		g_main_loop_quit(event_loop);
		return FALSE;
	}

	gatt_read_char(attrib, opt_handle, char_read_cb, attrib);

	return FALSE;
}
Ejemplo n.º 6
0
static void get_report(struct uhid_event *ev, void *user_data)
{
	struct hog_device *hogdev = user_data;
	struct report *report;
	guint8 err;

	/* uhid never sends reqs in parallel; if there's a req, it timed out */
	if (hogdev->getrep_att) {
		g_attrib_cancel(hogdev->attrib, hogdev->getrep_att);
		hogdev->getrep_att = 0;
	}

	hogdev->getrep_id = ev->u.get_report.id;

	report = find_report(hogdev, ev->u.get_report.rtype,
							ev->u.get_report.rnum);
	if (!report) {
		err = ENOTSUP;
		goto fail;
	}

	hogdev->getrep_att = gatt_read_char(hogdev->attrib,
						report->decl->value_handle,
						get_report_cb, hogdev);
	if (!hogdev->getrep_att) {
		err = ENOMEM;
		goto fail;
	}

	return;

fail:
	/* cancel the request on failure */
	get_report_cb(err, NULL, 0, hogdev);
}
Ejemplo n.º 7
0
//reads a certain handle and places value into buf, returns length
int ble_char_read(int handle, unsigned char* buf){
	//auto connect if not connected
	if(!ble_connected){
		ble_connect(name);
	}
	ble_read = 0;
	gettimeofday(&t1, NULL);
	gatt_read_char(attrib, handle, char_read_cb, attrib);
	while(!ble_read){
		usleep(10000);
		gettimeofday(&t2, NULL);
		elapsedTime = (t2.tv_sec - t1.tv_sec) * 1000.0;      // sec to ms
		elapsedTime += (t2.tv_usec - t1.tv_usec) / 1000.0;   // us to ms
		if (elapsedTime > 250)	//timeout of 250ms
		{
			printf("read error: %lf\n", elapsedTime);
			ble_disconnect();
			return 0;
		}
	}
    //printf("(%lfms) len: %d\n", elapsedTime, (int)ble_read_len);
	/*for (i = 0; i < ble_read_len; i++){
		printf("%02x ", ble_read_val[i]);
	}
	printf("\n");*/
	memcpy(buf, ble_read_val, ble_read_len);
	return ble_read_len;
}
Ejemplo n.º 8
0
Archivo: hog.c Proyecto: aguedes/bluez
static void discover_report_cb(uint8_t status, GSList *descs, void *user_data)
{
	struct report *report = user_data;
	struct bt_hog *hog = report->hog;

	if (status != 0) {
		error("Discover report descriptors failed: %s",
							att_ecode2str(status));
		return;
	}

	for ( ; descs; descs = descs->next) {
		struct gatt_desc *desc = descs->data;

		switch (desc->uuid16) {
		case GATT_CLIENT_CHARAC_CFG_UUID:
			report->ccc_handle = desc->handle;
			break;
		case GATT_REPORT_REFERENCE:
			gatt_read_char(hog->attrib, desc->handle,
						report_reference_cb, report);
			break;
		}
	}
}
Ejemplo n.º 9
0
static void cmd_read_hnd(int argcp, char **argvp)
{
	int handle;
	int offset = 0;

	if (conn_state != STATE_CONNECTED) {
		printf("Command failed: disconnected\n");
		return;
	}

	if (argcp < 2) {
		printf("Missing argument: handle\n");
		return;
	}

	handle = strtohandle(argvp[1]);
	if (handle < 0) {
		printf("Invalid handle: %s\n", argvp[1]);
		return;
	}

	if (argcp > 2) {
		char *e;

		errno = 0;
		offset = strtol(argvp[2], &e, 0);
		if (errno != 0 || *e != '\0') {
			printf("Invalid offset: %s\n", argvp[2]);
			return;
		}
	}

	gatt_read_char(g_connection->attrib, handle, offset, char_read_cb, g_connection->attrib);
}
static void discover_char_cb(uint8_t status, GSList *chars, void *user_data)
{
	struct csc *csc = user_data;
	uint16_t feature_val_handle = 0;

	if (status) {
		error("Discover CSCS characteristics: %s",
							att_ecode2str(status));
		return;
	}

	for (; chars; chars = chars->next) {
		struct gatt_char *c = chars->data;
		struct gatt_char *c_next =
				(chars->next ? chars->next->data : NULL);

		if (g_strcmp0(c->uuid, CSC_MEASUREMENT_UUID) == 0) {
			csc->attio_measurement_id =
				g_attrib_register(csc->attrib,
					ATT_OP_HANDLE_NOTIFY, c->value_handle,
					measurement_notify_handler, csc, NULL);

			discover_desc(csc, c, c_next);
		} else if (g_strcmp0(c->uuid, CSC_FEATURE_UUID) == 0) {
			feature_val_handle = c->value_handle;
		} else if (g_strcmp0(c->uuid, SENSOR_LOCATION_UUID) == 0) {
			DBG("Sensor Location supported");
			gatt_read_char(csc->attrib, c->value_handle,
							read_location_cb, csc);
		} else if (g_strcmp0(c->uuid, SC_CONTROL_POINT_UUID) == 0) {
			DBG("SC Control Point supported");
			csc->controlpoint_val_handle = c->value_handle;

			csc->attio_controlpoint_id = g_attrib_register(
					csc->attrib, ATT_OP_HANDLE_IND,
					c->value_handle,
					controlpoint_ind_handler, csc, NULL);

			discover_desc(csc, c, c_next);
		}
	}

	if (feature_val_handle > 0)
		gatt_read_char(csc->attrib, feature_val_handle,
							read_feature_cb, csc);
}
Ejemplo n.º 11
0
static void read_char(struct bt_bas *bas, GAttrib *attrib, uint16_t handle,
				GAttribResultFunc func, gpointer user_data)
{
	struct gatt_request *req;
	unsigned int id;

	req = create_request(bas, user_data);

	id = gatt_read_char(attrib, handle, func, req);

	set_and_store_gatt_req(bas, req, id);
}
Ejemplo n.º 12
0
Archivo: hog.c Proyecto: aguedes/bluez
static struct report *report_new(struct bt_hog *hog, struct gatt_char *chr)
{
	struct report *report;

	report = g_new0(struct report, 1);
	report->hog = hog;
	report->decl = g_memdup(chr, sizeof(*chr));
	hog->reports = g_slist_append(hog->reports, report);

	gatt_read_char(hog->attrib, chr->value_handle, report_read_cb, report);

	return report;
}
Ejemplo n.º 13
0
static void discover_descriptor_cb(uint8_t status, GSList *descs,
								void *user_data)
{
	struct report *report;
	struct hog_device *hogdev;
	GAttrib *attrib = NULL;

	if (status != 0) {
		error("Discover all descriptors failed: %s",
							att_ecode2str(status));
		return;
	}

	for ( ; descs; descs = descs->next) {
		struct gatt_desc *desc = descs->data;

		switch (desc->uuid16) {
		case GATT_CLIENT_CHARAC_CFG_UUID:
			report = user_data;
			report->ccc_handle = desc->handle;
			enable_report_notifications(report, true);
			break;
		case GATT_REPORT_REFERENCE:
			report = user_data;
			attrib = report->hogdev->attrib;
			gatt_read_char(attrib, desc->handle,
						report_reference_cb, report);
			break;
		case GATT_EXTERNAL_REPORT_REFERENCE:
			hogdev = user_data;
			attrib = hogdev->attrib;
			gatt_read_char(attrib, desc->handle,
					external_report_reference_cb, hogdev);
			break;
		}
	}
}
Ejemplo n.º 14
0
static void read_tx_power(struct monitor *monitor)
{
	struct att_range *txpower = monitor->txpower;
	bt_uuid_t uuid;

	if (monitor->txpowerhandle != 0) {
		gatt_read_char(monitor->attrib, monitor->txpowerhandle, 0,
						tx_power_read_cb, monitor);
		return;
	}

	bt_uuid16_create(&uuid, POWER_LEVEL_CHR_UUID);

	gatt_discover_char(monitor->attrib, txpower->start, txpower->end,
				&uuid, tx_power_handle_cb, monitor);
}
Ejemplo n.º 15
0
Archivo: hog.c Proyecto: aguedes/bluez
static void discover_external_cb(uint8_t status, GSList *descs, void *user_data)
{
	struct bt_hog *hog = user_data;

	if (status != 0) {
		error("Discover external descriptors failed: %s",
							att_ecode2str(status));
		return;
	}

	for ( ; descs; descs = descs->next) {
		struct gatt_desc *desc = descs->data;

		gatt_read_char(hog->attrib, desc->handle,
					external_report_reference_cb, hog);
	}
}
Ejemplo n.º 16
0
static void tx_power_handle_cb(GSList *characteristics, guint8 status,
							gpointer user_data)
{
	struct monitor *monitor = user_data;
	struct att_char *chr;

	if (status) {
		error("Discover Tx Power handle: %s", att_ecode2str(status));
		return;
	}

	chr = characteristics->data;
	monitor->txpowerhandle = chr->value_handle;

	DBG("Tx Power handle: 0x%04x", monitor->txpowerhandle);

	gatt_read_char(monitor->attrib, monitor->txpowerhandle, 0,
							tx_power_read_cb, monitor);
}
Ejemplo n.º 17
0
static void read_char(struct bt_dis *dis, GAttrib *attrib, uint16_t handle,
				GAttribResultFunc func, gpointer user_data)
{
	struct gatt_request *req;
	unsigned int id;

	req = create_request(dis, user_data);
	if (!req)
		return;

	id = gatt_read_char(attrib, handle, func, req);

	if (set_and_store_gatt_req(dis, req, id))
		return;

	error("dis: Could not read characteristic");
	g_attrib_cancel(attrib, id);
	free(req);
}
Ejemplo n.º 18
0
static void update_char_desc(guint8 status, const guint8 *pdu, guint16 len,
							gpointer user_data)
{
	struct query_data *current = user_data;
	struct gatt_service *gatt = current->gatt;
	struct characteristic *chr = current->chr;
	INFO("%s",chr->path);

	if (status == 0) {

		g_free(chr->desc);

		chr->desc = g_malloc(len);
		memcpy(chr->desc, pdu + 1, len - 1);
		chr->desc[len - 1] = '\0';

		store_attribute(gatt, current->handle,
				GATT_CHARAC_USER_DESC_UUID,
				(void *) chr->desc, len);
	} else if (status == ATT_ECODE_INSUFF_ENC) {
		GIOChannel *io = g_attrib_get_channel(gatt->attrib);
		BtIOSecLevel level = BT_IO_SEC_HIGH;

		bt_io_get(io, BT_IO_L2CAP, NULL,
				BT_IO_OPT_SEC_LEVEL, &level,
				BT_IO_OPT_INVALID);

		if (level < BT_IO_SEC_HIGH)
			level++;

		if (bt_io_set(io, BT_IO_L2CAP, NULL,
				BT_IO_OPT_SEC_LEVEL, level,
				BT_IO_OPT_INVALID)) {
			gatt_read_char(gatt->attrib, current->handle, 0,
					update_char_desc, current);
			return;
		}
	}

	add_characteristic_descriptor(current, GATT_CHARAC_USER_DESC_UUID);
	query_list_remove(gatt, current);
	g_free(current);
}
Ejemplo n.º 19
0
static void cmd_anki_vehicle_read(int argcp, char **argvp)
{
	if (conn_state != STATE_CONNECTED) {
		failed("Disconnected\n");
		return;
	}

	if (argcp < 1) {
		error("Missing argument: handle\n");
		return;
	}

	int handle = vehicle.read_char.value_handle;
	if (handle < 0) {
		error("Invalid handle: %s\n", argvp[1]);
		return;
	}

	gatt_read_char(attrib, handle, char_read_cb, attrib);
}
Ejemplo n.º 20
0
static int cmd_read_char(gpointer user_data, const char *handle)
{
  GAttrib *attrib = user_data;
  int hdl, ret;

  if (get_state() != STATE_CONNECTED) {
    printf("Device is not connected\n");
    return -1;
  }

  hdl = strtohandle(handle);
  if (hdl <= 0) {
    printf("A valid handle is needed\n");
    return -2;
  }

  gatt_read_char(attrib, hdl, char_read_cb, attrib);
  g_main_loop_run(event_loop);

  return 0;
}
Ejemplo n.º 21
0
static void cmd_read_hnd(int argcp, char **argvp)
{
	int handle;

	if (conn_state != STATE_CONNECTED) {
		resp_error(err_BAD_STATE);
		return;
	}

	if (argcp < 2) {
		resp_error(err_BAD_PARAM);
		return;
	}

	handle = strtohandle(argvp[1]);
	if (handle < 0) {
		resp_error(err_BAD_PARAM);
		return;
	}

	gatt_read_char(attrib, handle, char_read_cb, attrib);
}
Ejemplo n.º 22
0
static void cmd_read_hnd(int argcp, char **argvp)
{
	int handle;

	if (conn_state != STATE_CONNECTED) {
		failed("Disconnected\n");
		return;
	}

	if (argcp < 2) {
		error("Missing argument: handle\n");
		return;
	}

	handle = strtohandle(argvp[1]);
	if (handle < 0) {
		error("Invalid handle: %s\n", argvp[1]);
		return;
	}

	gatt_read_char(attrib, handle, char_read_cb, attrib);
}
static gboolean characteristics_read(gpointer user_data)
{
	GAttrib *attrib = user_data;

	if (opt_uuid != NULL) {

		gatt_read_char_by_uuid(attrib, opt_start, opt_end, opt_uuid,
						char_read_by_uuid_cb, NULL);

		return FALSE;
	}

	if (opt_handle <= 0) {
		g_printerr("A valid handle is required\n");
		g_main_loop_quit(event_loop);
		return FALSE;
	}

	gatt_read_char(attrib, opt_handle, char_read_cb, attrib);

	return FALSE;
}
Ejemplo n.º 24
0
static void update_char_value(guint8 status, const guint8 *pdu,
					guint16 len, gpointer user_data)
{
	struct query_data *current = user_data;
	struct gatt_service *gatt = current->gatt;
	struct characteristic *chr = current->chr;

	if (status == 0)
		characteristic_set_value(chr, pdu + 1, len - 1);
	else if (status == ATT_ECODE_INSUFF_ENC) {
		GIOChannel *io = g_attrib_get_channel(gatt->attrib);

		if (bt_io_set(io, BT_IO_L2CAP, NULL,
				BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_HIGH,
				BT_IO_OPT_INVALID)) {
			gatt_read_char(gatt->attrib, chr->handle, 0,
					update_char_value, current);
			return;
		}
	}

	query_list_remove(gatt, current);
	g_free(current);
}
Ejemplo n.º 25
0
static DBusMessage *read_val(DBusConnection *conn,
					DBusMessage *msg, void *data)
{
	struct characteristic *chr = data;
	DBusMessage *reply = NULL;
	DBusMessageIter iter;
	uint16_t offset = 0;
	uint16_t timeout = 0;
	guint retvalue = 0;

	if (!dbus_message_get_args(msg, NULL,
			DBUS_TYPE_UINT16, &offset,
			DBUS_TYPE_UINT16, &timeout,
			DBUS_TYPE_INVALID))
		return btd_error_invalid_args(msg);

	DBG("ReadValue chr=%s offset=%d timeout=%d",chr->path, offset, timeout);

	retvalue = gatt_read_char(chr->gatt->attrib,chr->handle,offset, read_val_cb,chr);
	if (retvalue == 0)
		return btd_error_failed(msg,"gatt_read_char failed");

	return dbus_message_new_method_return(msg);
}
Ejemplo n.º 26
0
static void process_deviceinfo_char(struct characteristic *ch)
{
	if (g_strcmp0(ch->attr.uuid, PNPID_UUID) == 0)
		gatt_read_char(ch->d->attrib, ch->attr.value_handle,
							read_pnpid_cb, ch);
}
Ejemplo n.º 27
0
Archivo: hog.c Proyecto: aguedes/bluez
static void char_discovered_cb(uint8_t status, GSList *chars, void *user_data)
{
	struct bt_hog *hog = user_data;
	struct gatt_primary *primary = hog->primary;
	bt_uuid_t report_uuid, report_map_uuid, info_uuid;
	bt_uuid_t proto_mode_uuid, ctrlpt_uuid;
	struct report *report;
	GSList *l;
	uint16_t info_handle = 0, proto_mode_handle = 0;

	if (status != 0) {
		const char *str = att_ecode2str(status);
		DBG("Discover all characteristics failed: %s", str);
		return;
	}

	bt_uuid16_create(&report_uuid, HOG_REPORT_UUID);
	bt_uuid16_create(&report_map_uuid, HOG_REPORT_MAP_UUID);
	bt_uuid16_create(&info_uuid, HOG_INFO_UUID);
	bt_uuid16_create(&proto_mode_uuid, HOG_PROTO_MODE_UUID);
	bt_uuid16_create(&ctrlpt_uuid, HOG_CONTROL_POINT_UUID);

	for (l = chars; l; l = g_slist_next(l)) {
		struct gatt_char *chr, *next;
		bt_uuid_t uuid;
		uint16_t start, end;

		chr = l->data;
		next = l->next ? l->next->data : NULL;

		DBG("0x%04x UUID: %s properties: %02x",
				chr->handle, chr->uuid, chr->properties);

		bt_string_to_uuid(&uuid, chr->uuid);

		start = chr->value_handle + 1;
		end = (next ? next->handle - 1 : primary->range.end);

		if (bt_uuid_cmp(&uuid, &report_uuid) == 0) {
			report = report_new(hog, chr);
			discover_report(hog->attrib, start, end, report);
		} else if (bt_uuid_cmp(&uuid, &report_map_uuid) == 0) {
			gatt_read_char(hog->attrib, chr->value_handle,
						report_map_read_cb, hog);
			discover_external(hog->attrib, start, end, hog);
		} else if (bt_uuid_cmp(&uuid, &info_uuid) == 0)
			info_handle = chr->value_handle;
		else if (bt_uuid_cmp(&uuid, &proto_mode_uuid) == 0)
			proto_mode_handle = chr->value_handle;
		else if (bt_uuid_cmp(&uuid, &ctrlpt_uuid) == 0)
			hog->ctrlpt_handle = chr->value_handle;
	}

	if (proto_mode_handle) {
		hog->proto_mode_handle = proto_mode_handle;
		gatt_read_char(hog->attrib, proto_mode_handle,
						proto_mode_read_cb, hog);
	}

	if (info_handle)
		gatt_read_char(hog->attrib, info_handle, info_read_cb, hog);
}
Ejemplo n.º 28
0
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);
}