Пример #1
0
gboolean sink_shutdown(struct sink *sink)
{
	if (!sink->session)
		return FALSE;

	avdtp_set_device_disconnect(sink->session, TRUE);

	/* cancel pending connect */
	if (sink->connect) {
		struct pending_request *pending = sink->connect;

		if (pending->msg)
			error_failed(pending->conn, pending->msg,
							"Stream setup failed");
		pending_request_free(sink->dev, pending);
		sink->connect = NULL;

		avdtp_unref(sink->session);
		sink->session = NULL;

		return TRUE;
	}

	/* disconnect already ongoing */
	if (sink->disconnect)
		return TRUE;

	if (!sink->stream)
		return FALSE;

	if (avdtp_close(sink->session, sink->stream, FALSE) < 0)
		return FALSE;

	return TRUE;
}
Пример #2
0
int source_disconnect(struct btd_service *service)
{
	struct source *source = btd_service_get_user_data(service);

	if (!source->session)
		return -ENOTCONN;

	/* cancel pending connect */
	if (source->connect_id > 0) {
		a2dp_cancel(source->connect_id);
		source->connect_id = 0;
		btd_service_connecting_complete(source->service, -ECANCELED);

		avdtp_unref(source->session);
		source->session = NULL;

		return 0;
	}

	/* disconnect already ongoing */
	if (source->disconnect_id > 0)
		return -EBUSY;

	if (!source->stream)
		return -ENOTCONN;

	return avdtp_close(source->session, source->stream, FALSE);
}
Пример #3
0
static DBusMessage *sink_disconnect(DBusConnection *conn,
					DBusMessage *msg, void *data)
{
	struct audio_device *device = data;
	struct sink *sink = device->sink;
	struct pending_request *pending;
	int err;

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

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

	if (sink->stream_state < AVDTP_STATE_OPEN) {
		DBusMessage *reply = dbus_message_new_method_return(msg);
		if (!reply)
			return NULL;
		avdtp_unref(sink->session);
		sink->session = NULL;
		return reply;
	}

	err = avdtp_close(sink->session, sink->stream, FALSE);
	if (err < 0)
		return btd_error_failed(msg, strerror(-err));

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

	return NULL;
}
Пример #4
0
static void bt_stream_close(const void *buf, uint16_t len)
{
	const struct audio_cmd_close_stream *cmd = buf;
	struct a2dp_setup *setup;
	int err;

	DBG("");

	setup = find_setup(cmd->id);
	if (!setup) {
		error("Unable to find stream for endpoint %u", cmd->id);
		goto failed;
	}

	err = avdtp_close(setup->dev->session, setup->stream, FALSE);
	if (err < 0) {
		error("avdtp_close: %s", strerror(-err));
		goto failed;
	}

	ipc_send_rsp(audio_ipc, AUDIO_SERVICE_ID, AUDIO_OP_CLOSE_STREAM,
							AUDIO_STATUS_SUCCESS);

	return;

failed:
	ipc_send_rsp(audio_ipc, AUDIO_SERVICE_ID, AUDIO_OP_CLOSE_STREAM,
							AUDIO_STATUS_FAILED);
}
Пример #5
0
static void reconf_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
			struct avdtp_stream *stream, struct avdtp_error *err,
			void *user_data)
{
	struct a2dp_sep *a2dp_sep = user_data;
	struct a2dp_setup *setup;

	if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
		debug("Sink %p: ReConfigure_Cfm", sep);
	else
		debug("Source %p: ReConfigure_Cfm", sep);

	setup = find_setup_by_session(session);
	if (!setup)
		return;

	if (setup->canceled) {
		if (!err)
			avdtp_close(session, stream);
		setup_unref(setup);
		return;
	}

	if (err) {
		setup->stream = NULL;
		setup->err = err;
	}

	finalize_config(setup);
}
Пример #6
0
int source_disconnect(struct audio_device *dev, gboolean shutdown)
{
	struct source *source = dev->source;

	if (!source->session)
		return -ENOTCONN;

	if (shutdown)
		avdtp_set_device_disconnect(source->session, TRUE);

	/* cancel pending connect */
	if (source->connect_id > 0) {
		a2dp_cancel(dev, source->connect_id);
		source->connect_id = 0;
		audio_source_connected(dev->btd_dev, -ECANCELED);

		avdtp_unref(source->session);
		source->session = NULL;

		return 0;
	}

	/* disconnect already ongoing */
	if (source->disconnect_id > 0)
		return -EBUSY;

	if (!source->stream)
		return -ENOTCONN;

	return avdtp_close(source->session, source->stream, FALSE);
}
Пример #7
0
static void send_command(void)
{
	avdtp_state_t state = avdtp_sep_get_state(local_sep);

	switch (command) {
	case CMD_GET_CONF:
		avdtp_get_configuration(avdtp, avdtp_stream);
		break;
	case CMD_OPEN:
		if (state == AVDTP_STATE_CONFIGURED)
			avdtp_open(avdtp, avdtp_stream);
		break;
	case CMD_START:
		if (state == AVDTP_STATE_OPEN)
			avdtp_start(avdtp, avdtp_stream);
		break;
	case CMD_SUSPEND:
		if (state == AVDTP_STATE_STREAMING)
			avdtp_suspend(avdtp , avdtp_stream);
		break;
	case CMD_CLOSE:
		if (state == AVDTP_STATE_STREAMING)
			avdtp_close(avdtp, avdtp_stream, FALSE);
		break;
	case CMD_ABORT:
		avdtp_abort(avdtp , avdtp_stream);
		break;
	case CMD_DELAY:
		avdtp_delay_report(avdtp , avdtp_stream , 250);
		break;
	default:
		break;
	}
}
Пример #8
0
int sink_disconnect(struct audio_device *dev, gboolean shutdown)
{
	struct sink *sink = dev->sink;

	if (!sink->session)
		return -ENOTCONN;

	if (shutdown)
		avdtp_set_device_disconnect(sink->session, TRUE);

	/* cancel pending connect */
	if (sink->connect_id > 0) {
		a2dp_cancel(dev, sink->connect_id);
		sink->connect_id = 0;
		btd_service_connecting_complete(sink->service, -ECANCELED);

		avdtp_unref(sink->session);
		sink->session = NULL;

		return 0;
	}

	/* disconnect already ongoing */
	if (sink->disconnect_id > 0)
		return -EBUSY;

	if (!sink->stream)
		return -ENOTCONN;

	return avdtp_close(sink->session, sink->stream, FALSE);
}
Пример #9
0
gboolean sink_shutdown(struct sink *sink)
{
	if (!sink->stream)
		return FALSE;

	if (avdtp_close(sink->session, sink->stream, FALSE) < 0)
		return FALSE;

	return TRUE;
}
Пример #10
0
static void disconnect_cb(struct btd_device *btd_dev, gboolean removal,
				void *user_data)
{
	struct audio_device *device = user_data;
	struct sink *sink = device->sink;

	DBG("Sink: disconnect %s", device->path);

	avdtp_close(sink->session, sink->stream, TRUE);
}
Пример #11
0
gboolean source_shutdown(struct source *source)
{
	if (!source->stream)
		return FALSE;

	if (avdtp_close(source->session, source->stream) < 0)
		return FALSE;

	return TRUE;
}
Пример #12
0
static void disconnect_cb(struct btd_device *btd_dev, gboolean removal,
				void *user_data)
{
	struct audio_device *device = user_data;
	struct source *source = device->source;

	debug("Source: disconnect %s", device->path);

	avdtp_close(source->session, source->stream);
}
Пример #13
0
void avdtp_free(avdtp_t *avdtp)
{
	struct avdtp_session *session;

	if (!avdtp)
		return;

	session = avdtp;

	avdtp_close(avdtp);

	memset(session, 0, sizeof(*session));
	free(session);
}
Пример #14
0
static DBusMessage *sink_disconnect(DBusConnection *conn,
					DBusMessage *msg, void *data)
{
	struct audio_device *device = data;
	struct sink *sink = device->sink;
	struct pending_request *pending;
	int err;

	if (!sink->session)
		return g_dbus_create_error(msg, ERROR_INTERFACE
						".NotConnected",
						"Device not Connected");

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

	if (sink->state < AVDTP_STATE_OPEN) {
		DBusMessage *reply = dbus_message_new_method_return(msg);
		if (!reply)
			return NULL;
		avdtp_unref(sink->session);
		sink->session = NULL;
		return reply;
	}

	err = avdtp_close(sink->session, sink->stream);
	if (err < 0)
		return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
						"%s", strerror(-err));

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

	return NULL;
}