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);
}
Exemple #2
0
static void cmd_char_write_common(int argcp, char **argvp, int with_response)
{
	uint8_t *value;
	size_t plen;
	int handle;

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

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

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

	plen = gatt_attr_data_from_string(argvp[2], &value);
	if (plen == 0) {
		resp_error(err_BAD_PARAM);
		return;
	}

	if (with_response)
		gatt_write_char(attrib, handle, value, plen,
					char_write_req_cb, NULL);
	else
        {
		gatt_write_char(attrib, handle, value, plen, NULL, NULL);
                resp_begin(rsp_WRITE);
                resp_end();
        }

	g_free(value);
}
static void read_supported_locations(struct csc *csc)
{
	struct controlpoint_req *req;

	req = g_new0(struct controlpoint_req, 1);
	req->csc = csc;
	req->opcode = REQUEST_SUPPORTED_SENSOR_LOC;

	csc->pending_req = req;

	gatt_write_char(csc->attrib, csc->controlpoint_val_handle,
					&req->opcode, sizeof(req->opcode),
					controlpoint_write_cb, req);
}
Exemple #4
0
static void set_report(struct uhid_event *ev, void *user_data)
{
	struct hog_device *hogdev = user_data;
	struct report *report;
	void *data;
	int size;
	int err;

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

	hogdev->setrep_id = ev->u.set_report.id;

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

	data = ev->u.set_report.data;
	size = ev->u.set_report.size;
	if (hogdev->has_report_id && size > 0) {
		data++;
		--size;
	}

	DBG("Sending report type %d ID %d to handle 0x%X", report->type,
				report->id, report->decl->value_handle);

	if (hogdev->attrib == NULL)
		return;

	hogdev->setrep_att = gatt_write_char(hogdev->attrib,
						report->decl->value_handle,
						data, size, set_report_cb,
						hogdev);
	if (!hogdev->setrep_att) {
		err = ENOMEM;
		goto fail;
	}

	return;
fail:
	/* cancel the request on failure */
	set_report_cb(err, NULL, 0, hogdev);
}
Exemple #5
0
static void write_char(struct bt_bas *bas, GAttrib *attrib, uint16_t handle,
					const uint8_t *value, size_t vlen,
					GAttribResultFunc func,
					gpointer user_data)
{
	struct gatt_request *req;
	unsigned int id;

	req = create_request(bas, user_data);

	id = gatt_write_char(attrib, handle, value, vlen, func, req);

	set_and_store_gatt_req(bas, req, id);
}
Exemple #6
0
static void cmd_char_write(int argcp, char **argvp)
{
	uint8_t *value;
	size_t plen;
	int handle;

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

	if (argcp < 3) {
		printf("Usage: %s <handle> <new value>\n", argvp[0]);
		return;
	}

	handle = strtohandle(argvp[1]);
	if (handle <= 0) {
		printf("A valid handle is required\n");
		return;
	}

	plen = gatt_attr_data_from_string(argvp[2], &value);
	if (plen == 0) {
		g_printerr("Invalid value\n");
		return;
	}

	if (g_strcmp0("char-write-req", argvp[0]) == 0)
		gatt_write_char(g_connection->attrib, handle, value, plen,
					char_write_req_cb, NULL);
	else
		gatt_write_char(g_connection->attrib, handle, value, plen, NULL, NULL);

	g_free(value);
}
static void write_char(struct bt_scpp *scan, GAttrib *attrib, uint16_t handle,
					const uint8_t *value, size_t vlen,
					GAttribResultFunc func,
					gpointer user_data)
{
	unsigned int id;

	id = gatt_write_char(attrib, handle, value, vlen, func, user_data);

	if (queue_push_head(scan->gatt_op, UINT_TO_PTR(id)))
		return;

	error("scpp: Could not read char");
	g_attrib_cancel(attrib, id);
}
Exemple #8
0
static void forward_report(struct uhid_event *ev, void *user_data)
{
	struct bt_hog *hog = user_data;
	struct report *report;
	GSList *l;
	void *data;
	int size;
	guint type;

	if (hog->has_report_id) {
		data = ev->u.output.data + 1;
		size = ev->u.output.size - 1;
	} else {
		data = ev->u.output.data;
		size = ev->u.output.size;
	}

	switch (ev->type) {
	case UHID_OUTPUT:
		type = HOG_REPORT_TYPE_OUTPUT;
		break;
	case UHID_FEATURE:
		type = HOG_REPORT_TYPE_FEATURE;
		break;
	default:
		return;
	}

	l = g_slist_find_custom(hog->reports, GUINT_TO_POINTER(type),
							report_type_cmp);
	if (!l)
		return;

	report = l->data;

	DBG("Sending report type %d to handle 0x%X", type,
						report->decl->value_handle);

	if (hog->attrib == NULL)
		return;

	if (report->decl->properties & GATT_CHR_PROP_WRITE)
		gatt_write_char(hog->attrib, report->decl->value_handle,
				data, size, output_written_cb, hog);
	else if (report->decl->properties & GATT_CHR_PROP_WRITE_WITHOUT_RESP)
		gatt_write_cmd(hog->attrib, report->decl->value_handle,
						data, size, NULL, NULL);
}
Exemple #9
0
static void enable_measurement(gpointer data, gpointer user_data)
{
	struct heartrate *hr = data;
	uint16_t handle = hr->measurement_ccc_handle;
	uint8_t value[2];
	char *msg;

	if (hr->attrib == NULL || !handle)
		return;

	att_put_u16(GATT_CLIENT_CHARAC_CFG_NOTIF_BIT, value);
	msg = g_strdup("Enable measurement");

	gatt_write_char(hr->attrib, handle, value, sizeof(value),
							char_write_cb, msg);
}
Exemple #10
0
static void disable_measurement(gpointer data, gpointer user_data)
{
	struct heartrate *hr = data;
	uint16_t handle = hr->measurement_ccc_handle;
	uint8_t value[2];
	char *msg;

	if (hr->attrib == NULL || !handle)
		return;

	att_put_u16(0x0000, value);
	msg = g_strdup("Disable measurement");

	gatt_write_char(hr->attrib, handle, value, sizeof(value),
							char_write_cb, msg);
}
Exemple #11
0
int gattlib_write_char_by_handle(gatt_connection_t* connection, uint16_t handle, void* buffer, size_t buffer_len) {
	int write_completed = FALSE;

	guint ret = gatt_write_char(connection->attrib, handle, buffer, buffer_len,
								gattlib_write_result_cb, &write_completed);
	if (ret == 0) {
		return 1;
	}

	// Wait for completion of the event
	while(write_completed == FALSE) {
		g_main_context_iteration(g_gattlib_thread.loop_context, FALSE);
	}

	return 0;
}
Exemple #12
0
static void discover_descriptor_cb(uint8_t status, GSList *descs,
								void *user_data)
{
	struct scan *scan = user_data;
	struct gatt_desc *desc;
	uint8_t value[2];

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

	/* There will be only one descriptor on list and it will be CCC */
	desc = descs->data;

	put_le16(GATT_CLIENT_CHARAC_CFG_NOTIF_BIT, value);
	gatt_write_char(scan->attrib, desc->handle, value, sizeof(value),
						ccc_written_cb, user_data);
}
Exemple #13
0
static void cmd_anki_vehicle_lights_pattern(int argcp, char **argvp)
{
        uint8_t *value;
        size_t plen;
        int handle;

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

        if (argcp < 6) {
                rl_printf("Usage: %s <channel> <effect> <start> <end> <cycles_per_min>\n", argvp[0]);
                rl_printf("  channels: RED, TAIL, BLUE, GREEN, FRONTL, FRONTR\n");
                rl_printf("   effects: STEADY, FADE, THROB, FLASH, RANDOM\n");
                return;
        }

        handle = vehicle.write_char.value_handle;

        uint8_t channel = get_channel_by_name(argvp[1]);
        if (channel == channel_invalid) {
            rl_printf("Unrecognized channel: %s\n", argvp[1]);
            return;
        } 

        uint8_t effect = get_effect_by_name(argvp[2]);
        if (effect == effect_invalid) {
            rl_printf("Unrecognized channel: %s\n", argvp[2]); 
            return;
        }

        uint8_t start = atoi(argvp[3]);
        uint8_t end = atoi(argvp[4]);
        uint16_t cycles_per_min = atoi(argvp[5]);

        anki_vehicle_msg_t msg;
        plen = anki_vehicle_msg_lights_pattern(&msg, channel, effect, start, end, cycles_per_min);
        value = (uint8_t *)&msg;

        gatt_write_char(attrib, handle, value, plen, NULL, NULL);
}
Exemple #14
0
static DBusMessage *write_val(DBusConnection *conn,
					DBusMessage *msg, void *data)
{
	DBusMessage *reply;
	struct characteristic *chr = data;
	struct gatt_service *gatt = chr->gatt;
	char* value;
	char* write_method;
	uint16_t len = 0;
	uint16_t offset = 0;
	uint16_t timeout = 0;
	guint retvalue = 0;
	struct write_val_op *op;

	if (!dbus_message_get_args(msg, NULL,
			DBUS_TYPE_ARRAY,DBUS_TYPE_BYTE, &value, &len,
			DBUS_TYPE_STRING, &write_method,
			DBUS_TYPE_UINT16, &offset,
			DBUS_TYPE_UINT16, &timeout,
			DBUS_TYPE_INVALID))
		return btd_error_invalid_args(msg);

	DBG("WriteValue");// chr=%s value[0]=%d len=%d write_method=%s offset=%d timeout=%d",chr->path, value[0], len, write_method, offset, timeout);

	op = g_new0(struct write_val_op, 1);
	op->msg = dbus_message_ref(msg);
	op->conn = conn;
	op->chr = chr;

	if (g_str_equal("WriteWithResponse", write_method)) {
		INFO("write with response");
		retvalue = gatt_write_char(chr->gatt->attrib, chr->handle, (uint8_t*)value, len, write_req_cb, op);
	} else if (g_str_equal("WriteWithoutResponse", write_method)) {
		INFO("write without response");
		retvalue = gatt_write_cmd(chr->gatt->attrib, chr->handle, (uint8_t*)value, len, write_cmd_cb, op);
	} else {
		ERROR("write_method %s is not supported at the moment.",write_method);
		return btd_error_not_supported(msg);
	}
	return NULL;
}
static void exchange_mtu_cb(
	guint8 status,
	guint8 const* pdu,
	guint16 plen,
	gpointer user_data)
{
	uint16_t mtu;
	user_data_t* ud = static_cast<user_data_t*>(user_data);

	if (status != 0) {
		std::cout << "Exchange MTU Request failed: " << att_ecode2str(status) << std::endl;
		disconnect(ud->attrib, ud->chan);
		g_main_loop_quit(event_loop);
		return;
	}

	if (!dec_mtu_resp(pdu, plen, &mtu)) {
		std::cout << "Protocol error" << std::endl;
		disconnect(ud->attrib, ud->chan);
		g_main_loop_quit(event_loop);
		return;
	}

	mtu = std::min(mtu, ud->mtu);
	/* Set new value for MTU in client */
	if (g_attrib_set_mtu(ud->attrib, mtu)) {
		std::cout << "MTU was exchanged successfully:" << mtu << std::endl;
		gatt_write_char(
			ud->attrib,
			ud->handle,
			reinterpret_cast<uint8_t const*>(&ud->value),
			sizeof(ud->value),
			gatt_write_char_cb,
			nullptr);
	}
	else {
		std::cout << "Error exchanging MTU" << std::endl;
		disconnect(ud->attrib, ud->chan);
		g_main_loop_quit(event_loop);
	}
}
Exemple #16
0
static void write_char(struct bt_scpp *scan, GAttrib *attrib, uint16_t handle,
					const uint8_t *value, size_t vlen,
					GAttribResultFunc func,
					gpointer user_data)
{
	struct gatt_request *req;
	unsigned int id;

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

	id = gatt_write_char(attrib, handle, value, vlen, func, req);

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

	error("scpp: Could not read char");
	g_attrib_cancel(attrib, id);
	free(req);
}
Exemple #17
0
static void char_discovered_cb(GSList *characteristics, guint8 status,
							gpointer user_data)
{
	struct monitor *monitor = user_data;
	struct att_char *chr;
	uint8_t value = str2level(monitor->linklosslevel);

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

	DBG("Setting alert level \"%s\" on Reporter", monitor->linklosslevel);

	/* Assume there is a single Alert Level characteristic */
	chr = characteristics->data;
	monitor->linklosshandle = chr->value_handle;

	gatt_write_char(monitor->attrib, monitor->linklosshandle, &value, 1,
						linkloss_written, monitor);
}
Exemple #18
0
static int write_alert_level(struct monitor *monitor)
{
	struct att_range *linkloss = monitor->linkloss;
	bt_uuid_t uuid;

	if (monitor->linklosshandle) {
		uint8_t value = str2level(monitor->linklosslevel);

		gatt_write_char(monitor->attrib, monitor->linklosshandle,
					&value, 1, linkloss_written, monitor);
		return 0;
	}

	bt_uuid16_create(&uuid, ALERT_LEVEL_CHR_UUID);

	/* FIXME: use cache (requires service changed support) ? */
	gatt_discover_char(monitor->attrib, linkloss->start, linkloss->end,
					&uuid, char_discovered_cb, monitor);

	return 0;
}
static void discover_desc_cb(guint8 status, GSList *descs, gpointer user_data)
{
	struct characteristic *ch = user_data;
	struct gatt_desc *desc;
	uint8_t attr_val[2];
	char *msg = NULL;

	if (status != 0) {
		error("Discover %s descriptors failed: %s", ch->uuid,
							att_ecode2str(status));
		goto done;
	}

	/* There will be only one descriptor on list and it will be CCC */
	desc = descs->data;

	if (g_strcmp0(ch->uuid, CSC_MEASUREMENT_UUID) == 0) {
		ch->csc->measurement_ccc_handle = desc->handle;

		if (g_slist_length(ch->csc->cadapter->watchers) == 0) {
			put_le16(0x0000, attr_val);
			msg = g_strdup("Disable measurement");
		} else {
			put_le16(GATT_CLIENT_CHARAC_CFG_NOTIF_BIT,
							attr_val);
			msg = g_strdup("Enable measurement");
		}
	} else if (g_strcmp0(ch->uuid, SC_CONTROL_POINT_UUID) == 0) {
		put_le16(GATT_CLIENT_CHARAC_CFG_IND_BIT, attr_val);
		msg = g_strdup("Enable SC Control Point indications");
	} else {
		goto done;
	}

	gatt_write_char(ch->csc->attrib, desc->handle, attr_val,
					sizeof(attr_val), char_write_cb, msg);

done:
	g_free(ch);
}
Exemple #20
0
static DBusMessage *hrcp_reset(DBusConnection *conn, DBusMessage *msg,
								void *data)
{
	struct heartrate *hr = data;
	uint8_t value;
	char *vmsg;

	if (!hr->hrcp_val_handle)
		return btd_error_not_supported(msg);

	if (!hr->attrib)
		return btd_error_not_available(msg);

	value = 0x01;
	vmsg = g_strdup("Reset Control Point");
	gatt_write_char(hr->attrib, hr->hrcp_val_handle, &value,
					sizeof(value), char_write_cb, vmsg);

	DBG("Energy Expended Value has been reset");

	return dbus_message_new_method_return(msg);
}
static int cmd_char_write(gpointer user_data, const char *handle, const char* data, int type)
{
  GAttrib *attrib = user_data;
  uint8_t *value;
  size_t len;
  int hdl, ret;

  /* we need to enable notifications very early, as well change mode
   * when we receive an exception to quit
   */
  if ((get_state() != STATE_DATARCVD) && (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;
  }

  len = gatt_attr_data_from_string(data, &value);
  if (len == 0) {
    printf("Invalid value(s) passed\n");
    return -3;
  }

  if (type == WRITE_REQUEST) {
    ret = gatt_write_char(attrib, hdl, value, len, NULL, NULL);
  } else if (type == WRITE_COMMAND) {
    ret = gatt_write_cmd(attrib, hdl, value, len, NULL, NULL);
  }

  g_free(value);

  return 0;
}
Exemple #22
0
static void cmd_anki_vehicle_get_version(int argcp, char **argvp)
{
        uint8_t *value;
        size_t plen;
        int handle;
        
        if (conn_state != STATE_CONNECTED) {
                failed("Disconnected\n");
                return;
        }

        if (argcp < 1) {
                rl_printf("Usage: %s\n", argvp[0]);
                return;
        }

        handle = vehicle.write_char.value_handle;

        anki_vehicle_msg_t msg;
        plen = anki_vehicle_msg_get_version(&msg);
        value = (uint8_t *)&msg;

        gatt_write_char(attrib, handle, value, plen, NULL, NULL);
}