Beispiel #1
0
static DBusMessage *media_folder_list_items(DBusConnection *conn,
						DBusMessage *msg, void *data)
{
	struct media_player *mp = data;
	struct media_folder *folder = mp->scope;
	struct player_callback *cb = mp->cb;
	DBusMessageIter iter;
	uint32_t start, end;
	int err;

	dbus_message_iter_init(msg, &iter);

	if (parse_filters(mp, &iter, &start, &end) < 0)
		return btd_error_invalid_args(msg);

	if (cb->cbs->list_items == NULL)
		return btd_error_not_supported(msg);

	if (folder->msg != NULL)
		return btd_error_failed(msg, strerror(EBUSY));

	err = cb->cbs->list_items(mp, folder->item->name, start, end,
							cb->user_data);
	if (err < 0)
		return btd_error_failed(msg, strerror(-err));

	folder->msg = dbus_message_ref(msg);

	return NULL;
}
static DBusMessage *create_gatt_dbus_error(DBusMessage *msg, uint8_t att_ecode)
{
	switch (att_ecode) {
	case BT_ATT_ERROR_READ_NOT_PERMITTED:
		return btd_error_not_permitted(msg, "Read not permitted");
	case BT_ATT_ERROR_WRITE_NOT_PERMITTED:
		return btd_error_not_permitted(msg, "Write not permitted");
	case BT_ATT_ERROR_AUTHENTICATION:
	case BT_ATT_ERROR_INSUFFICIENT_ENCRYPTION:
	case BT_ATT_ERROR_INSUFFICIENT_ENCRYPTION_KEY_SIZE:
		return btd_error_not_permitted(msg, "Not paired");
	case BT_ATT_ERROR_INVALID_OFFSET:
		return btd_error_invalid_args_str(msg, "Invalid offset");
	case BT_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN:
		return btd_error_invalid_args_str(msg, "Invalid Length");
	case BT_ATT_ERROR_AUTHORIZATION:
		return btd_error_not_authorized(msg);
	case BT_ATT_ERROR_REQUEST_NOT_SUPPORTED:
		return btd_error_not_supported(msg);
	case 0:
		return btd_error_failed(msg, "Operation failed");
	default:
		return g_dbus_create_error(msg, ERROR_INTERFACE,
				"Operation failed with ATT error: 0x%02x",
				att_ecode);
	}

	return NULL;
}
Beispiel #3
0
static DBusMessage *media_folder_search(DBusConnection *conn, DBusMessage *msg,
								void *data)
{
	struct media_player *mp = data;
	struct media_folder *folder = mp->scope;
	struct player_callback *cb = mp->cb;
	DBusMessageIter iter;
	const char *string;
	int err;

	dbus_message_iter_init(msg, &iter);

	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
		return btd_error_invalid_args(msg);

	dbus_message_iter_get_basic(&iter, &string);

	if (!mp->searchable || folder != mp->folder || !cb->cbs->search)
		return btd_error_not_supported(msg);

	if (folder->msg != NULL)
		return btd_error_failed(msg, strerror(EINVAL));

	err = cb->cbs->search(mp, string, cb->user_data);
	if (err < 0)
		return btd_error_failed(msg, strerror(-err));

	folder->msg = dbus_message_ref(msg);

	return NULL;
}
Beispiel #4
0
/*
 * Input Device methods
 */
static DBusMessage *input_device_connect(DBusConnection *conn,
					DBusMessage *msg, void *data)
{
	struct input_device *idev = data;
	struct input_conn *iconn;
	DBusMessage *reply;
	GError *err = NULL;

	DBG("idev %p", idev);

	iconn = find_connection(idev->connections, HID_UUID);
	if (!iconn)
		return btd_error_not_supported(msg);

	if (iconn->pending_connect)
		return btd_error_in_progress(msg);

	if (is_connected(iconn))
		return btd_error_already_connected(msg);

	iconn->pending_connect = dbus_message_ref(msg);

	dev_connect(idev, iconn, &err);

	if (err == NULL)
		return NULL;

	error("%s", err->message);
	dbus_message_unref(iconn->pending_connect);
	iconn->pending_connect = NULL;
	reply = btd_error_failed(msg, err->message);
	g_error_free(err);
	return reply;
}
Beispiel #5
0
static DBusMessage *register_player(DBusConnection *conn, DBusMessage *msg,
					void *data)
{
	struct media_adapter *adapter = data;
	struct media_player *mp;
	DBusMessageIter args;
	const char *sender, *path;
	int err;

	sender = dbus_message_get_sender(msg);

	dbus_message_iter_init(msg, &args);

	dbus_message_iter_get_basic(&args, &path);
	dbus_message_iter_next(&args);

	if (media_adapter_find_player(adapter, sender, path) != NULL)
		return btd_error_already_exists(msg);

	mp = media_player_create(adapter, sender, path, &err);
	if (mp == NULL) {
		if (err == -EPROTONOSUPPORT)
			return btd_error_not_supported(msg);
		else
			return btd_error_invalid_args(msg);
	}

	if (parse_player_properties(mp, &args) == FALSE) {
		media_player_destroy(mp);
		return btd_error_invalid_args(msg);
	}

	return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
}
static void controlpoint_method_reply(struct controlpoint_req *req,
								uint8_t code)
{
	DBusMessage *reply;

	switch (code) {
	case RSP_SUCCESS:
		reply = dbus_message_new_method_return(req->msg);
		break;
	case RSP_NOT_SUPPORTED:
		reply = btd_error_not_supported(req->msg);
		break;
	case RSP_INVALID_PARAM:
		reply = btd_error_invalid_args(req->msg);
		break;
	case RSP_FAILED:
		reply = btd_error_failed(req->msg, "Failed");
		break;
	default:
		reply = btd_error_failed(req->msg, "Unknown error");
		break;
	}

	g_dbus_send_message(btd_get_dbus_connection(), reply);

	dbus_message_unref(req->msg);
}
Beispiel #7
0
static DBusMessage *set_indicating(DBusConnection *conn, DBusMessage *msg,
			DBusMessageIter *iter, struct characteristic *chr)
{
	struct gatt_service *gatt = chr->gatt;
	DBusMessageIter sub;
	dbus_bool_t indicating;
	uint8_t value[2];
	int len = 2;
	struct write_val_op *op;

	INFO("set_indicating");

	if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_BOOLEAN)
		return btd_error_invalid_args(msg);

	dbus_message_iter_get_basic(iter, &indicating);

	if (chr->ccc_handle == 0) /* Error if char does not have a ccc */
		return btd_error_not_supported(msg);

	if ((chr->perm & GATT_CHAR_PROPS_INDICATE) == 0) /* Error if char permissions do not allow indicating */
		return btd_error_not_supported(msg);

	if (indicating) { /* we do not allow notification + indicating at the same time */
		chr->client_config = chr->client_config | GATT_CHAR_CLIENTCONF_INDICATE;
		chr->client_config = chr->client_config & ~GATT_CHAR_CLIENTCONF_NOTIFY;
	} else {
		chr->client_config = chr->client_config & ~GATT_CHAR_CLIENTCONF_INDICATE;
	}

	value[0] = chr->client_config & 0xFF;
	value[1] = 0;
	INFO("value[0]=%02X",chr->client_config);

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

	gatt_write_cmd(chr->gatt->attrib, chr->ccc_handle, (uint8_t*)value, len, set_indicating_cb, op);

	return dbus_message_new_method_return(msg);
}
Beispiel #8
0
static DBusMessage *set_broadcasting(DBusConnection *conn, DBusMessage *msg,
			DBusMessageIter *iter, struct characteristic *chr)
{
	struct gatt_service *gatt = chr->gatt;
	DBusMessageIter sub;
	dbus_bool_t broadcasting;
	uint8_t value[2];
	int len = 2;
	struct write_val_op *op;

	INFO("set_broadcasting");

	if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_BOOLEAN)
		return btd_error_invalid_args(msg);

	dbus_message_iter_get_basic(iter, &broadcasting);

	if (chr->scc_handle == 0) /* Error if char does not have a ccc */
		return btd_error_not_supported(msg);

	if ((chr->perm & GATT_CHAR_PROPS_BROADCAST) == 0) /* Error if char permissions do not allow broadcasting */
		return btd_error_not_supported(msg);

	if (broadcasting) {
		chr->server_config = chr->server_config | GATT_CHAR_SERVERCONF_BROADCAST;
	} else {
		chr->server_config = chr->server_config & ~GATT_CHAR_SERVERCONF_BROADCAST;
	}

	value[0] = chr->server_config & 0xFF;
	value[1] = 0;

	op = g_new0(struct write_val_op, 1);
	op->msg = 0;
	op->conn = conn;
	op->chr = chr;
	INFO("value[0]=%02X",chr->server_config);


	gatt_write_cmd(chr->gatt->attrib, chr->scc_handle, (uint8_t*)value, len, set_broadcasting_cb, op);

	return dbus_message_new_method_return(msg);
}
Beispiel #9
0
static DBusMessage *media_folder_change_folder(DBusConnection *conn,
						DBusMessage *msg, void *data)
{
	struct media_player *mp = data;
	struct media_folder *folder = mp->scope;
	struct player_callback *cb = mp->cb;
	const char *path;
	int err;

	if (!dbus_message_get_args(msg, NULL,
					DBUS_TYPE_OBJECT_PATH, &path,
					DBUS_TYPE_INVALID))
		return btd_error_invalid_args(msg);

	if (folder->msg != NULL)
		return btd_error_failed(msg, strerror(EBUSY));

	folder = media_player_find_folder(mp, path);
	if (folder == NULL)
		return btd_error_invalid_args(msg);

	if (mp->scope == folder)
		return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);

	if (folder == mp->playlist || folder == mp->folder ||
						folder == mp->search) {
		media_player_change_scope(mp, folder);
		return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
	}

	/*
	 * ChangePath can only navigate one level up/down so check if folder
	 * is direct child or parent of the current folder otherwise fail.
	 */
	if (!g_slist_find(mp->folder->subfolders, folder) &&
				!g_slist_find(folder->subfolders, mp->folder))
		return btd_error_invalid_args(msg);

	if (cb->cbs->change_folder == NULL)
		return btd_error_not_supported(msg);

	err = cb->cbs->change_folder(mp, folder->item->name, folder->item->uid,
								cb->user_data);
	if (err < 0)
		return btd_error_failed(msg, strerror(-err));

	mp->scope->msg = dbus_message_ref(msg);

	return NULL;
}
Beispiel #10
0
static DBusMessage *port_connect(DBusConnection *conn,
					DBusMessage *msg, void *user_data)
{
	struct serial_device *device = user_data;
	struct serial_port *port;
	const char *pattern;
	int err;

	if (dbus_message_has_member(msg, "ConnectFD") && DBUS_TYPE_UNIX_FD < 0)
		return btd_error_not_supported(msg);

	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &pattern,
						DBUS_TYPE_INVALID) == FALSE)
		return NULL;

	port = find_port(device->ports, pattern);
	if (!port) {
		char *endptr = NULL;
		int channel;

		channel = strtol(pattern, &endptr, 10);
		if ((endptr && *endptr != '\0') || channel < 1 || channel > 30)
			return btd_error_does_not_exist(msg);

		port = create_port(device, NULL, channel);
	}

	if (port->listener_id)
		return btd_error_failed(msg, "Port already in use");

	port->listener_id = g_dbus_add_disconnect_watch(conn,
						dbus_message_get_sender(msg),
						port_owner_exited, port,
						NULL);

	port->msg = dbus_message_ref(msg);

	err = connect_port(port);
	if (err < 0) {
		error("%s", strerror(-err));
		g_dbus_remove_watch(conn, port->listener_id);
		port->listener_id = 0;

		return btd_error_failed(msg, strerror(-err));
	}

	return NULL;
}
Beispiel #11
0
static DBusMessage *media_player_rewind(DBusConnection *conn, DBusMessage *msg,
								void *data)
{
	struct media_player *mp = data;
	struct player_callback *cb = mp->cb;
	int err;

	if (cb->cbs->rewind == NULL)
		return btd_error_not_supported(msg);

	err = cb->cbs->rewind(mp, cb->user_data);
	if (err < 0)
		return btd_error_failed(msg, strerror(-err));

	return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
}
Beispiel #12
0
/* Connect and initiate BNEP session */
static DBusMessage *connection_connect(DBusConnection *conn,
						DBusMessage *msg, void *data)
{
	struct network_peer *peer = data;
	struct network_conn *nc;
	const char *svc;
	uint16_t id;
	GError *err = NULL;

	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &svc,
						DBUS_TYPE_INVALID) == FALSE)
		return NULL;

	id = bnep_service_id(svc);
	nc = find_connection(peer->connections, id);
	if (!nc)
		return btd_error_not_supported(msg);

	if (nc->state != DISCONNECTED)
		return btd_error_already_connected(msg);

	nc->io = bt_io_connect(BT_IO_L2CAP, connect_cb, nc,
				NULL, &err,
				BT_IO_OPT_SOURCE_BDADDR, &peer->src,
				BT_IO_OPT_DEST_BDADDR, &peer->dst,
				BT_IO_OPT_PSM, BNEP_PSM,
				BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
				BT_IO_OPT_OMTU, BNEP_MTU,
				BT_IO_OPT_IMTU, BNEP_MTU,
				BT_IO_OPT_INVALID);
	if (!nc->io) {
		DBusMessage *reply;
		error("%s", err->message);
		reply = btd_error_failed(msg, err->message);
		g_error_free(err);
		return reply;
	}

	nc->state = CONNECTING;
	nc->msg = dbus_message_ref(msg);
	nc->watch = g_dbus_add_disconnect_watch(conn,
						dbus_message_get_sender(msg),
						connection_destroy,
						nc, NULL);

	return NULL;
}
Beispiel #13
0
static DBusMessage *media_item_play(DBusConnection *conn, DBusMessage *msg,
								void *data)
{
	struct media_item *item = data;
	struct media_player *mp = item->player;
	struct player_callback *cb = mp->cb;
	int err;

	if (!item->playable || !cb->cbs->play_item)
		return btd_error_not_supported(msg);

	err = cb->cbs->play_item(mp, item->path, item->uid, cb->user_data);
	if (err < 0)
		return btd_error_failed(msg, strerror(-err));

	return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
}
Beispiel #14
0
static DBusMessage *key_pressed(DBusConnection *conn, DBusMessage *msg,
						uint8_t op, void *data)
{
	struct control *control = data;
	int err;

	if (!control->session)
		return btd_error_not_connected(msg);

	if (!control->target)
		return btd_error_not_supported(msg);

	err = avctp_send_passthrough(control->session, op);
	if (err < 0)
		return btd_error_failed(msg, strerror(-err));

	return dbus_message_new_method_return(msg);
}
Beispiel #15
0
static DBusMessage *volume_down(DBusConnection *conn, DBusMessage *msg,
								void *data)
{
	struct audio_device *device = data;
	struct control *control = device->control;
	int err;

	if (!control->session)
		return btd_error_not_connected(msg);

	if (!control->target)
		return btd_error_not_supported(msg);

	err = avctp_send_passthrough(control->session, VOL_DOWN_OP);
	if (err < 0)
		return btd_error_failed(msg, strerror(-err));

	return dbus_message_new_method_return(msg);
}
Beispiel #16
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;
}
Beispiel #17
0
static DBusMessage *register_endpoint(DBusConnection *conn, DBusMessage *msg,
					void *data)
{
	struct media_adapter *adapter = data;
	DBusMessageIter args, props;
	const char *sender, *path, *uuid;
	gboolean delay_reporting = FALSE;
	uint8_t codec;
	uint8_t *capabilities;
	int size = 0;
	int err;

	sender = dbus_message_get_sender(msg);

	dbus_message_iter_init(msg, &args);

	dbus_message_iter_get_basic(&args, &path);
	dbus_message_iter_next(&args);

	if (media_adapter_find_endpoint(adapter, sender, path, NULL) != NULL)
		return btd_error_already_exists(msg);

	dbus_message_iter_recurse(&args, &props);
	if (dbus_message_iter_get_arg_type(&props) != DBUS_TYPE_DICT_ENTRY)
		return btd_error_invalid_args(msg);

	if (parse_properties(&props, &uuid, &delay_reporting, &codec,
						&capabilities, &size) < 0)
		return btd_error_invalid_args(msg);

	if (media_endpoint_create(adapter, sender, path, uuid, delay_reporting,
				codec, capabilities, size, &err) == NULL) {
		if (err == -EPROTONOSUPPORT)
			return btd_error_not_supported(msg);
		else
			return btd_error_invalid_args(msg);
	}

	return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
}
Beispiel #18
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);
}
Beispiel #19
0
static DBusMessage *local_connect(DBusConnection *conn,
						DBusMessage *msg, void *data)
{
	struct network_peer *peer = data;
	struct btd_service *service;
	struct network_conn *nc;
	const char *svc;
	const char *uuid;
	uint16_t id;
	int err;

	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &svc,
						DBUS_TYPE_INVALID) == FALSE)
		return btd_error_invalid_args(msg);

	id = bnep_service_id(svc);
	uuid = bnep_uuid(id);

	if (uuid == NULL)
		return btd_error_invalid_args(msg);

	service = btd_device_get_service(peer->device, uuid);
	if (service == NULL)
		return btd_error_not_supported(msg);

	nc = btd_service_get_user_data(service);

	if (nc->connect != NULL)
		return btd_error_busy(msg);

	err = connection_connect(nc->service);
	if (err < 0)
		return btd_error_failed(msg, strerror(-err));

	nc->connect = dbus_message_ref(msg);

	return NULL;
}
static DBusMessage *characteristic_write_value(DBusConnection *conn,
					DBusMessage *msg, void *user_data)
{
	struct characteristic *chrc = user_data;
	struct bt_gatt_client *gatt = chrc->service->client->gatt;
	uint8_t *value = NULL;
	size_t value_len = 0;
	bool supported = false;

	if (chrc->write_id)
		return btd_error_in_progress(msg);

	if (!parse_value_arg(msg, &value, &value_len))
		return btd_error_invalid_args(msg);

	/*
	 * Decide which write to use based on characteristic properties. For now
	 * we don't perform signed writes since gatt-client doesn't support them
	 * and the user can always encrypt the through pairing. The procedure to
	 * use is determined based on the following priority:
	 *
	 *   * "reliable-write" property set -> reliable long-write.
	 *   * "write" property set -> write request.
	 *     - If value is larger than MTU - 3: long-write
	 *   * "write-without-response" property set -> write command.
	 */
	if ((chrc->ext_props & BT_GATT_CHRC_EXT_PROP_RELIABLE_WRITE)) {
		supported = true;
		chrc->write_id = start_long_write(msg, chrc->value_handle, gatt,
						true, value, value_len,
						chrc, chrc_write_complete);
		if (chrc->write_id)
			return NULL;
	}

	if (chrc->props & BT_GATT_CHRC_PROP_WRITE) {
		uint16_t mtu;

		supported = true;
		mtu = bt_gatt_client_get_mtu(gatt);
		if (!mtu)
			return btd_error_failed(msg, "No ATT transport");

		if (value_len <= (unsigned) mtu - 3)
			chrc->write_id = start_write_request(msg,
						chrc->value_handle,
						gatt, value, value_len,
						chrc, chrc_write_complete);
		else
			chrc->write_id = start_long_write(msg,
						chrc->value_handle, gatt,
						false, value, value_len,
						chrc, chrc_write_complete);

		if (chrc->write_id)
			return NULL;
	}

	if (!(chrc->props & BT_GATT_CHRC_PROP_WRITE_WITHOUT_RESP))
		goto fail;

	supported = true;
	chrc->write_id = bt_gatt_client_write_without_response(gatt,
							chrc->value_handle,
							false, value,
							value_len);
	if (chrc->write_id)
		return dbus_message_new_method_return(msg);

fail:
	if (supported)
		return btd_error_failed(msg, "Failed to initiate write");

	return btd_error_not_supported(msg);
}
Beispiel #21
0
/*
 * Input Device methods
 */
static DBusMessage *input_device_connect(DBusConnection *conn,
					DBusMessage *msg, void *data)
{
//+++ BRCM
#ifdef BT_ALT_STACK
	struct input_device *idev = data;
	tDTUN_DEVICE_METHOD method;

	method.hh_open.hdr.id = DTUN_METHOD_HH_OPEN;
	method.hh_open.hdr.len = sizeof(tDTUN_METHOD_HH_OPEN) - sizeof(tDTUN_HDR);
	memcpy(&method.hh_open.bdaddr, &idev->dst, 6);
	read_remote_class(&idev->src, &idev->dst, &method.hh_open.cod);

	dtun_client_call_method(&method);
	return NULL;
#else
	struct input_device *idev = data;
	struct input_conn *iconn;
	struct fake_input *fake;
	DBusMessage *reply;
	GError *err = NULL;

	iconn = find_connection(idev->connections, "HID");
	if (!iconn)
		return btd_error_not_supported(msg);

	if (iconn->pending_connect)
		return btd_error_in_progress(msg);

	if (is_connected(iconn))
		return btd_error_already_connected(msg);

	iconn->pending_connect = dbus_message_ref(msg);
	fake = iconn->fake;

	if (fake) {
		/* Fake input device */
		if (fake->connect(iconn, &err))
			fake->flags |= FI_FLAG_CONNECTED;
	} else {
		/* HID devices */
		GIOChannel *io;

		io = bt_io_connect(BT_IO_L2CAP, control_connect_cb, iconn,
					NULL, &err,
					BT_IO_OPT_SOURCE_BDADDR, &idev->src,
					BT_IO_OPT_DEST_BDADDR, &idev->dst,
					BT_IO_OPT_PSM, L2CAP_PSM_HIDP_CTRL,
					BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
					BT_IO_OPT_POWER_ACTIVE, 0,
					BT_IO_OPT_INVALID);
		iconn->ctrl_io = io;
	}

	if (err == NULL)
		return NULL;

	error("%s", err->message);
	dbus_message_unref(iconn->pending_connect);
	iconn->pending_connect = NULL;
	reply = btd_error_failed(msg, err->message);
	g_error_free(err);
	return reply;
#endif
//--- BRCM
}
Beispiel #22
0
static DBusMessage *characteristic_start_notify(DBusConnection *conn,
					DBusMessage *msg, void *user_data)
{
	struct characteristic *chrc = user_data;
	struct bt_gatt_client *gatt = chrc->service->client->gatt;
	const char *sender = dbus_message_get_sender(msg);
	struct async_dbus_op *op;
	struct notify_client *client;

	if (!(chrc->props & BT_GATT_CHRC_PROP_NOTIFY ||
				chrc->props & BT_GATT_CHRC_PROP_INDICATE))
		return btd_error_not_supported(msg);

	/* Each client can only have one active notify session. */
	client = queue_find(chrc->notify_clients, match_notify_sender, sender);
	if (client)
		return client->notify_id ?
				btd_error_failed(msg, "Already notifying") :
				btd_error_in_progress(msg);

	client = notify_client_create(chrc, sender);
	if (!client)
		return btd_error_failed(msg, "Failed allocate notify session");

	queue_push_tail(chrc->notify_clients, client);
	queue_push_tail(chrc->service->client->all_notify_clients, client);

	/*
	 * If the device is currently not connected, return success. We will
	 * automatically try and register all clients when a GATT client becomes
	 * ready.
	 */
	if (!gatt) {
		DBusMessage *reply;

		reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
		if (reply)
			return reply;

		/*
		 * Clean up and respond with an error instead of timing out to
		 * avoid any ambiguities.
		 */
		error("Failed to construct D-Bus message reply");
		goto fail;
	}

	op = new0(struct async_dbus_op, 1);
	op->data = client;
	op->msg = dbus_message_ref(msg);

	client->notify_id = bt_gatt_client_register_notify(gatt,
						chrc->value_handle,
						register_notify_cb, notify_cb,
						op, async_dbus_op_free);
	if (client->notify_id)
		return NULL;

	async_dbus_op_free(op);

fail:
	queue_remove(chrc->notify_clients, client);
	queue_remove(chrc->service->client->all_notify_clients, client);

	/* Directly free the client */
	notify_client_free(client);

	return btd_error_failed(msg, "Failed to register notify session");
}