static gboolean mpeg_setconf_ind(struct avdtp *session,
				struct avdtp_local_sep *sep,
				struct avdtp_stream *stream,
				GSList *caps, uint8_t *err,
				uint8_t *category, void *user_data)
{
	struct a2dp_sep *a2dp_sep = user_data;
	struct audio_device *dev;

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

	dev = a2dp_get_dev(session);
	if (!dev) {
		*err = AVDTP_UNSUPPORTED_CONFIGURATION;
		*category = 0x00;
		return FALSE;
	}

	avdtp_stream_add_cb(session, stream, stream_state_changed, a2dp_sep);
	a2dp_sep->stream = stream;

	if (a2dp_sep->type == AVDTP_SEP_TYPE_SOURCE)
		sink_new_stream(dev, session, stream);

	return TRUE;
}
Exemple #2
0
static void a2dp_config_complete(struct avdtp *session, struct a2dp_sep *sep,
					struct avdtp_stream *stream,
					struct avdtp_error *err,
					void *user_data)
{
	struct unix_client *client = user_data;
	char buf[BT_SUGGESTED_BUFFER_SIZE];
	struct bt_set_configuration_rsp *rsp = (void *) buf;
	struct a2dp_data *a2dp = &client->d.a2dp;
	uint16_t imtu, omtu;
	GSList *caps;

	client->req_id = 0;

	if (err)
		goto failed;

	memset(buf, 0, sizeof(buf));

	if (!stream)
		goto failed;

	if (client->cb_id > 0)
		avdtp_stream_remove_cb(a2dp->session, a2dp->stream,
								client->cb_id);

	a2dp->sep = sep;
	a2dp->stream = stream;

	if (!avdtp_stream_get_transport(stream, &client->data_fd, &imtu, &omtu,
					&caps)) {
		error("Unable to get stream transport");
		goto failed;
	}

	rsp->h.type = BT_RESPONSE;
	rsp->h.name = BT_SET_CONFIGURATION;
	rsp->h.length = sizeof(*rsp);

	/* FIXME: Use imtu when fd_opt is CFG_FD_OPT_READ */
	rsp->link_mtu = omtu;

	unix_ipc_sendmsg(client, &rsp->h);

	client->cb_id = avdtp_stream_add_cb(session, stream,
						stream_state_changed, client);

	return;

failed:
	error("config failed");

	unix_ipc_error(client, BT_SET_CONFIGURATION, EIO);

	avdtp_unref(a2dp->session);

	a2dp->session = NULL;
	a2dp->stream = NULL;
	a2dp->sep = NULL;
}
Exemple #3
0
static gboolean auto_config(gpointer data)
{
	struct a2dp_setup *setup = data;

	/* Check if configuration was aborted */
	if (setup->sep->stream == NULL)
		return FALSE;

	if (setup->err != NULL)
		goto done;

	avdtp_stream_add_cb(setup->session, setup->stream,
				stream_state_changed, setup->sep);

	if (setup->sep->type == AVDTP_SEP_TYPE_SOURCE)
		sink_new_stream(setup->dev, setup->session, setup->stream);
	else
		source_new_stream(setup->dev, setup->session, setup->stream);

done:
	if (setup->setconf_cb)
		setup->setconf_cb(setup->session, setup->stream, setup->err);

	finalize_config(setup);

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

	setup_unref(setup);

	return FALSE;
}
Exemple #4
0
static gboolean sbc_setconf_ind(struct avdtp *session,
				struct avdtp_local_sep *sep,
				struct avdtp_stream *stream,
				GSList *caps, uint8_t *err,
				uint8_t *category, void *user_data)
{
	struct a2dp_sep *a2dp_sep = user_data;
	struct audio_device *dev;
	struct avdtp_service_capability *cap;
	struct avdtp_media_codec_capability *codec_cap;
	struct sbc_codec_cap *sbc_cap;

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

	dev = a2dp_get_dev(session);
	if (!dev) {
		*err = AVDTP_UNSUPPORTED_CONFIGURATION;
		*category = 0x00;
		return FALSE;
	}

	/* Check bipool range */
	for (codec_cap = NULL; caps; caps = g_slist_next(caps)) {
		cap = caps->data;
		if (cap->category != AVDTP_MEDIA_CODEC)
			continue;

		if (cap->length < sizeof(struct sbc_codec_cap))
			continue;

		codec_cap = (void *) cap->data;

		if (codec_cap->media_codec_type != A2DP_CODEC_SBC)
			continue;

		sbc_cap = (void *) codec_cap;

		if (sbc_cap->min_bitpool < MIN_BITPOOL ||
					sbc_cap->max_bitpool > MAX_BITPOOL) {
			*err = AVDTP_UNSUPPORTED_CONFIGURATION;
			*category = AVDTP_MEDIA_CODEC;
			return FALSE;
		}

		break;
	}

	avdtp_stream_add_cb(session, stream, stream_state_changed, a2dp_sep);
	a2dp_sep->stream = stream;

	if (a2dp_sep->type == AVDTP_SEP_TYPE_SOURCE)
		sink_new_stream(dev, session, stream);

	return TRUE;
}
static void setconf_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;
	struct audio_device *dev;
	int ret;

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

	setup = find_setup_by_session(session);

	if (err) {
		if (setup) {
			setup->err = err;
			finalize_config(setup);
		}
		return;
	}

	avdtp_stream_add_cb(session, stream, stream_state_changed, a2dp_sep);
	a2dp_sep->stream = stream;

	if (!setup)
		return;

	dev = a2dp_get_dev(session);

	/* Notify D-Bus interface of the new stream */
	if (a2dp_sep->type == AVDTP_SEP_TYPE_SOURCE)
		sink_new_stream(dev, session, setup->stream);
	else
		source_new_stream(dev, session, setup->stream);

	ret = avdtp_open(session, stream);
	if (ret < 0) {
		error("Error on avdtp_open %s (%d)", strerror(-ret), -ret);
		setup->stream = NULL;
		finalize_config_errno(setup, ret);
	}
}
Exemple #6
0
gboolean source_new_stream(struct btd_service *service, struct avdtp *session,
				struct avdtp_stream *stream)
{
	struct source *source = btd_service_get_user_data(service);

	if (source->stream)
		return FALSE;

	if (!source->session)
		source->session = avdtp_ref(session);

	source->stream = stream;

	source->cb_id = avdtp_stream_add_cb(session, stream,
						stream_state_changed, service);

	return TRUE;
}
gboolean sink_new_stream(struct audio_device *dev, struct avdtp *session,
				struct avdtp_stream *stream)
{
	struct sink *sink = dev->sink;

	if (sink->stream)
		return FALSE;

	if (!sink->session)
		sink->session = avdtp_ref(session);

	sink->stream = stream;

	sink->cb_id = avdtp_stream_add_cb(session, stream,
						stream_state_changed, dev);

	return TRUE;
}
Exemple #8
0
gboolean source_new_stream(struct audio_device *dev, struct avdtp *session,
				struct avdtp_stream *stream)
{
	struct source *source = dev->source;

	if (source->stream)
		return FALSE;

	if (!source->session)
		source->session = avdtp_ref(session);

	source->stream = stream;

	source->cb_id = avdtp_stream_add_cb(session, stream,
						stream_state_changed, dev);

	return TRUE;
}
static gboolean mpeg_setconf_ind(struct avdtp *session,
				struct avdtp_local_sep *sep,
				struct avdtp_stream *stream,
				GSList *caps, uint8_t *err,
				uint8_t *category, void *user_data)
{
	struct a2dp_sep *a2dp_sep = user_data;
	struct audio_device *dev;

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

	dev = a2dp_get_dev(session);
	if (!dev) {
		*err = AVDTP_UNSUPPORTED_CONFIGURATION;
		*category = 0x00;
		return FALSE;
	}

	for (; caps != NULL; caps = g_slist_next(caps)) {
		struct avdtp_service_capability *cap = caps->data;

		if (cap->category == AVDTP_DELAY_REPORTING &&
					!a2dp_sep->delay_reporting) {
			*err = AVDTP_UNSUPPORTED_CONFIGURATION;
			*category = AVDTP_DELAY_REPORTING;
			return FALSE;
		}
	}

	avdtp_stream_add_cb(session, stream, stream_state_changed, a2dp_sep);
	a2dp_sep->stream = stream;

	if (a2dp_sep->type == AVDTP_SEP_TYPE_SOURCE)
		sink_new_stream(dev, session, stream);

	return TRUE;
}
Exemple #10
0
static gboolean auto_config(gpointer data)
{
	struct a2dp_setup *setup = data;
	struct btd_device *dev = avdtp_get_device(setup->session);
	struct btd_service *service;

	/* Check if configuration was aborted */
	if (setup->sep->stream == NULL)
		return FALSE;

	if (setup->err != NULL)
		goto done;

	avdtp_stream_add_cb(setup->session, setup->stream,
				stream_state_changed, setup->sep);

	if (setup->sep->type == AVDTP_SEP_TYPE_SOURCE) {
		service = btd_device_get_service(dev, A2DP_SINK_UUID);
		sink_new_stream(service, setup->session, setup->stream);
	} else {
		service = btd_device_get_service(dev, A2DP_SOURCE_UUID);
		source_new_stream(service, setup->session, setup->stream);
	}

done:
	if (setup->setconf_cb)
		setup->setconf_cb(setup->session, setup->stream, setup->err);

	finalize_config(setup);

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

	setup_unref(setup);

	return FALSE;
}