예제 #1
0
static void resolve_included_uuid_cb(uint8_t status, const uint8_t *pdu,
					uint16_t len, gpointer user_data)
{
	struct included_uuid_query *query = user_data;
	struct included_discovery *isd = query->isd;
	struct gatt_included *incl = query->included;
	unsigned int err = status;
	bt_uuid_t uuid128;
	size_t buflen;
	uint8_t *buf;

	if (err)
		goto done;

	buf = g_attrib_get_buffer(isd->attrib, &buflen);
	if (dec_read_resp(pdu, len, buf, buflen) != 16) {
		err = ATT_ECODE_IO;
		goto done;
	}

	get_uuid128(BT_UUID128, buf, &uuid128);

	bt_uuid_to_string(&uuid128, incl->uuid, sizeof(incl->uuid));
	isd->includes = g_slist_append(isd->includes, incl);
	query->included = NULL;

done:
	if (isd->err == 0)
		isd->err = err;
}
예제 #2
0
static struct gatt_included *included_from_buf(const uint8_t *buf, gsize len)
{
	struct gatt_included *incl = g_new0(struct gatt_included, 1);

	incl->handle = get_le16(&buf[0]);
	incl->range.start = get_le16(&buf[2]);
	incl->range.end = get_le16(&buf[4]);

	if (len == 8) {
		bt_uuid_t uuid128;

		get_uuid128(BT_UUID16, &buf[6], &uuid128);
		bt_uuid_to_string(&uuid128, incl->uuid, sizeof(incl->uuid));
	}

	return incl;
}
예제 #3
0
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);
}
예제 #4
0
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);
}
예제 #5
0
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);
}
예제 #6
0
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;
	uint8_t type;

	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 != 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, dc->id, buf, oplen,
				char_discovered_cb, discover_char_ref(dc),
				discover_char_unref);

		return;
	}

done:
	err = (dc->characteristics ? 0 : err);
	dc->cb(err, dc->characteristics, dc->user_data);
}