guint gatt_discover_desc(GAttrib *attrib, uint16_t start, uint16_t end,
						bt_uuid_t *uuid, gatt_cb_t func,
						gpointer user_data)
{
	size_t buflen;
	uint8_t *buf = g_attrib_get_buffer(attrib, &buflen);
	struct discover_desc *dd;
	guint16 plen;

	plen = enc_find_info_req(start, end, buf, buflen);
	if (plen == 0)
		return 0;

	dd = g_try_new0(struct discover_desc, 1);
	if (dd == NULL)
		return 0;

	dd->attrib = g_attrib_ref(attrib);
	dd->cb = func;
	dd->user_data = user_data;
	dd->start = start;
	dd->end = end;
	dd->uuid = g_memdup(uuid, sizeof(bt_uuid_t));

	dd->id = g_attrib_send(attrib, 0, buf, plen, desc_discovered_cb,
				discover_desc_ref(dd), discover_desc_unref);

	return dd->id;
}
Exemple #2
0
guint gatt_discover_char_desc(GAttrib *attrib, uint16_t start, uint16_t end,
				GAttribResultFunc func, gpointer user_data)
{
	uint8_t *buf;
	size_t buflen;
	guint16 plen;

	buf = g_attrib_get_buffer(attrib, &buflen);
	plen = enc_find_info_req(start, end, buf, buflen);
	if (plen == 0)
		return 0;

	return g_attrib_send(attrib, 0, buf, plen, func, user_data, NULL);
}
guint gatt_find_info(GAttrib *attrib, uint16_t start, uint16_t end,
				GAttribResultFunc func, gpointer user_data)
{
	uint8_t *buf;
	int buflen;
	guint16 plen;

	buf = g_attrib_get_buffer(attrib, &buflen);
	plen = enc_find_info_req(start, end, buf, buflen);
	if (plen == 0)
		return 0;

	return g_attrib_send(attrib, 0, ATT_OP_FIND_INFO_REQ, buf, plen, func,
							user_data, 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);
}