Beispiel #1
0
static guint resume_a2dp(struct media_transport *transport,
				struct media_owner *owner)
{
	struct a2dp_transport *a2dp = transport->data;
	struct media_endpoint *endpoint = transport->endpoint;
	struct a2dp_sep *sep = media_endpoint_get_sep(endpoint);
	guint id;

	if (a2dp->session == NULL) {
		a2dp->session = avdtp_get(transport->device);
		if (a2dp->session == NULL)
			return 0;
	}

	if (state_in_use(transport->state))
		return a2dp_resume(a2dp->session, sep, a2dp_resume_complete,
									owner);

	if (a2dp_sep_lock(sep, a2dp->session) == FALSE)
		return 0;

	id = a2dp_resume(a2dp->session, sep, a2dp_resume_complete, owner);

	if (id == 0) {
		a2dp_sep_unlock(sep, a2dp->session);
		return 0;
	}

	if (transport->state == TRANSPORT_STATE_IDLE)
		transport_set_state(transport, TRANSPORT_STATE_REQUESTING);

	return id;
}
static DBusMessage *sink_connect(DBusConnection *conn,
				DBusMessage *msg, void *data)
{
	struct audio_device *dev = data;
	struct sink *sink = dev->sink;
	struct pending_request *pending;

	if (!sink->session)
		sink->session = avdtp_get(&dev->src, &dev->dst);

	if (!sink->session)
		return btd_error_failed(msg, "Unable to get a session");

	if (sink->connect || sink->disconnect)
		return btd_error_busy(msg);

	if (sink->stream_state >= AVDTP_STATE_OPEN)
		return btd_error_already_connected(msg);

	if (!sink_setup_stream(sink, NULL))
		return btd_error_failed(msg, "Failed to create a stream");

	dev->auto_connect = FALSE;

	pending = sink->connect;

	pending->conn = dbus_connection_ref(conn);
	pending->msg = dbus_message_ref(msg);

	DBG("stream creation in progress");

	return NULL;
}
Beispiel #3
0
int source_connect(struct audio_device *dev)
{
	struct source *source = dev->source;

	if (!source->session)
		source->session = avdtp_get(dev);

	if (!source->session) {
		DBG("Unable to get a session");
		return -EIO;
	}

	if (source->connect_id > 0 || source->disconnect_id > 0)
		return -EBUSY;

	if (source->stream_state >= AVDTP_STATE_OPEN)
		return -EALREADY;

	if (!source_setup_stream(source, NULL)) {
		DBG("Failed to create a stream");
		return -EIO;
	}

	DBG("stream creation in progress");

	return 0;
}
int sink_connect(struct btd_service *service)
{
	struct sink *sink = btd_service_get_user_data(service);

	if (!sink->session)
		sink->session = avdtp_get(btd_service_get_device(service));

	if (!sink->session) {
		DBG("Unable to get a session");
		return -EIO;
	}

	if (sink->connect_id > 0 || sink->disconnect_id > 0)
		return -EBUSY;

	if (sink->state == SINK_STATE_CONNECTING)
		return -EBUSY;

	if (sink->stream_state >= AVDTP_STATE_OPEN)
		return -EALREADY;

	if (!sink_setup_stream(service, NULL)) {
		DBG("Failed to create a stream");
		return -EIO;
	}

	DBG("stream creation in progress");

	return 0;
}
Beispiel #5
0
static DBusMessage *sink_connect(DBusConnection *conn,
				DBusMessage *msg, void *data)
{
	struct audio_device *dev = data;
	struct sink *sink = dev->sink;
	struct pending_request *pending;

	if (!sink->session)
		sink->session = avdtp_get(&dev->src, &dev->dst);

	if (!sink->session)
		return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
						"Unable to get a session");

	if (sink->connect || sink->disconnect)
		return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
						"%s", strerror(EBUSY));

	if (sink->state >= AVDTP_STATE_OPEN)
		return g_dbus_create_error(msg, ERROR_INTERFACE
						".AlreadyConnected",
						"Device Already Connected");

	pending = g_new0(struct pending_request, 1);
	pending->conn = dbus_connection_ref(conn);
	pending->msg = dbus_message_ref(msg);
	sink->connect = pending;

	avdtp_discover(sink->session, discovery_complete, sink);

	debug("stream creation in progress");

	return NULL;
}
Beispiel #6
0
static void start_discovery(struct audio_device *dev, struct unix_client *client)
{
	struct a2dp_data *a2dp;
	int err = 0;

	switch (client->type) {
	case TYPE_SINK:
	case TYPE_SOURCE:
		a2dp = &client->d.a2dp;

		if (!a2dp->session)
			a2dp->session = avdtp_get(&dev->src, &dev->dst);

		if (!a2dp->session) {
			error("Unable to get a session");
			goto failed;
		}

		err = avdtp_discover(a2dp->session, a2dp_discovery_complete,
					client);
		if (err) {
			if (a2dp->session) {
				avdtp_unref(a2dp->session);
				a2dp->session = NULL;
			}
			goto failed;
		}
		break;

	case TYPE_HEADSET:
	case TYPE_GATEWAY:
		headset_discovery_complete(dev, client);
		break;

	default:
		error("No known services for device");
		goto failed;
	}

	client->dev = dev;

	return;

failed:
	unix_ipc_error(client, BT_GET_CAPABILITIES, err ? : EIO);
}
static gboolean avdtp_connect_timeout(gpointer user_data)
{
	struct audio_device *dev = user_data;

	dev->priv->avdtp_timer = 0;

	if (dev->sink) {
		struct avdtp *session = avdtp_get(&dev->src, &dev->dst);

		if (!session)
			return FALSE;

		sink_setup_stream(dev->sink, session);
		avdtp_unref(session);
	}

	return FALSE;
}
static DBusMessage *dev_connect(DBusConnection *conn, DBusMessage *msg,
								void *data)
{
	struct audio_device *dev = data;
	struct dev_priv *priv = dev->priv;

	if (priv->state == AUDIO_STATE_CONNECTING)
		return g_dbus_create_error(msg, ERROR_INTERFACE ".InProgress",
						"Connect in Progress");
	else if (priv->state == AUDIO_STATE_CONNECTED)
		return g_dbus_create_error(msg, ERROR_INTERFACE
						".AlreadyConnected",
						"Already Connected");

	dev->auto_connect = TRUE;

	if (dev->headset)
		headset_config_stream(dev, FALSE, NULL, NULL);

	if (priv->state != AUDIO_STATE_CONNECTING && dev->sink) {
		struct avdtp *session = avdtp_get(&dev->src, &dev->dst);

		if (!session)
			return g_dbus_create_error(msg, ERROR_INTERFACE
					".Failed",
					"Failed to get AVDTP session");

		sink_setup_stream(dev->sink, session);
		avdtp_unref(session);
	}

	/* The previous calls should cause a call to the state callback to
	 * indicate AUDIO_STATE_CONNECTING */
	if (priv->state != AUDIO_STATE_CONNECTING)
		return g_dbus_create_error(msg, ERROR_INTERFACE
				".ConnectFailed",
				"Headset connect failed");

	priv->conn_req = dbus_message_ref(msg);

	return NULL;
}
Beispiel #9
0
static DBusMessage *source_connect(DBusConnection *conn,
				DBusMessage *msg, void *data)
{
	struct audio_device *dev = data;
	struct source *source = dev->source;
	struct pending_request *pending;

	if (!source->session)
		source->session = avdtp_get(&dev->src, &dev->dst);

	if (!source->session)
		return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
						"Unable to get a session");

	if (source->connect || source->disconnect)
		return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
						"%s", strerror(EBUSY));

	if (source->stream_state >= AVDTP_STATE_OPEN)
		return g_dbus_create_error(msg, ERROR_INTERFACE
						".AlreadyConnected",
						"Device Already Connected");

	if (!source_setup_stream(source, NULL))
		return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
						"Failed to create a stream");

	dev->auto_connect = FALSE;

	pending = source->connect;

	pending->conn = dbus_connection_ref(conn);
	pending->msg = dbus_message_ref(msg);

	debug("stream creation in progress");

	return NULL;
}
Beispiel #10
0
static guint resume_a2dp(struct media_transport *transport,
				struct media_owner *owner)
{
	struct a2dp_transport *a2dp = transport->data;
	struct media_endpoint *endpoint = transport->endpoint;
	struct audio_device *device = transport->device;
	struct a2dp_sep *sep = media_endpoint_get_sep(endpoint);

	if (a2dp->session == NULL) {
		a2dp->session = avdtp_get(&device->src, &device->dst);
		if (a2dp->session == NULL)
			return 0;
	}

	if (transport->in_use == TRUE)
		goto done;

	transport->in_use = a2dp_sep_lock(sep, a2dp->session);
	if (transport->in_use == FALSE)
		return 0;

done:
	return a2dp_resume(a2dp->session, sep, a2dp_resume_complete, owner);
}
Beispiel #11
0
static void start_config(struct audio_device *dev, struct unix_client *client)
{
	struct a2dp_data *a2dp;
	struct headset_data *hs;
	unsigned int id;

	switch (client->type) {
	case TYPE_SINK:
	case TYPE_SOURCE:
		a2dp = &client->d.a2dp;

		if (!a2dp->session)
			a2dp->session = avdtp_get(&dev->src, &dev->dst);

		if (!a2dp->session) {
			error("Unable to get a session");
			goto failed;
		}

		if (!a2dp->sep) {
			error("seid %d not opened", client->seid);
			goto failed;
		}

		id = a2dp_config(a2dp->session, a2dp->sep, a2dp_config_complete,
					client->caps, client);
		client->cancel = a2dp_cancel;
		break;

	case TYPE_HEADSET:
		hs = &client->d.hs;

		if (!hs->locked) {
			error("seid %d not opened", client->seid);
			goto failed;
		}

		id = headset_config_stream(dev, TRUE, headset_setup_complete,
						client);
		client->cancel = headset_cancel_stream;
		break;
	case TYPE_GATEWAY:
		if (gateway_config_stream(dev, gateway_setup_complete, client) >= 0) {
			client->cancel = gateway_cancel_stream;
			id = 1;
		} else
			id = 0;
		break;

	default:
		error("No known services for device");
		goto failed;
	}

	if (id == 0) {
		error("config failed");
		goto failed;
	}

	client->req_id = id;

	return;

failed:
	unix_ipc_error(client, BT_SET_CONFIGURATION, EIO);
}
Beispiel #12
0
static void start_open(struct audio_device *dev, struct unix_client *client)
{
	struct a2dp_data *a2dp;
	struct headset_data *hs;
	struct avdtp_remote_sep *rsep;
	gboolean unref_avdtp_on_fail = FALSE;

	switch (client->type) {
	case TYPE_SINK:
	case TYPE_SOURCE:
		a2dp = &client->d.a2dp;

		if (!a2dp->session) {
			a2dp->session = avdtp_get(&dev->src, &dev->dst);
			unref_avdtp_on_fail = TRUE;
		}

		if (!a2dp->session) {
			error("Unable to get a session");
			goto failed;
		}

		if (a2dp->sep) {
			error("Client already has an opened session");
			goto failed;
		}

		rsep = avdtp_get_remote_sep(a2dp->session, client->seid);
		if (!rsep) {
			error("Invalid seid %d", client->seid);
			goto failed;
		}

		a2dp->sep = a2dp_get(a2dp->session, rsep);
		if (!a2dp->sep) {
			error("seid %d not available or locked", client->seid);
			goto failed;
		}

		if (!a2dp_sep_lock(a2dp->sep, a2dp->session)) {
			error("Unable to open seid %d", client->seid);
			a2dp->sep = NULL;
			goto failed;
		}

		break;

	case TYPE_HEADSET:
		hs = &client->d.hs;

		if (hs->locked) {
			error("Client already has an opened session");
			goto failed;
		}

		hs->locked = headset_lock(dev, client->lock);
		if (!hs->locked) {
			error("Unable to open seid %d", client->seid);
			goto failed;
		}
		break;

        case TYPE_GATEWAY:
                break;
	default:
		error("No known services for device");
		goto failed;
	}

	client->dev = dev;

	open_complete(dev, client);

	return;

failed:
	if (unref_avdtp_on_fail && a2dp->session) {
		avdtp_unref(a2dp->session);
		a2dp->session = NULL;
	}
	unix_ipc_error(client, BT_OPEN, EINVAL);
}
Beispiel #13
0
static void start_suspend(struct audio_device *dev, struct unix_client *client)
{
	struct a2dp_data *a2dp;
	struct headset_data *hs;
	unsigned int id;
	gboolean unref_avdtp_on_fail = FALSE;

	switch (client->type) {
	case TYPE_SINK:
	case TYPE_SOURCE:
		a2dp = &client->d.a2dp;

		if (!a2dp->session) {
			a2dp->session = avdtp_get(&dev->src, &dev->dst);
			unref_avdtp_on_fail = TRUE;
		}

		if (!a2dp->session) {
			error("Unable to get a session");
			goto failed;
		}

		if (!a2dp->sep) {
			error("Unable to get a sep");
			goto failed;
		}

		id = a2dp_suspend(a2dp->session, a2dp->sep,
					a2dp_suspend_complete, client);
		client->cancel = a2dp_cancel;
		break;

	case TYPE_HEADSET:
		hs = &client->d.hs;

		if (!hs->locked) {
			error("seid not opened");
			goto failed;
		}

		id = headset_suspend_stream(dev, headset_suspend_complete,
						client);
		client->cancel = headset_cancel_stream;
		break;

	case TYPE_GATEWAY:
		gateway_suspend_stream(dev);
		client->cancel = gateway_cancel_stream;
		headset_suspend_complete(dev, client);
		id = 1;
		break;

	default:
		error("No known services for device");
		goto failed;
	}

	if (id == 0) {
		error("suspend failed");
		goto failed;
	}

	return;

failed:
	if (unref_avdtp_on_fail && a2dp->session) {
		avdtp_unref(a2dp->session);
		a2dp->session = NULL;
	}
	unix_ipc_error(client, BT_STOP_STREAM, EIO);
}
Beispiel #14
0
static void start_resume(struct audio_device *dev, struct unix_client *client)
{
	struct a2dp_data *a2dp = NULL;
	struct headset_data *hs;
	unsigned int id;
	struct avdtp *session = NULL;

	switch (client->type) {
	case TYPE_SINK:
	case TYPE_SOURCE:
		a2dp = &client->d.a2dp;

		if (!a2dp->sep) {
			error("seid not opened");
			goto failed;
		}

		if (!a2dp->session) {
			session = avdtp_get(&dev->src, &dev->dst);
			if (!session) {
				error("Unable to get a session");
				goto failed;
			}
			a2dp->session = session;
		}

		id = a2dp_resume(a2dp->session, a2dp->sep, a2dp_resume_complete,
					client);
		client->cancel = a2dp_cancel;

		break;

	case TYPE_HEADSET:
		hs = &client->d.hs;

		if (!hs->locked) {
			error("seid not opened");
			goto failed;
		}

		id = headset_request_stream(dev, headset_resume_complete,
						client);
		client->cancel = headset_cancel_stream;
		break;

	case TYPE_GATEWAY:
		id = gateway_request_stream(dev, gateway_resume_complete,
						client);
		client->cancel = gateway_cancel_stream;
		break;

	default:
		error("No known services for device");
		goto failed;
	}

	if (id == 0) {
		error("start_resume: resume failed");
		goto failed;
	}

	client->req_id = id;

	return;

failed:
	if (session) {
		avdtp_unref(session);
		a2dp->session = NULL;
	}

	unix_ipc_error(client, BT_START_STREAM, EIO);
}
static void start_config(struct audio_device *dev, struct unix_client *client)
{
	struct a2dp_data *a2dp;
	struct headset_data *hs;
	struct avdtp_remote_sep *rsep;
	struct avdtp_service_capability *media_scms_t;
	struct avdtp_content_protection_capability scms_t_cap = {0x02, 0x00};
	unsigned int id;

	switch (client->type) {
	case TYPE_SINK:
	case TYPE_SOURCE:
		a2dp = &client->d.a2dp;

		if (!a2dp->session)
			a2dp->session = avdtp_get(&dev->src, &dev->dst);

		if (!a2dp->session) {
			error("Unable to get a session");
			goto failed;
		}

		if (!a2dp->sep) {
			error("seid %d not opened", client->seid);
			goto failed;
		}

		rsep = avdtp_get_remote_sep(a2dp->session, client->seid);
		media_scms_t = avdtp_get_remote_sep_protection(rsep);

		if (media_scms_t &&
			(memcmp(media_scms_t->data, &scms_t_cap, sizeof(scms_t_cap)) == 0)) {
			media_scms_t = avdtp_service_cap_new(AVDTP_CONTENT_PROTECTION,
						&scms_t_cap, 2);
			client->caps = g_slist_append(client->caps, media_scms_t);
		}
		id = a2dp_config(a2dp->session, a2dp->sep, a2dp_config_complete,
					client->caps, client);
		client->cancel = a2dp_cancel;
		break;

	case TYPE_HEADSET:
		hs = &client->d.hs;

		if (!hs->locked) {
			error("seid %d not opened", client->seid);
			goto failed;
		}

		id = headset_config_stream(dev, TRUE, headset_setup_complete,
						client);
		client->cancel = headset_cancel_stream;
		break;
	case TYPE_GATEWAY:
		if (gateway_config_stream(dev, gateway_setup_complete, client) >= 0) {
			client->cancel = gateway_cancel_stream;
			id = 1;
		} else
			id = 0;
		break;

	default:
		error("No known services for device");
		goto failed;
	}

	if (id == 0) {
		error("config failed");
		goto failed;
	}

	client->req_id = id;
	g_slist_free(client->caps);
	client->caps = NULL;

	return;

failed:
	if (client->caps) {
		g_slist_free(client->caps);
		client->caps = NULL;
	}
	unix_ipc_error(client, BT_SET_CONFIGURATION, EIO);
}