Beispiel #1
0
static void handle_characteristic(struct gatt_db_attribute *attr,
								void *user_data)
{
	struct gas *gas = user_data;
	uint16_t value_handle;
	bt_uuid_t uuid;

	if (!gatt_db_attribute_get_char_data(attr, NULL, &value_handle, NULL,
								NULL, &uuid)) {
		error("Failed to obtain characteristic data");
		return;
	}

	if (uuid_cmp(GATT_CHARAC_DEVICE_NAME, &uuid))
		handle_device_name(gas, value_handle);
	else if (uuid_cmp(GATT_CHARAC_APPEARANCE, &uuid))
		handle_appearance(gas, value_handle);
	else {
		char uuid_str[MAX_LEN_UUID_STR];

		/* TODO: Support peripheral privacy feature */

		bt_uuid_to_string(&uuid, uuid_str, sizeof(uuid_str));
		DBG("Unsupported characteristic: %s", uuid_str);
	}
}
Beispiel #2
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 uuid;
	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;
	}

	uuid = att_get_uuid128(buf);
	bt_uuid_to_string(&uuid, incl->uuid, sizeof(incl->uuid));
	isd->includes = g_slist_append(isd->includes, incl);

done:
	if (err)
		g_free(incl);

	if (isd->err == 0)
		isd->err = err;

	isd_unref(isd);

	g_free(query);
}
static void print_uuid(const bt_uuid_t *uuid)
{
	char uuid_str[MAX_LEN_UUID_STR];
	bt_uuid_t uuid128;

	bt_uuid_to_uuid128(uuid, &uuid128);
	bt_uuid_to_string(&uuid128, uuid_str, sizeof(uuid_str));

	printf("%s\n", uuid_str);
}
Beispiel #4
0
static void print_uuid(const uint8_t uuid[16])
{
	char uuid_str[MAX_LEN_UUID_STR];
	bt_uuid_t tmp;

	tmp.type = BT_UUID128;
	memcpy(tmp.value.u128.data, uuid, 16 * sizeof(uint8_t));
	bt_uuid_to_string(&tmp, uuid_str, sizeof(uuid_str));

	printf("%s\n", uuid_str);
}
static gboolean characteristic_get_uuid(const GDBusPropertyTable *property,
					DBusMessageIter *iter, void *data)
{
	char uuid[MAX_LEN_UUID_STR + 1];
	const char *ptr = uuid;
	struct characteristic *chrc = data;

	bt_uuid_to_string(&chrc->uuid, uuid, sizeof(uuid));
	dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &ptr);

	return TRUE;
}
Beispiel #6
0
static void check_updated_characteristics(struct gatt_service *gatt)
{
	DBusMessage *reply;
	DBusMessageIter iter, array_iter;
	GSList *l, *d;
	uint16_t count = 0;

	if (!att_device_connected(gatt))
		return;

	INFO("%s",gatt->path);

	for (l = gatt->chars; l; l = l->next) {
		struct characteristic *chr = l->data;
		for (d = chr->descriptors; d; d = d->next, count++);
		if (count < chr->descriptor_count) {
			INFO("Not all chars are updated (%s)",chr->path);
			return;
		}
	}

	/* DEBUG ONLY */
	for (l = gatt->chars; l; l = l->next) {
		struct characteristic *chr = l->data;
		for (d = chr->descriptors; d; d = d->next) {
			struct characteristic_descriptor *desc = d->data;
			char str[100];
			bt_uuid_to_string(&desc->uuid,str,100);
			INFO("%s desc:%s handle:%02X",chr->path,str,desc->handle);
		}
	}
	/* END OF DEBUG ONLY */

	reply = dbus_message_new_method_return(gatt->query->msg);

	dbus_message_iter_init_append(reply, &iter);

	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
				DBUS_TYPE_OBJECT_PATH_AS_STRING, &array_iter);

	for (l = gatt->chars; l; l = l->next) {
		struct characteristic *chr = l->data;

		dbus_message_iter_append_basic(&array_iter,
					DBUS_TYPE_OBJECT_PATH, &chr->path);
	}

	dbus_message_iter_close_container(&iter, &array_iter);

	g_dbus_send_message(gatt->conn, reply);
	INFO("dbus sent");
}
Beispiel #7
0
static void log_service_event(struct gatt_db_attribute *attr, const char *str)
{
	char uuid_str[MAX_LEN_UUID_STR];
	bt_uuid_t uuid;
	uint16_t start, end;

	gatt_db_attribute_get_service_uuid(attr, &uuid);
	bt_uuid_to_string(&uuid, uuid_str, sizeof(uuid_str));

	gatt_db_attribute_get_service_handles(attr, &start, &end);

	PRLOG("%s - UUID: %s start: 0x%04x end: 0x%04x\n", str, uuid_str,
								start, end);
}
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 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;
}
Beispiel #10
0
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);
}
Beispiel #11
0
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);
}
Beispiel #13
0
static void handle_characteristic(struct gatt_db_attribute *attr,
								void *user_data)
{
	struct btd_device *device = user_data;
	uint16_t value_handle;
	bt_uuid_t uuid, pnpid_uuid;

	bt_string_to_uuid(&pnpid_uuid, PNPID_UUID);

	if (!gatt_db_attribute_get_char_data(attr, NULL, &value_handle, NULL,
								NULL, &uuid)) {
		error("Failed to obtain characteristic data");
		return;
	}

	if (bt_uuid_cmp(&pnpid_uuid, &uuid) == 0)
		handle_pnpid(device, value_handle);
	else {
		char uuid_str[MAX_LEN_UUID_STR];

		bt_uuid_to_string(&uuid, uuid_str, sizeof(uuid_str));
		DBG("Unsupported characteristic: %s", uuid_str);
	}
}
Beispiel #14
0
static void store_attribute(struct gatt_service *gatt, uint16_t handle,
				uint16_t type, uint8_t *value, gsize len)
{
	bdaddr_t sba, dba;
	bt_uuid_t uuid;
	char *str, *tmp;
	guint i;

	str = g_malloc0(MAX_LEN_UUID_STR + len * 2 + 1);

	bt_uuid16_create(&uuid, type);
	bt_uuid_to_string(&uuid, str, MAX_LEN_UUID_STR);

	str[MAX_LEN_UUID_STR - 1] = '#';

	for (i = 0, tmp = str + MAX_LEN_UUID_STR; i < len; i++, tmp += 2)
		sprintf(tmp, "%02X", value[i]);

	gatt_get_address(gatt, &sba, &dba);

	write_device_attribute(&sba, &dba, handle, str);

	g_free(str);
}
Beispiel #15
0
int gattlib_uuid_to_string(const bt_uuid_t *uuid, char *str, size_t n) {
	return bt_uuid_to_string(uuid, str, n);
}
Beispiel #16
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;

	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);
}
Beispiel #17
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;

	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);
}
Beispiel #18
0
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");
}
Beispiel #19
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);
}
Beispiel #20
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);
}
Beispiel #21
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);
}