예제 #1
0
파일: gatt.c 프로젝트: atraber/RaspExt
static void find_included_cb(uint8_t status, const uint8_t *pdu, uint16_t len,
							gpointer user_data)
{
	struct included_discovery *isd = user_data;
	uint16_t last_handle = isd->end_handle;
	unsigned int err = status;
	struct att_data_list *list;
	int i;

	if (err == ATT_ECODE_ATTR_NOT_FOUND)
		err = 0;

	if (status)
		goto done;

	list = dec_read_by_type_resp(pdu, len);
	if (list == NULL) {
		err = ATT_ECODE_IO;
		goto done;
	}

	if (list->len != 6 && list->len != 8) {
		err = ATT_ECODE_IO;
		att_data_list_free(list);
		goto done;
	}

	for (i = 0; i < list->num; i++) {
		struct gatt_included *incl;

		incl = included_from_buf(list->data[i], list->len);
		last_handle = incl->handle;

		/* 128 bit UUID, needs resolving */
		if (list->len == 6) {
			resolve_included_uuid(isd, incl);
			continue;
		}

		isd->includes = g_slist_append(isd->includes, incl);
	}

	att_data_list_free(list);

	if (last_handle < isd->end_handle)
		find_included(isd, last_handle + 1);

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

	isd_unref(isd);
}
예제 #2
0
static void char_read_by_uuid_cb(guint8 status, const guint8 *pdu,
					guint16 plen, gpointer user_data)
{
	struct att_data_list *list;
	int i;
	GString *s;

	if (status != 0) {
		error("Read characteristics by UUID failed: %s\n",
							att_ecode2str(status));
		return;
	}

	list = dec_read_by_type_resp(pdu, plen);
	if (list == NULL)
		return;

	s = g_string_new(NULL);
	for (i = 0; i < list->num; i++) {
		uint8_t *value = list->data[i];
		int j;

		g_string_printf(s, "handle: 0x%04x \t value: ",
							get_le16(value));
		value += 2;
		for (j = 0; j < list->len - 2; j++, value++)
			g_string_append_printf(s, "%02x ", *value);

		rl_printf("%s\n", s->str);
	}

	att_data_list_free(list);
	g_string_free(s, TRUE);
}
static void char_read_by_uuid_cb(guint8 status, const guint8 *pdu,
					guint16 plen, gpointer user_data)
{
	struct att_data_list *list;
	int i;

	if (status != 0) {
		g_printerr("Read characteristics by UUID failed: %s\n",
							att_ecode2str(status));
		goto done;
	}

	list = dec_read_by_type_resp(pdu, plen);
	if (list == NULL)
		goto done;

	for (i = 0; i < list->num; i++) {
		uint8_t *value = list->data[i];
		int j;

		g_print("handle: 0x%04x \t value: ", get_le16(value));
		value += 2;
		for (j = 0; j < list->len - 2; j++, value++)
			g_print("%02x ", *value);
		g_print("\n");
	}

	att_data_list_free(list);

done:
	g_main_loop_quit(event_loop);
}
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);
}
예제 #5
0
파일: callback.c 프로젝트: DayBr3ak/BlueLib
void read_by_uuid_cb(guint8 status, const guint8 *pdu, guint16 plen,
                     gpointer user_data)
{
    struct att_data_list *list;
    GSList               *bl_value_list = NULL;
    cb_ctx_t             *cb_ctx = user_data;

    printf_dbg("[CB] IN read_by_uuid_cb\n");
    if (status) {
        cb_ctx->cb_ret_val = BL_REQUEST_FAIL_ERROR;
        sprintf(cb_ctx->cb_ret_msg, "Read by uuid callback: Failure: %s\n",
                att_ecode2str(status));
        goto error;
    }

    list = dec_read_by_type_resp(pdu, plen);
    if (list == NULL) {
        strcpy(cb_ctx->cb_ret_msg, "Read by uuid callback: Nothing found\n");
        cb_ctx->cb_ret_val = BL_NO_ERROR;
        goto error;
    }

    for (int i = 0; i < list->num; i++) {
        bl_value_t *bl_value = bl_value_new(NULL, att_get_u16(list->data[i]),
                                            list->len - 2, list->data[i] + 2);
        if (bl_value == NULL) {
            cb_ctx->cb_ret_val = BL_MALLOC_ERROR;
            strcpy(cb_ctx->cb_ret_msg,
                   "Read by uuid callback: Malloc error\n");
            goto error;
        }

        // Add it to the value list
        if (bl_value_list == NULL) {
            bl_value_list = g_slist_alloc();
            if (bl_value_list == NULL) {
                cb_ctx->cb_ret_val = BL_MALLOC_ERROR;
                strcpy(cb_ctx->cb_ret_msg,
                       "Read by uuid callback: Malloc error\n");
                goto error;
            }
            bl_value_list->data = bl_value;
        } else {
            bl_value_list = g_slist_append(bl_value_list, bl_value);
        }
    }

    att_data_list_free(list);

    cb_ctx->cb_ret_pointer = bl_value_list;
    cb_ctx->cb_ret_val     = BL_NO_ERROR;
    goto exit;

error:
    if (bl_value_list)
        bl_value_list_free(bl_value_list);
exit:
    g_mutex_unlock(&cb_ctx->pending_cb_mtx);
    printf_dbg("[CB] OUT read_by_uuid_cb\n");
}
예제 #6
0
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);
}
예제 #7
0
파일: hog_device.c 프로젝트: intgr/bluez
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);
}
예제 #9
0
파일: gatttool.c 프로젝트: BaKStap/bluez
static void char_read_by_uuid_cb(guint8 status, const guint8 *pdu,
					guint16 plen, gpointer user_data)
{
	struct characteristic_data *char_data = user_data;
	struct att_data_list *list;
	int i;

	if (status == ATT_ECODE_ATTR_NOT_FOUND &&
					char_data->start != opt_start)
		goto done;

	if (status != 0) {
		g_printerr("Read characteristics by UUID failed: %s\n",
							att_ecode2str(status));
		goto done;
	}

	list = dec_read_by_type_resp(pdu, plen);
	if (list == NULL)
		goto done;

	for (i = 0; i < list->num; i++) {
		uint8_t *value = list->data[i];
		int j;

		char_data->start = att_get_u16(value) + 1;

		g_print("handle: 0x%04x \t value: ", att_get_u16(value));
		value += 2;
		for (j = 0; j < list->len - 2; j++, value++)
			g_print("%02x ", *value);
		g_print("\n");
	}

	att_data_list_free(list);

	gatt_read_char_by_uuid(char_data->attrib, char_data->start,
					char_data->end, opt_uuid,
					char_read_by_uuid_cb,
					char_data);

	return;
done:
	g_free(char_data);
	g_main_loop_quit(event_loop);
}
예제 #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);
}
예제 #11
0
static void gattlib_result_read_uuid_cb(guint8 status, const guint8 *pdu, guint16 len, gpointer user_data) {
	struct gattlib_result_read_uuid_t* gattlib_result = user_data;
	struct att_data_list *list;
	int i;

	if (status == ATT_ECODE_ATTR_NOT_FOUND) {
		goto done;
	}

	if (status != 0) {
		fprintf(stderr, "Read characteristics by UUID failed: %s\n", att_ecode2str(status));
		goto done;
	}

	list = dec_read_by_type_resp(pdu, len);
	if (list == NULL) {
		goto done;
	}

	for (i = 0; i < list->num; i++) {
		uint8_t *value = list->data[i];
		int j;

		value += 2;

		gattlib_result->buffer_len = list->len - 2;

		if (gattlib_result->callback) {
			gattlib_result->callback(value, gattlib_result->buffer_len);
		} else {
			memcpy(gattlib_result->buffer, value, MIN(gattlib_result->buffer_len, gattlib_result->buffer_max_len));
		}
	}

	att_data_list_free(list);

done:
	if (gattlib_result->callback) {
		free(gattlib_result);
	} else {
		gattlib_result->completed = TRUE;
	}
}
예제 #12
0
static void char_read_by_uuid_cb(guint8 status, const guint8 *pdu,
					guint16 plen, gpointer user_data)
{
	struct characteristic_data *char_data = user_data;
	struct att_data_list *list;
	int i;

	if (status == ATT_ECODE_ATTR_NOT_FOUND &&
				char_data->start != char_data->orig_start)
        {
		printf("# TODO case in char_read_by_uuid_cb\n");
		goto done;
        }

	if (status != 0) {
		resp_error(err_COMM_ERR); // Todo: status
		goto done;
	}

	list = dec_read_by_type_resp(pdu, plen);

	resp_begin(rsp_READ);
        if (list == NULL)
		goto nolist;

	for (i = 0; i < list->num; i++) {
		uint8_t *value = list->data[i];
		int j;

		char_data->start = att_get_u16(value) + 1;

		send_uint(tag_HANDLE, att_get_u16(value));
                send_data(value+2, list->len-2); // All the same length??
	}

	att_data_list_free(list);
nolist:
	resp_end();

done:
	g_free(char_data);
}
예제 #13
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);
}
예제 #14
0
static void char_read_by_uuid_cb(guint8 status, const guint8 *pdu,
                                 guint16 plen, gpointer user_data)
{
    struct characteristic_data *char_data = user_data;
    struct att_data_list *list;
    int i;

    if (status == ATT_ECODE_ATTR_NOT_FOUND &&
            char_data->start != char_data->orig_start)
        goto done;

    if (status != 0) {
        printf("Read characteristics by UUID failed: %s\n",
               att_ecode2str(status));
        goto done;
    }

    list = dec_read_by_type_resp(pdu, plen);
    if (list == NULL)
        goto done;

    for (i = 0; i < list->num; i++) {
        uint8_t *value = list->data[i];
        int j;

        char_data->start = att_get_u16(value) + 1;

        printf("\nhandle: 0x%04x \t value: ", att_get_u16(value));
        value += 2;
        for (j = 0; j < list->len - 2; j++, value++)
            printf("%02x ", *value);
        printf("\n");
    }

    att_data_list_free(list);

done:
    printf("\n%s", get_prompt());
    fflush(stdout);

    g_free(char_data);
}
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);
}
예제 #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 = 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);
}
예제 #17
0
static void find_included_cb(uint8_t status, const uint8_t *pdu, uint16_t len,
							gpointer user_data)
{
	struct included_discovery *isd = user_data;
	uint16_t last_handle = isd->end_handle;
	unsigned int err = status;
	struct att_data_list *list;
	int i;

	if (err == ATT_ECODE_ATTR_NOT_FOUND)
		err = 0;

	if (status)
		goto done;

	list = dec_read_by_type_resp(pdu, len);
	if (list == NULL) {
		err = ATT_ECODE_IO;
		goto done;
	}

	if (list->len != 6 && list->len != 8) {
		err = ATT_ECODE_IO;
		att_data_list_free(list);
		goto done;
	}

	for (i = 0; i < list->num; i++) {
		struct gatt_included *incl;

		incl = included_from_buf(list->data[i], list->len);
		last_handle = incl->handle;

		/* 128 bit UUID, needs resolving */
		if (list->len == 6) {
			resolve_included_uuid(isd, incl);
			continue;
		}

		isd->includes = g_slist_append(isd->includes, incl);
	}

	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_handle < isd->start_handle) {
		isd->err = ATT_ECODE_UNLIKELY;
		goto done;
	}

	isd->start_handle = last_handle + 1;

	if (last_handle < isd->end_handle)
		find_included(isd, isd->start_handle);

done:
	if (isd->err == 0)
		isd->err = err;
}
예제 #18
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);
}
예제 #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);
}
예제 #20
0
파일: client.c 프로젝트: richardxu/panda-a4
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);
}
예제 #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;

	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);
}
예제 #22
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);
}
예제 #23
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");
}