Example #1
0
gboolean avrcp_connect(struct audio_device *dev)
{
	struct control *control = dev->control;
	struct avctp *session;
	int err;

	if (control->session)
		return TRUE;

	session = avctp_get(&dev->src, &dev->dst);
	if (!session) {
		error("Unable to create new AVCTP session");
		return FALSE;
	}

	device_remove_control_timer(dev);

	session->dev = dev;
	session->state = AVCTP_STATE_CONNECTING;

	err = bt_l2cap_connect(&dev->src, &dev->dst, AVCTP_PSM, 0,
				avctp_connect_cb, session);
	if (err < 0) {
		avctp_unref(session);
		error("Connect failed. %s(%d)", strerror(-err), -err);
		return FALSE;
	}

	control->session = session;

	return TRUE;
}
Example #2
0
static void state_changed(struct btd_device *dev, avctp_state_t old_state,
				avctp_state_t new_state, void *user_data)
{
	struct control *control = user_data;
	DBusConnection *conn = btd_get_dbus_connection();
	const char *path = device_get_path(dev);

	switch (new_state) {
	case AVCTP_STATE_DISCONNECTED:
		control->session = NULL;

		g_dbus_emit_property_changed(conn, path,
					AUDIO_CONTROL_INTERFACE, "Connected");

		break;
	case AVCTP_STATE_CONNECTING:
		if (control->session)
			break;

		control->session = avctp_get(dev);

		break;
	case AVCTP_STATE_CONNECTED:
		g_dbus_emit_property_changed(conn, path,
					AUDIO_CONTROL_INTERFACE, "Connected");
		break;
	default:
		return;
	}
}
Example #3
0
static void state_changed(struct audio_device *dev, avctp_state_t old_state,
				avctp_state_t new_state, void *user_data)
{
	struct control *control = dev->control;
	gboolean value;

	switch (new_state) {
	case AVCTP_STATE_DISCONNECTED:
		control->session = NULL;

		if (old_state != AVCTP_STATE_CONNECTED)
			break;

		value = FALSE;
		g_dbus_emit_signal(dev->conn, dev->path,
					AUDIO_CONTROL_INTERFACE,
					"Disconnected", DBUS_TYPE_INVALID);
		emit_property_changed(dev->conn, dev->path,
					AUDIO_CONTROL_INTERFACE, "Connected",
					DBUS_TYPE_BOOLEAN, &value);

		break;
	case AVCTP_STATE_CONNECTING:
		if (control->session)
			break;

		control->session = avctp_get(&dev->src, &dev->dst);

		break;
	case AVCTP_STATE_CONNECTED:
		value = TRUE;
		g_dbus_emit_signal(dev->conn, dev->path,
				AUDIO_CONTROL_INTERFACE, "Connected",
				DBUS_TYPE_INVALID);
		emit_property_changed(dev->conn, dev->path,
				AUDIO_CONTROL_INTERFACE, "Connected",
				DBUS_TYPE_BOOLEAN, &value);
		break;
	default:
		return;
	}
}
Example #4
0
static void avctp_server_cb(GIOChannel *chan, int err, const bdaddr_t *src,
				const bdaddr_t *dst, gpointer data)
{
	socklen_t size;
	struct l2cap_options l2o;
	struct avctp *session;
	GIOCondition flags = G_IO_ERR | G_IO_HUP | G_IO_NVAL;
	struct audio_device *dev;
	char address[18];

	if (err < 0) {
		error("AVCTP server socket: %s (%d)", strerror(-err), -err);
		return;
	}

	session = avctp_get(src, dst);

	if (!session) {
		error("Unable to create new AVCTP session");
		goto drop;
	}

	if (session->sock >= 0) {
		error("Refusing unexpected connect from %s", address);
		goto drop;
	}

	dev = manager_find_device(&session->dst, AUDIO_CONTROL_INTERFACE, FALSE);

	if (!dev) {
		error("Unable to get audio device object for %s", address);
		goto drop;
	}

	if (!dev->control)
		dev->control = control_init(dev);

	device_remove_control_timer(dev);

	session->state = AVCTP_STATE_CONNECTING;
	session->sock = g_io_channel_unix_get_fd(chan);

	memset(&l2o, 0, sizeof(l2o));
	size = sizeof(l2o);
	if (getsockopt(session->sock, SOL_L2CAP, L2CAP_OPTIONS, &l2o, &size) < 0) {
		err = errno;
		error("getsockopt(L2CAP_OPTIONS): %s (%d)", strerror(err),
				err);
		avctp_unref(session);
		goto drop;
	}

	session->mtu = l2o.imtu;

	if (session->io)
		g_source_remove(session->io);
	session->io = g_io_add_watch(chan, flags, (GIOFunc) session_cb,
				session);
	g_io_channel_unref(chan);

	if (avdtp_is_connected(src, dst))
		goto proceed;

	if (service_req_auth(src, dst, AVRCP_TARGET_UUID, auth_cb, session) < 0)
		goto drop;

	return;

proceed:
	avctp_connect_session(session);

	return;

drop:
	close(session->sock);
}