[RFC 7/7] media: implement a2dp reconfiguration

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



---
 audio/transport.c |  117 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 117 insertions(+), 0 deletions(-)

diff --git a/audio/transport.c b/audio/transport.c
index f9b924a..6dd3c58 100644
--- a/audio/transport.c
+++ b/audio/transport.c
@@ -43,6 +43,7 @@
 #include "a2dp.h"
 #include "headset.h"
 #include "gateway.h"
+#include "ipc.h"
 
 #ifndef DBUS_TYPE_UNIX_FD
 #define DBUS_TYPE_UNIX_FD -1
@@ -53,6 +54,7 @@
 struct media_request {
 	DBusMessage		*msg;
 	guint			id;
+	DBusConnection		*conn;
 };
 
 struct media_owner {
@@ -837,11 +839,123 @@ static DBusMessage *set_property(DBusConnection *conn, DBusMessage *msg,
 	return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 }
 
+static GSList *handle_a2dp_transport(uint8_t codec)
+{
+	struct avdtp_service_capability *media_transport, *media_codec;
+	struct sbc_codec_cap sbc_cap;
+	struct mpeg_codec_cap mpg_cap;
+	GSList *caps = NULL;
+
+	if (codec == A2DP_CODEC_MPEG12) {
+		memset(&mpg_cap, 0, sizeof(mpg_cap));
+
+		/* FIXME: this code says MP3 and hope the receiver accept */
+		mpg_cap.cap.media_type = AVDTP_MEDIA_TYPE_AUDIO;
+		mpg_cap.cap.media_codec_type = A2DP_CODEC_MPEG12;
+		mpg_cap.channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO;
+		mpg_cap.crc = 0;
+		mpg_cap.layer = BT_MPEG_LAYER_3;
+		mpg_cap.frequency = MPEG_SAMPLING_FREQ_44100;
+		mpg_cap.mpf = 0;
+		mpg_cap.bitrate = 0x80;
+
+		media_codec = avdtp_service_cap_new(AVDTP_MEDIA_CODEC, &mpg_cap,
+							sizeof(mpg_cap));
+
+		DBG("Handling switch to MPEG transport");
+	} else if (codec == A2DP_CODEC_SBC) {
+		memset(&sbc_cap, 0, sizeof(sbc_cap));
+
+		/* FIXME: this is the mandatory SBC params for a source */
+		sbc_cap.cap.media_type = AVDTP_MEDIA_TYPE_AUDIO;
+		sbc_cap.cap.media_codec_type = A2DP_CODEC_SBC;
+		sbc_cap.channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO;
+		sbc_cap.frequency = BT_SBC_SAMPLING_FREQ_44100;
+		sbc_cap.allocation_method = BT_A2DP_ALLOCATION_LOUDNESS;
+		sbc_cap.subbands = BT_A2DP_SUBBANDS_8;
+		sbc_cap.block_length = BT_A2DP_BLOCK_LENGTH_16;
+		sbc_cap.min_bitpool = 53;
+		sbc_cap.max_bitpool = 53;
+
+		media_codec = avdtp_service_cap_new(AVDTP_MEDIA_CODEC, &sbc_cap,
+							sizeof(sbc_cap));
+
+		DBG("Handling switch to SBC transport");
+	} else
+		return NULL;
+
+	media_transport = avdtp_service_cap_new(AVDTP_MEDIA_TRANSPORT,
+						NULL, 0);
+
+	caps = g_slist_append(caps, media_transport);
+	caps = g_slist_append(caps, media_codec);
+
+	return caps;
+}
+
+static void a2dp_config_complete(struct avdtp *session, struct a2dp_sep *sep,
+					struct avdtp_stream *stream,
+					struct avdtp_error *err,
+					void *user_data)
+{
+	struct media_request *req = user_data;
+
+	media_request_reply(req, req->conn, err ? -ENOTSUP : 0);
+
+	dbus_connection_unref(req->conn);
+
+	g_free(req);
+}
+
+static void media_transport_reconfigure(struct avdtp *session, const char *path,
+						struct media_request *req)
+{
+	int err;
+	GSList *caps;
+	uint8_t codec;
+	struct media_endpoint *endpoint;
+	struct a2dp_sep *sep;
+
+	endpoint = media_endpoint_find(path);
+	if (endpoint == NULL) {
+		err = -EEXIST;
+		goto failed;
+	}
+	sep = media_endpoint_get_sep(endpoint);
+	codec = media_endpoint_get_codec(endpoint);
+
+	DBG(" sep %p creating caps list for codec %d", sep, codec);
+
+	/* FIXME prevent usage on SCO transport */
+	caps = handle_a2dp_transport(codec);
+	if (caps == NULL) {
+		err = -EINVAL;
+		goto failed;
+	}
+
+	err = a2dp_config(session, sep, a2dp_config_complete,
+					caps, req);
+	if (err < 0)
+		goto failed;
+
+	req->id = err;
+	return;
+
+failed:
+	media_request_reply(req, req->conn, -err);
+
+	dbus_connection_unref(req->conn);
+
+	g_free(req);
+}
+
 static DBusMessage *reconfigure(DBusConnection *conn, DBusMessage *msg,
 								void *data)
 {
+	struct media_transport *transport = data;
 	DBusMessageIter iter;
 	const char *endpoint;
+	struct media_request *req;
 
 	if (!dbus_message_iter_init(msg, &iter))
 		return btd_error_invalid_args(msg);
@@ -849,6 +963,9 @@ static DBusMessage *reconfigure(DBusConnection *conn, DBusMessage *msg,
 		return btd_error_invalid_args(msg);
 	dbus_message_iter_get_basic(&iter, &endpoint);
 
+	req = media_request_create(msg, 0);
+	req->conn = dbus_connection_ref(conn);
+	media_transport_reconfigure(transport->session, endpoint, req);
 
 	return NULL;
 }
-- 
1.7.5.4

--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux