Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH 04/10] Add support for media transport in gstreamer plugin
From: Luiz Augusto von Dentz @ 2010-09-13 14:15 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1284387337-18822-1-git-send-email-luiz.dentz@gmail.com>

From: Luiz Augusto von Dentz <luiz.dentz-von@nokia.com>

---
 Makefile.am          |    4 +-
 audio/a2dp-codecs.h  |  116 ++++++++++
 audio/gsta2dpsink.c  |   33 +++-
 audio/gsta2dpsink.h  |    1 +
 audio/gstavdtpsink.c |  609 +++++++++++++++++++++++++++++++++++++++++++++++++-
 audio/gstavdtpsink.h |    6 +
 6 files changed, 757 insertions(+), 12 deletions(-)
 create mode 100644 audio/a2dp-codecs.h

diff --git a/Makefile.am b/Makefile.am
index a8829d9..46f5449 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -307,9 +307,9 @@ audio_libgstbluetooth_la_SOURCES = audio/gstbluetooth.c audio/gstpragma.h \
 				audio/rtp.h audio/ipc.h audio/ipc.c
 audio_libgstbluetooth_la_LDFLAGS = -module -avoid-version
 audio_libgstbluetooth_la_LIBADD = sbc/libsbc.la lib/libbluetooth.la \
-				@GSTREAMER_LIBS@ -lgstaudio-0.10 -lgstrtp-0.10
+				@DBUS_LIBS@ @GSTREAMER_LIBS@ -lgstaudio-0.10 -lgstrtp-0.10
 audio_libgstbluetooth_la_CFLAGS = -fvisibility=hidden -fno-strict-aliasing \
-						$(AM_CFLAGS) @GSTREAMER_CFLAGS@
+						$(AM_CFLAGS) @DBUS_CFLAGS@ @GSTREAMER_CFLAGS@
 endif
 endif
 
diff --git a/audio/a2dp-codecs.h b/audio/a2dp-codecs.h
new file mode 100644
index 0000000..e44634e
--- /dev/null
+++ b/audio/a2dp-codecs.h
@@ -0,0 +1,116 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2006-2010  Nokia Corporation
+ *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#define A2DP_CODEC_SBC			0x00
+#define A2DP_CODEC_MPEG12		0x01
+#define A2DP_CODEC_MPEG24		0x02
+#define A2DP_CODEC_ATRAC		0x03
+
+#define SBC_SAMPLING_FREQ_16000		(1 << 3)
+#define SBC_SAMPLING_FREQ_32000		(1 << 2)
+#define SBC_SAMPLING_FREQ_44100		(1 << 1)
+#define SBC_SAMPLING_FREQ_48000		1
+
+#define SBC_CHANNEL_MODE_MONO		(1 << 3)
+#define SBC_CHANNEL_MODE_DUAL_CHANNEL	(1 << 2)
+#define SBC_CHANNEL_MODE_STEREO		(1 << 1)
+#define SBC_CHANNEL_MODE_JOINT_STEREO	1
+
+#define SBC_BLOCK_LENGTH_4		(1 << 3)
+#define SBC_BLOCK_LENGTH_8		(1 << 2)
+#define SBC_BLOCK_LENGTH_12		(1 << 1)
+#define SBC_BLOCK_LENGTH_16		1
+
+#define SBC_SUBBANDS_4			(1 << 1)
+#define SBC_SUBBANDS_8			1
+
+#define SBC_ALLOCATION_SNR		(1 << 1)
+#define SBC_ALLOCATION_LOUDNESS		1
+
+#define MPEG_CHANNEL_MODE_MONO		(1 << 3)
+#define MPEG_CHANNEL_MODE_DUAL_CHANNEL	(1 << 2)
+#define MPEG_CHANNEL_MODE_STEREO	(1 << 1)
+#define MPEG_CHANNEL_MODE_JOINT_STEREO	1
+
+#define MPEG_LAYER_MP1			(1 << 2)
+#define MPEG_LAYER_MP2			(1 << 1)
+#define MPEG_LAYER_MP3			1
+
+#define MPEG_SAMPLING_FREQ_16000	(1 << 5)
+#define MPEG_SAMPLING_FREQ_22050	(1 << 4)
+#define MPEG_SAMPLING_FREQ_24000	(1 << 3)
+#define MPEG_SAMPLING_FREQ_32000	(1 << 2)
+#define MPEG_SAMPLING_FREQ_44100	(1 << 1)
+#define MPEG_SAMPLING_FREQ_48000	1
+
+#define MAX_BITPOOL 64
+#define MIN_BITPOOL 2
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+
+typedef struct {
+	uint8_t channel_mode:4;
+	uint8_t frequency:4;
+	uint8_t allocation_method:2;
+	uint8_t subbands:2;
+	uint8_t block_length:4;
+	uint8_t min_bitpool;
+	uint8_t max_bitpool;
+} __attribute__ ((packed)) a2dp_sbc_t;
+
+typedef struct {
+	uint8_t channel_mode:4;
+	uint8_t crc:1;
+	uint8_t layer:3;
+	uint8_t frequency:6;
+	uint8_t mpf:1;
+	uint8_t rfa:1;
+	uint16_t bitrate;
+} __attribute__ ((packed)) a2dp_mpeg_t;
+
+#elif __BYTE_ORDER == __BIG_ENDIAN
+
+typedef struct {
+	uint8_t frequency:4;
+	uint8_t channel_mode:4;
+	uint8_t block_length:4;
+	uint8_t subbands:2;
+	uint8_t allocation_method:2;
+	uint8_t min_bitpool;
+	uint8_t max_bitpool;
+} __attribute__ ((packed)) a2dp_sbc_t;
+
+typedef struct {
+	uint8_t layer:3;
+	uint8_t crc:1;
+	uint8_t channel_mode:4;
+	uint8_t rfa:1;
+	uint8_t mpf:1;
+	uint8_t frequency:6;
+	uint16_t bitrate;
+} __attribute__ ((packed)) a2dp_mpeg_t;
+
+#else
+#error "Unknown byte order"
+#endif
diff --git a/audio/gsta2dpsink.c b/audio/gsta2dpsink.c
index 492fc63..ac63424 100644
--- a/audio/gsta2dpsink.c
+++ b/audio/gsta2dpsink.c
@@ -44,7 +44,8 @@ GST_DEBUG_CATEGORY_STATIC(gst_a2dp_sink_debug);
 enum {
 	PROP_0,
 	PROP_DEVICE,
-	PROP_AUTOCONNECT
+	PROP_AUTOCONNECT,
+	PROP_TRANSPORT
 };
 
 GST_BOILERPLATE(GstA2dpSink, gst_a2dp_sink, GstBin, GST_TYPE_BIN);
@@ -175,6 +176,16 @@ static void gst_a2dp_sink_set_property(GObject *object, guint prop_id,
 		self->device = g_value_dup_string(value);
 		break;
 
+	case PROP_TRANSPORT:
+		if (self->sink != NULL)
+			gst_avdtp_sink_set_transport(self->sink,
+				g_value_get_string(value));
+
+		if (self->transport != NULL)
+			g_free(self->transport);
+		self->transport = g_value_dup_string(value);
+		break;
+
 	case PROP_AUTOCONNECT:
 		self->autoconnect = g_value_get_boolean(value);
 
@@ -193,7 +204,7 @@ static void gst_a2dp_sink_get_property(GObject *object, guint prop_id,
 					GValue *value, GParamSpec *pspec)
 {
 	GstA2dpSink *self = GST_A2DP_SINK(object);
-	gchar *device;
+	gchar *device, *transport;
 
 	switch (prop_id) {
 	case PROP_DEVICE:
@@ -210,6 +221,13 @@ static void gst_a2dp_sink_get_property(GObject *object, guint prop_id,
 
 		g_value_set_boolean(value, self->autoconnect);
 		break;
+	case PROP_TRANSPORT:
+		if (self->sink != NULL) {
+			transport = gst_avdtp_sink_get_transport(self->sink);
+			if (transport != NULL)
+				g_value_take_string(value, transport);
+		}
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
 		break;
@@ -285,6 +303,10 @@ static GstStateChangeReturn gst_a2dp_sink_change_state(GstElement *element,
 			gst_avdtp_sink_set_device(self->sink,
 					self->device);
 
+		if (self->transport != NULL)
+			gst_avdtp_sink_set_transport(self->sink,
+					self->transport);
+
 		g_object_set(G_OBJECT(self->sink), "auto-connect",
 					self->autoconnect, NULL);
 
@@ -365,6 +387,11 @@ static void gst_a2dp_sink_class_init(GstA2dpSinkClass *klass)
 			"Automatically attempt to connect to device",
 			DEFAULT_AUTOCONNECT, G_PARAM_READWRITE));
 
+	g_object_class_install_property(object_class, PROP_TRANSPORT,
+			g_param_spec_string("transport", "Transport",
+			"Use configured transport",
+			NULL, G_PARAM_READWRITE));
+
 	GST_DEBUG_CATEGORY_INIT(gst_a2dp_sink_debug, "a2dpsink", 0,
 				"A2DP sink element");
 }
@@ -437,6 +464,7 @@ static gboolean gst_a2dp_sink_init_avdtp_sink(GstA2dpSink *self)
 	self->sink = GST_AVDTP_SINK(sink);
 	self->sink_is_in_bin = TRUE;
 	g_object_set(G_OBJECT(self->sink), "device", self->device, NULL);
+	g_object_set(G_OBJECT(self->sink), "transport", self->transport, NULL);
 
 	gst_element_set_state(sink, GST_STATE_PAUSED);
 
@@ -674,6 +702,7 @@ static void gst_a2dp_sink_init(GstA2dpSink *self,
 	self->fakesink = NULL;
 	self->rtp = NULL;
 	self->device = NULL;
+	self->transport = NULL;
 	self->autoconnect = DEFAULT_AUTOCONNECT;
 	self->capsfilter = NULL;
 	self->newseg_event = NULL;
diff --git a/audio/gsta2dpsink.h b/audio/gsta2dpsink.h
index 3ff4e45..3c4510e 100644
--- a/audio/gsta2dpsink.h
+++ b/audio/gsta2dpsink.h
@@ -53,6 +53,7 @@ struct _GstA2dpSink {
 	GstElement *fakesink;
 
 	gchar *device;
+	gchar *transport;
 	gboolean autoconnect;
 	gboolean sink_is_in_bin;
 
diff --git a/audio/gstavdtpsink.c b/audio/gstavdtpsink.c
index b8c8832..95c4811 100644
--- a/audio/gstavdtpsink.c
+++ b/audio/gstavdtpsink.c
@@ -37,8 +37,11 @@
 
 #include <gst/rtp/gstrtpbuffer.h>
 
+#include <dbus/dbus.h>
+
 #include "ipc.h"
 #include "rtp.h"
+#include "a2dp-codecs.h"
 
 #include "gstpragma.h"
 #include "gstavdtpsink.h"
@@ -61,11 +64,20 @@ GST_DEBUG_CATEGORY_STATIC(avdtp_sink_debug);
 		g_mutex_unlock(s->sink_lock);		\
 	} G_STMT_END
 
+#ifndef DBUS_TYPE_UNIX_FD
+#define DBUS_TYPE_UNIX_FD -1
+#endif
 
 struct bluetooth_data {
 	struct bt_get_capabilities_rsp *caps; /* Bluetooth device caps */
 	guint link_mtu;
 
+	DBusConnection *conn;
+	guint8 codec; /* Bluetooth transport configuration */
+	gchar *uuid;
+	guint8 *config;
+	gint config_size;
+
 	gchar buffer[BUFFER_SIZE];	/* Codec transfer buffer */
 };
 
@@ -75,7 +87,8 @@ struct bluetooth_data {
 enum {
 	PROP_0,
 	PROP_DEVICE,
-	PROP_AUTOCONNECT
+	PROP_AUTOCONNECT,
+	PROP_TRANSPORT
 };
 
 GST_BOILERPLATE(GstAvdtpSink, gst_avdtp_sink, GstBaseSink,
@@ -127,6 +140,23 @@ static void gst_avdtp_sink_base_init(gpointer g_class)
 	gst_element_class_set_details(element_class, &avdtp_sink_details);
 }
 
+static void gst_avdtp_sink_transport_release(GstAvdtpSink *self)
+{
+	DBusMessage *msg;
+	const char *access_type = "w";
+
+	msg = dbus_message_new_method_call("org.bluez", self->transport,
+						"org.bluez.MediaTransport",
+						"Release");
+
+	dbus_message_append_args(msg, DBUS_TYPE_STRING, &access_type,
+					DBUS_TYPE_INVALID);
+
+	dbus_connection_send(self->data->conn, msg, NULL);
+
+	dbus_message_unref(msg);
+}
+
 static gboolean gst_avdtp_sink_stop(GstBaseSink *basesink)
 {
 	GstAvdtpSink *self = GST_AVDTP_SINK(basesink);
@@ -151,6 +181,10 @@ static gboolean gst_avdtp_sink_stop(GstBaseSink *basesink)
 	}
 
 	if (self->data) {
+		if (self->transport)
+			gst_avdtp_sink_transport_release(self);
+		if (self->data->conn)
+			dbus_connection_unref(self->data->conn);
 		g_free(self->data);
 		self->data = NULL;
 	}
@@ -178,6 +212,9 @@ static void gst_avdtp_sink_finalize(GObject *object)
 	if (self->device)
 		g_free(self->device);
 
+	if (self->transport)
+		g_free(self->transport);
+
 	g_mutex_free(self->sink_lock);
 
 	G_OBJECT_CLASS(parent_class)->finalize(object);
@@ -198,6 +235,13 @@ static void gst_avdtp_sink_set_property(GObject *object, guint prop_id,
 	case PROP_AUTOCONNECT:
 		sink->autoconnect = g_value_get_boolean(value);
 		break;
+
+	case PROP_TRANSPORT:
+		if (sink->transport)
+			g_free(sink->transport);
+		sink->transport = g_value_dup_string(value);
+		break;
+
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
 		break;
@@ -217,6 +261,11 @@ static void gst_avdtp_sink_get_property(GObject *object, guint prop_id,
 	case PROP_AUTOCONNECT:
 		g_value_set_boolean(value, sink->autoconnect);
 		break;
+
+	case PROP_TRANSPORT:
+		g_value_set_string(value, sink->transport);
+		break;
+
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
 		break;
@@ -370,6 +419,10 @@ static gboolean gst_avdtp_sink_conf_recv_stream_fd(
 	GIOFlags flags;
 	gsize read;
 
+	/* Proceed if stream was already acquired */
+	if (self->stream != NULL)
+		goto proceed;
+
 	ret = gst_avdtp_sink_bluetooth_recvmsg_fd(self);
 	if (ret < 0)
 		return FALSE;
@@ -380,6 +433,7 @@ static gboolean gst_avdtp_sink_conf_recv_stream_fd(
 		return FALSE;
 	}
 
+proceed:
 	/* set stream socket to nonblock */
 	GST_LOG_OBJECT(self, "setting stream socket to nonblock");
 	flags = g_io_channel_get_flags(self->stream);
@@ -733,6 +787,325 @@ static GstStructure *gst_avdtp_sink_parse_mpeg_caps(
 	return structure;
 }
 
+static GstStructure *gst_avdtp_sink_parse_sbc_raw(GstAvdtpSink *self)
+{
+	a2dp_sbc_t *sbc = (a2dp_sbc_t *) self->data->config;
+	GstStructure *structure;
+	GValue *value;
+	GValue *list;
+	gboolean mono, stereo;
+
+	structure = gst_structure_empty_new("audio/x-sbc");
+	value = g_value_init(g_new0(GValue, 1), G_TYPE_STRING);
+
+	/* mode */
+	list = g_value_init(g_new0(GValue, 1), GST_TYPE_LIST);
+	if (sbc->channel_mode & BT_A2DP_CHANNEL_MODE_MONO) {
+		g_value_set_static_string(value, "mono");
+		gst_value_list_prepend_value(list, value);
+	}
+	if (sbc->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO) {
+		g_value_set_static_string(value, "stereo");
+		gst_value_list_prepend_value(list, value);
+	}
+	if (sbc->channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL) {
+		g_value_set_static_string(value, "dual");
+		gst_value_list_prepend_value(list, value);
+	}
+	if (sbc->channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO) {
+		g_value_set_static_string(value, "joint");
+		gst_value_list_prepend_value(list, value);
+	}
+	g_value_unset(value);
+	if (list) {
+		gst_structure_set_value(structure, "mode", list);
+		g_free(list);
+		list = NULL;
+	}
+
+	/* subbands */
+	list = g_value_init(g_new0(GValue, 1), GST_TYPE_LIST);
+	value = g_value_init(value, G_TYPE_INT);
+	if (sbc->subbands & BT_A2DP_SUBBANDS_4) {
+		g_value_set_int(value, 4);
+		gst_value_list_prepend_value(list, value);
+	}
+	if (sbc->subbands & BT_A2DP_SUBBANDS_8) {
+		g_value_set_int(value, 8);
+		gst_value_list_prepend_value(list, value);
+	}
+	g_value_unset(value);
+	if (list) {
+		gst_structure_set_value(structure, "subbands", list);
+		g_free(list);
+		list = NULL;
+	}
+
+	/* blocks */
+	value = g_value_init(value, G_TYPE_INT);
+	list = g_value_init(g_new0(GValue, 1), GST_TYPE_LIST);
+	if (sbc->block_length & BT_A2DP_BLOCK_LENGTH_16) {
+		g_value_set_int(value, 16);
+		gst_value_list_prepend_value(list, value);
+	}
+	if (sbc->block_length & BT_A2DP_BLOCK_LENGTH_12) {
+		g_value_set_int(value, 12);
+		gst_value_list_prepend_value(list, value);
+	}
+	if (sbc->block_length & BT_A2DP_BLOCK_LENGTH_8) {
+		g_value_set_int(value, 8);
+		gst_value_list_prepend_value(list, value);
+	}
+	if (sbc->block_length & BT_A2DP_BLOCK_LENGTH_4) {
+		g_value_set_int(value, 4);
+		gst_value_list_prepend_value(list, value);
+	}
+	g_value_unset(value);
+	if (list) {
+		gst_structure_set_value(structure, "blocks", list);
+		g_free(list);
+		list = NULL;
+	}
+
+	/* allocation */
+	g_value_init(value, G_TYPE_STRING);
+	list = g_value_init(g_new0(GValue,1), GST_TYPE_LIST);
+	if (sbc->allocation_method & BT_A2DP_ALLOCATION_LOUDNESS) {
+		g_value_set_static_string(value, "loudness");
+		gst_value_list_prepend_value(list, value);
+	}
+	if (sbc->allocation_method & BT_A2DP_ALLOCATION_SNR) {
+		g_value_set_static_string(value, "snr");
+		gst_value_list_prepend_value(list, value);
+	}
+	g_value_unset(value);
+	if (list) {
+		gst_structure_set_value(structure, "allocation", list);
+		g_free(list);
+		list = NULL;
+	}
+
+	/* rate */
+	g_value_init(value, G_TYPE_INT);
+	list = g_value_init(g_new0(GValue, 1), GST_TYPE_LIST);
+	if (sbc->frequency & BT_SBC_SAMPLING_FREQ_48000) {
+		g_value_set_int(value, 48000);
+		gst_value_list_prepend_value(list, value);
+	}
+	if (sbc->frequency & BT_SBC_SAMPLING_FREQ_44100) {
+		g_value_set_int(value, 44100);
+		gst_value_list_prepend_value(list, value);
+	}
+	if (sbc->frequency & BT_SBC_SAMPLING_FREQ_32000) {
+		g_value_set_int(value, 32000);
+		gst_value_list_prepend_value(list, value);
+	}
+	if (sbc->frequency & BT_SBC_SAMPLING_FREQ_16000) {
+		g_value_set_int(value, 16000);
+		gst_value_list_prepend_value(list, value);
+	}
+	g_value_unset(value);
+	if (list) {
+		gst_structure_set_value(structure, "rate", list);
+		g_free(list);
+		list = NULL;
+	}
+
+	/* bitpool */
+	value = g_value_init(value, GST_TYPE_INT_RANGE);
+	gst_value_set_int_range(value,
+			MIN(sbc->min_bitpool, TEMPLATE_MAX_BITPOOL),
+			MIN(sbc->max_bitpool, TEMPLATE_MAX_BITPOOL));
+	gst_structure_set_value(structure, "bitpool", value);
+	g_value_unset(value);
+
+	/* channels */
+	mono = FALSE;
+	stereo = FALSE;
+	if (sbc->channel_mode & BT_A2DP_CHANNEL_MODE_MONO)
+		mono = TRUE;
+	if ((sbc->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO) ||
+			(sbc->channel_mode &
+			BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL) ||
+			(sbc->channel_mode &
+			BT_A2DP_CHANNEL_MODE_JOINT_STEREO))
+		stereo = TRUE;
+
+	if (mono && stereo) {
+		g_value_init(value, GST_TYPE_INT_RANGE);
+		gst_value_set_int_range(value, 1, 2);
+	} else {
+		g_value_init(value, G_TYPE_INT);
+		if (mono)
+			g_value_set_int(value, 1);
+		else if (stereo)
+			g_value_set_int(value, 2);
+		else {
+			GST_ERROR_OBJECT(self,
+				"Unexpected number of channels");
+			g_value_set_int(value, 0);
+		}
+	}
+
+	gst_structure_set_value(structure, "channels", value);
+	g_free(value);
+
+	return structure;
+}
+
+static GstStructure *gst_avdtp_sink_parse_mpeg_raw(GstAvdtpSink *self)
+{
+	a2dp_mpeg_t *mpeg = (a2dp_mpeg_t *) self->data->config;
+	GstStructure *structure;
+	GValue *value;
+	GValue *list;
+	gboolean valid_layer = FALSE;
+	gboolean mono, stereo;
+
+	GST_LOG_OBJECT(self, "parsing mpeg caps");
+
+	structure = gst_structure_empty_new("audio/mpeg");
+	value = g_new0(GValue, 1);
+	g_value_init(value, G_TYPE_INT);
+
+	list = g_value_init(g_new0(GValue, 1), GST_TYPE_LIST);
+	g_value_set_int(value, 1);
+	gst_value_list_prepend_value(list, value);
+	g_value_set_int(value, 2);
+	gst_value_list_prepend_value(list, value);
+	gst_structure_set_value(structure, "mpegversion", list);
+	g_free(list);
+
+	/* layer */
+	GST_LOG_OBJECT(self, "setting mpeg layer");
+	list = g_value_init(g_new0(GValue, 1), GST_TYPE_LIST);
+	if (mpeg->layer & BT_MPEG_LAYER_1) {
+		g_value_set_int(value, 1);
+		gst_value_list_prepend_value(list, value);
+		valid_layer = TRUE;
+	}
+	if (mpeg->layer & BT_MPEG_LAYER_2) {
+		g_value_set_int(value, 2);
+		gst_value_list_prepend_value(list, value);
+		valid_layer = TRUE;
+	}
+	if (mpeg->layer & BT_MPEG_LAYER_3) {
+		g_value_set_int(value, 3);
+		gst_value_list_prepend_value(list, value);
+		valid_layer = TRUE;
+	}
+	if (list) {
+		gst_structure_set_value(structure, "layer", list);
+		g_free(list);
+		list = NULL;
+	}
+
+	if (!valid_layer) {
+		gst_structure_free(structure);
+		g_free(value);
+		return NULL;
+	}
+
+	/* rate */
+	GST_LOG_OBJECT(self, "setting mpeg rate");
+	list = g_value_init(g_new0(GValue, 1), GST_TYPE_LIST);
+	if (mpeg->frequency & BT_MPEG_SAMPLING_FREQ_48000) {
+		g_value_set_int(value, 48000);
+		gst_value_list_prepend_value(list, value);
+	}
+	if (mpeg->frequency & BT_MPEG_SAMPLING_FREQ_44100) {
+		g_value_set_int(value, 44100);
+		gst_value_list_prepend_value(list, value);
+	}
+	if (mpeg->frequency & BT_MPEG_SAMPLING_FREQ_32000) {
+		g_value_set_int(value, 32000);
+		gst_value_list_prepend_value(list, value);
+	}
+	if (mpeg->frequency & BT_MPEG_SAMPLING_FREQ_24000) {
+		g_value_set_int(value, 24000);
+		gst_value_list_prepend_value(list, value);
+	}
+	if (mpeg->frequency & BT_MPEG_SAMPLING_FREQ_22050) {
+		g_value_set_int(value, 22050);
+		gst_value_list_prepend_value(list, value);
+	}
+	if (mpeg->frequency & BT_MPEG_SAMPLING_FREQ_16000) {
+		g_value_set_int(value, 16000);
+		gst_value_list_prepend_value(list, value);
+	}
+	g_value_unset(value);
+	if (list) {
+		gst_structure_set_value(structure, "rate", list);
+		g_free(list);
+		list = NULL;
+	}
+
+	/* channels */
+	GST_LOG_OBJECT(self, "setting mpeg channels");
+	mono = FALSE;
+	stereo = FALSE;
+	if (mpeg->channel_mode & BT_A2DP_CHANNEL_MODE_MONO)
+		mono = TRUE;
+	if ((mpeg->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO) ||
+			(mpeg->channel_mode &
+			BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL) ||
+			(mpeg->channel_mode &
+			BT_A2DP_CHANNEL_MODE_JOINT_STEREO))
+		stereo = TRUE;
+
+	if (mono && stereo) {
+		g_value_init(value, GST_TYPE_INT_RANGE);
+		gst_value_set_int_range(value, 1, 2);
+	} else {
+		g_value_init(value, G_TYPE_INT);
+		if (mono)
+			g_value_set_int(value, 1);
+		else if (stereo)
+			g_value_set_int(value, 2);
+		else {
+			GST_ERROR_OBJECT(self,
+				"Unexpected number of channels");
+			g_value_set_int(value, 0);
+		}
+	}
+	gst_structure_set_value(structure, "channels", value);
+	g_free(value);
+
+	return structure;
+}
+
+static gboolean gst_avdtp_sink_update_config(GstAvdtpSink *self)
+{
+	GstStructure *structure;
+	gchar *tmp;
+
+	switch (self->data->codec) {
+	case A2DP_CODEC_SBC:
+		structure = gst_avdtp_sink_parse_sbc_raw(self);
+		break;
+	case A2DP_CODEC_MPEG12:
+		structure = gst_avdtp_sink_parse_mpeg_raw(self);
+		break;
+	default:
+		GST_ERROR_OBJECT(self, "Unsupported configuration");
+		return FALSE;
+	}
+
+	if (structure == NULL)
+		return FALSE;
+
+	if (self->dev_caps != NULL)
+		gst_caps_unref(self->dev_caps);
+
+	self->dev_caps = gst_caps_new_full(structure, NULL);
+
+	tmp = gst_caps_to_string(self->dev_caps);
+	GST_DEBUG_OBJECT(self, "Transport configuration: %s", tmp);
+	g_free(tmp);
+
+	return TRUE;
+}
+
 static gboolean gst_avdtp_sink_update_caps(GstAvdtpSink *self)
 {
 	sbc_capabilities_t *sbc;
@@ -743,6 +1116,9 @@ static gboolean gst_avdtp_sink_update_caps(GstAvdtpSink *self)
 
 	GST_LOG_OBJECT(self, "updating device caps");
 
+	if (self->data->config_size != 0 && self->data->config != NULL)
+		return gst_avdtp_sink_update_config(self);
+
 	sbc = (void *) gst_avdtp_find_caps(self, BT_A2DP_SBC_SINK);
 	mpeg = (void *) gst_avdtp_find_caps(self, BT_A2DP_MPEG12_SINK);
 
@@ -870,6 +1246,192 @@ static gboolean gst_avdtp_sink_event(GstBaseSink *basesink,
 	return TRUE;
 }
 
+static gboolean gst_avdtp_sink_transport_parse_property(GstAvdtpSink *self,
+							DBusMessageIter *i)
+{
+	const char *key;
+	DBusMessageIter variant_i;
+
+	if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_STRING) {
+		GST_ERROR_OBJECT(self, "Property name not a string.");
+		return FALSE;
+	}
+
+	dbus_message_iter_get_basic(i, &key);
+
+	if (!dbus_message_iter_next(i))  {
+		GST_ERROR_OBJECT(self, "Property value missing");
+		return FALSE;
+	}
+
+	if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_VARIANT) {
+		GST_ERROR_OBJECT(self, "Property value not a variant.");
+		return FALSE;
+	}
+
+	dbus_message_iter_recurse(i, &variant_i);
+
+	switch (dbus_message_iter_get_arg_type(&variant_i)) {
+	case DBUS_TYPE_BYTE: {
+		uint8_t value;
+		dbus_message_iter_get_basic(&variant_i, &value);
+
+		if (g_str_equal(key, "Codec") == TRUE)
+			self->data->codec = value;
+
+		break;
+	}
+	case DBUS_TYPE_UINT16: {
+		uint16_t value;
+		dbus_message_iter_get_basic(&variant_i, &value);
+
+		if (g_str_equal(key, "OMTU") == TRUE)
+			self->data->link_mtu = value;
+
+		break;
+	}
+        case DBUS_TYPE_STRING: {
+		const char *value;
+		dbus_message_iter_get_basic(&variant_i, &value);
+
+		if (g_str_equal(key, "UUID") == TRUE) {
+			g_free(self->data->uuid);
+			self->data->uuid = g_strdup(value);
+		}
+
+		break;
+	}
+	case DBUS_TYPE_ARRAY: {
+		DBusMessageIter array_i;
+		char *value;
+		int size;
+
+		dbus_message_iter_recurse(&variant_i, &array_i);
+		dbus_message_iter_get_fixed_array(&array_i, &value, &size);
+
+		if (g_str_equal(key, "Configuration")) {
+			g_free(self->data->config);
+			self->data->config = g_new0(guint8, size);
+			self->data->config_size = size;
+			memcpy(self->data->config, value, size);
+		}
+
+		break;
+	}
+	}
+
+	return TRUE;
+}
+
+static gboolean gst_avdtp_sink_transport_acquire(GstAvdtpSink *self)
+{
+	DBusMessage *msg, *reply;
+	DBusError err;
+	const char *access_type = "w";
+	int fd;
+
+	dbus_error_init(&err);
+
+	if (self->data->conn == NULL)
+		self->data->conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
+
+	msg = dbus_message_new_method_call("org.bluez", self->transport,
+						"org.bluez.MediaTransport",
+						"Acquire");
+
+	dbus_message_append_args(msg, DBUS_TYPE_STRING, &access_type,
+					DBUS_TYPE_INVALID);
+
+	reply = dbus_connection_send_with_reply_and_block(self->data->conn,
+							msg, -1, &err);
+
+	if (dbus_error_is_set(&err))
+		goto fail;
+
+	if (dbus_message_get_args(reply, &err, DBUS_TYPE_UNIX_FD, &fd,
+					DBUS_TYPE_INVALID) == FALSE)
+		goto fail;
+
+	dbus_message_unref(reply);
+
+	self->stream = g_io_channel_unix_new(fd);
+	g_io_channel_set_close_on_unref(self->stream, TRUE);
+	GST_DEBUG_OBJECT(self, "stream_fd=%d", fd);
+
+	return TRUE;
+
+fail:
+	GST_ERROR_OBJECT(self, "Failed to acquire transport stream: %s",
+				err.message);
+
+	dbus_error_free(&err);
+
+	if (reply)
+		dbus_message_unref(msg);
+
+	return FALSE;
+}
+
+static gboolean gst_avdtp_sink_transport_get_properties(GstAvdtpSink *self)
+{
+	DBusMessage *msg, *reply;
+	DBusMessageIter arg_i, ele_i;
+	DBusError err;
+
+	dbus_error_init(&err);
+
+	/* Transport need to be acquire first to make sure the MTUs are
+	   available */
+	if (gst_avdtp_sink_transport_acquire(self) == FALSE)
+		return FALSE;
+
+	msg = dbus_message_new_method_call("org.bluez", self->transport,
+						"org.bluez.MediaTransport",
+						"GetProperties");
+	reply = dbus_connection_send_with_reply_and_block(self->data->conn,
+							msg, -1, &err);
+
+	if (dbus_error_is_set(&err) || reply == NULL) {
+		GST_ERROR_OBJECT(self, "Failed to get transport properties: %s",
+					err.message);
+		goto fail;
+	}
+
+	if (!dbus_message_iter_init(reply, &arg_i)) {
+		GST_ERROR_OBJECT(self, "GetProperties reply has no arguments.");
+		goto fail;
+	}
+
+	if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_ARRAY) {
+		GST_ERROR_OBJECT(self, "GetProperties argument is not an array.");
+		goto fail;
+	}
+
+	dbus_message_iter_recurse(&arg_i, &ele_i);
+	while (dbus_message_iter_get_arg_type(&ele_i) != DBUS_TYPE_INVALID) {
+
+		if (dbus_message_iter_get_arg_type(&ele_i) ==
+				DBUS_TYPE_DICT_ENTRY) {
+			DBusMessageIter dict_i;
+
+			dbus_message_iter_recurse(&ele_i, &dict_i);
+
+			gst_avdtp_sink_transport_parse_property(self, &dict_i);
+		}
+
+		if (!dbus_message_iter_next(&ele_i))
+			break;
+	}
+
+	return gst_avdtp_sink_update_caps(self);
+
+fail:
+	dbus_message_unref(msg);
+	dbus_message_unref(reply);
+	return FALSE;
+
+}
+
 static gboolean gst_avdtp_sink_start(GstBaseSink *basesink)
 {
 	GstAvdtpSink *self = GST_AVDTP_SINK(basesink);
@@ -878,6 +1440,16 @@ static gboolean gst_avdtp_sink_start(GstBaseSink *basesink)
 
 	GST_INFO_OBJECT(self, "start");
 
+	self->data = g_new0(struct bluetooth_data, 1);
+
+	self->stream = NULL;
+	self->stream_caps = NULL;
+	self->mp3_using_crc = -1;
+	self->channel_mode = -1;
+
+	if (self->transport != NULL)
+		return gst_avdtp_sink_transport_get_properties(self);
+
 	self->watch_id = 0;
 
 	sk = bt_audio_service_open();
@@ -892,13 +1464,6 @@ static gboolean gst_avdtp_sink_start(GstBaseSink *basesink)
 	self->watch_id = g_io_add_watch(self->server, G_IO_HUP | G_IO_ERR |
 					G_IO_NVAL, server_callback, self);
 
-	self->data = g_new0(struct bluetooth_data, 1);
-
-	self->stream = NULL;
-	self->stream_caps = NULL;
-	self->mp3_using_crc = -1;
-	self->channel_mode = -1;
-
 	if (!gst_avdtp_sink_get_capabilities(self)) {
 		GST_ERROR_OBJECT(self, "failed to get capabilities "
 				"from device");
@@ -920,6 +1485,9 @@ static gboolean gst_avdtp_sink_stream_start(GstAvdtpSink *self)
 	struct bt_new_stream_ind *ind = (void *) buf;
 	GIOError io_error;
 
+	if (self->transport != NULL)
+		return gst_avdtp_sink_conf_recv_stream_fd(self);
+
 	memset(req, 0, sizeof(buf));
 	req->h.type = BT_REQUEST;
 	req->h.name = BT_START_STREAM;
@@ -1051,6 +1619,10 @@ static gboolean gst_avdtp_sink_configure(GstAvdtpSink *self,
 	GST_DEBUG_OBJECT(self, "configuring device with caps: %s", temp);
 	g_free(temp);
 
+	/* Transport already configured */
+	if (self->transport != NULL)
+		return TRUE;
+
 	structure = gst_caps_get_structure(caps, 0);
 
 	if (gst_structure_has_name(structure, "audio/x-sbc"))
@@ -1237,6 +1809,12 @@ static void gst_avdtp_sink_class_init(GstAvdtpSinkClass *klass)
 					"to device", DEFAULT_AUTOCONNECT,
 					G_PARAM_READWRITE));
 
+	g_object_class_install_property(object_class, PROP_TRANSPORT,
+					g_param_spec_string("transport",
+					"Transport",
+					"Use configured transport",
+					NULL, G_PARAM_READWRITE));
+
 	GST_DEBUG_CATEGORY_INIT(avdtp_sink_debug, "avdtpsink", 0,
 				"A2DP headset sink element");
 }
@@ -1245,6 +1823,7 @@ static void gst_avdtp_sink_init(GstAvdtpSink *self,
 			GstAvdtpSinkClass *klass)
 {
 	self->device = NULL;
+	self->transport = NULL;
 	self->data = NULL;
 
 	self->stream = NULL;
@@ -1400,11 +1979,25 @@ void gst_avdtp_sink_set_device(GstAvdtpSink *self, const gchar *dev)
 	self->device = g_strdup(dev);
 }
 
+void gst_avdtp_sink_set_transport(GstAvdtpSink *self, const gchar *trans)
+{
+	if (self->transport != NULL)
+		g_free(self->transport);
+
+	GST_LOG_OBJECT(self, "Setting transport: %s", trans);
+	self->transport = g_strdup(trans);
+}
+
 gchar *gst_avdtp_sink_get_device(GstAvdtpSink *self)
 {
 	return g_strdup(self->device);
 }
 
+gchar *gst_avdtp_sink_get_transport(GstAvdtpSink *self)
+{
+	return g_strdup(self->transport);
+}
+
 void gst_avdtp_sink_set_crc(GstAvdtpSink *self, gboolean crc)
 {
 	gint new_crc;
diff --git a/audio/gstavdtpsink.h b/audio/gstavdtpsink.h
index eb78248..888169f 100644
--- a/audio/gstavdtpsink.h
+++ b/audio/gstavdtpsink.h
@@ -51,6 +51,7 @@ struct _GstAvdtpSink {
 	GstBaseSink sink;
 
 	gchar *device;
+	gchar *transport;
 	GIOChannel *stream;
 
 	struct bluetooth_data *data;
@@ -86,8 +87,13 @@ guint gst_avdtp_sink_get_link_mtu(GstAvdtpSink *sink);
 void gst_avdtp_sink_set_device(GstAvdtpSink *sink,
 		const gchar* device);
 
+void gst_avdtp_sink_set_transport(GstAvdtpSink *sink,
+		const gchar *transport);
+
 gchar *gst_avdtp_sink_get_device(GstAvdtpSink *sink);
 
+gchar *gst_avdtp_sink_get_transport(GstAvdtpSink *sink);
+
 gboolean gst_avdtp_sink_plugin_init(GstPlugin *plugin);
 
 void gst_avdtp_sink_set_crc(GstAvdtpSink *self, gboolean crc);
-- 
1.7.1


^ permalink raw reply related

* [PATCH 03/10] Add option to enable/disable unix ipc via audio.conf
From: Luiz Augusto von Dentz @ 2010-09-13 14:15 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1284387337-18822-1-git-send-email-luiz.dentz@gmail.com>

From: Luiz Augusto Von Dentz <luiz.dentz-von@nokia.com>

---
 audio/main.c    |    9 ---------
 audio/manager.c |   12 ++++++++++++
 audio/manager.h |    1 +
 3 files changed, 13 insertions(+), 9 deletions(-)

diff --git a/audio/main.c b/audio/main.c
index 9d316ec..745c307 100644
--- a/audio/main.c
+++ b/audio/main.c
@@ -42,7 +42,6 @@
 #include "plugin.h"
 #include "log.h"
 #include "device.h"
-#include "unix.h"
 #include "headset.h"
 #include "manager.h"
 #include "gateway.h"
@@ -151,11 +150,6 @@ static int audio_init(void)
 
 	config = load_config_file(CONFIGDIR "/audio.conf");
 
-	if (unix_init() < 0) {
-		error("Unable to setup unix socket");
-		goto failed;
-	}
-
 	if (audio_manager_init(connection, config, &enable_sco) < 0)
 		goto failed;
 
@@ -174,7 +168,6 @@ static int audio_init(void)
 
 failed:
 	audio_manager_exit();
-	unix_exit();
 
 	if (connection) {
 		dbus_connection_unref(connection);
@@ -194,8 +187,6 @@ static void audio_exit(void)
 
 	audio_manager_exit();
 
-	unix_exit();
-
 	dbus_connection_unref(connection);
 }
 
diff --git a/audio/manager.c b/audio/manager.c
index 3db5987..87e7a2a 100644
--- a/audio/manager.c
+++ b/audio/manager.c
@@ -70,6 +70,7 @@
 #include "manager.h"
 #include "sdpd.h"
 #include "telephony.h"
+#include "unix.h"
 
 typedef enum {
 	HEADSET	= 1 << 0,
@@ -113,6 +114,7 @@ static struct enabled_interfaces enabled = {
 	.sink		= TRUE,
 	.source		= FALSE,
 	.control	= TRUE,
+	.socket		= TRUE,
 };
 
 static struct audio_adapter *find_adapter(GSList *list,
@@ -1074,6 +1076,8 @@ int audio_manager_init(DBusConnection *conn, GKeyFile *conf,
 			enabled.source = TRUE;
 		else if (g_str_equal(list[i], "Control"))
 			enabled.control = TRUE;
+		else if (g_str_equal(list[i], "Socket"))
+			enabled.socket = TRUE;
 	}
 	g_strfreev(list);
 
@@ -1090,6 +1094,8 @@ int audio_manager_init(DBusConnection *conn, GKeyFile *conf,
 			enabled.source = FALSE;
 		else if (g_str_equal(list[i], "Control"))
 			enabled.control = FALSE;
+		else if (g_str_equal(list[i], "Socket"))
+			enabled.socket = FALSE;
 	}
 	g_strfreev(list);
 
@@ -1117,6 +1123,9 @@ int audio_manager_init(DBusConnection *conn, GKeyFile *conf,
 		max_connected_headsets = i;
 
 proceed:
+	if (enabled.socket)
+		unix_init();
+
 	if (enabled.headset) {
 		telephony_init();
 		btd_register_adapter_driver(&headset_server_driver);
@@ -1152,6 +1161,9 @@ void audio_manager_exit(void)
 		config = NULL;
 	}
 
+	if (enabled.socket)
+		unix_exit();
+
 	if (enabled.headset) {
 		btd_unregister_adapter_driver(&headset_server_driver);
 		telephony_exit();
diff --git a/audio/manager.h b/audio/manager.h
index 90fe6f0..c79b761 100644
--- a/audio/manager.h
+++ b/audio/manager.h
@@ -29,6 +29,7 @@ struct enabled_interfaces {
 	gboolean sink;
 	gboolean source;
 	gboolean control;
+	gboolean socket;
 };
 
 int audio_manager_init(DBusConnection *conn, GKeyFile *config,
-- 
1.7.1


^ permalink raw reply related

* [PATCH 02/10] Add rule to enabling talking to org.bluez.MediaEndpoint
From: Luiz Augusto von Dentz @ 2010-09-13 14:15 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1284387337-18822-1-git-send-email-luiz.dentz@gmail.com>

From: Luiz Augusto Von Dentz <luiz.dentz-von@nokia.com>

---
 src/bluetooth.conf |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/src/bluetooth.conf b/src/bluetooth.conf
index 56e7a83..354e5e0 100644
--- a/src/bluetooth.conf
+++ b/src/bluetooth.conf
@@ -12,6 +12,7 @@
     <allow send_destination="org.bluez"/>
     <allow send_interface="org.bluez.Agent"/>
     <allow send_interface="org.bluez.HandsfreeAgent"/>
+    <allow send_interface="org.bluez.MediaEndpoint"/>
   </policy>
 
   <policy at_console="true">
-- 
1.7.1


^ permalink raw reply related

* [PATCH 01/10] Add media API documentation
From: Luiz Augusto von Dentz @ 2010-09-13 14:15 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1284387337-18822-1-git-send-email-luiz.dentz@gmail.com>

From: Luiz Augusto von Dentz <luiz.dentz-von@nokia.com>

Media API is a replacement for the internal audio IPC which is no longer
necessary as DBus 1.3 and newer are capable of transfering file
descriptors.
---
 doc/media-api.txt |  169 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 169 insertions(+), 0 deletions(-)
 create mode 100644 doc/media-api.txt

diff --git a/doc/media-api.txt b/doc/media-api.txt
new file mode 100644
index 0000000..94fc62f
--- /dev/null
+++ b/doc/media-api.txt
@@ -0,0 +1,169 @@
+BlueZ D-Bus Media API description
+*********************************
+
+Media hierarchy
+===============
+
+Service		org.bluez
+Interface	org.bluez.Media
+Object path	[variable prefix]/{hci0,hci1,...}
+
+Methods		void RegisterEndpoint(object endpoint, dict properties)
+
+			Register a local end point to sender, the sender can
+			register as many end points as it likes.
+
+			Note: If the sender disconnects the end points are
+			automatically unregistered.
+
+			possible properties:
+
+				string UUID:
+
+					UUID of the profile which the endpoint
+					is for.
+
+				byte Codec:
+
+					Assigned mumber of codec that the
+					endpoint implements. The values should
+					match the profile specification which
+					is indicated by the UUID.
+
+				array{byte} Capabilities:
+
+					Capabilities blob, it is used as it is
+					so the size and byte order must match.
+
+		void UnregisterEndpoint(object endpoint)
+
+			Unregister sender end point.
+
+MediaEndpoint hierarchy
+=======================
+
+Service		unique name
+Interface	org.bluez.MediaEndpoint
+Object path	freely definable
+
+Methods		void SetConfiguration(object transport, array{byte} configuration)
+
+			Set configuration for the transport.
+
+		array{byte} SelectConfiguration(array{byte} capabilities)
+
+			Select preferable configuration from the supported
+			capabilities.
+
+			Returns a configuration which can be used to setup
+			a transport.
+
+			Note: There is no need to cache the selected
+			configuration since on success the configuration is
+			send back as parameter of SetConfiguration.
+
+		void ClearConfiguration()
+
+			Clear any configuration set.
+
+		void Release()
+
+			This method gets called when the service daemon
+			unregisters the endpoint. An endpoint can use it to do
+			cleanup tasks. There is no need to unregister the
+			endpoint, because when this method gets called it has
+			already been unregistered.
+
+MediaTransport hierarchy
+========================
+
+Service		org.bluez
+Interface	org.bluez.MediaTransport
+Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/fdX
+
+Methods		dict GetProperties()
+
+			Returns all properties for the interface. See the
+			properties section for available properties.
+
+		fd Acquire(string accesstype)
+
+			Acquire transport file descriptor.
+
+			possible accesstype:
+
+				"r" : Read only access
+
+				"w" : Write only access
+
+				"rw": Read and write access
+
+		void Release(string accesstype)
+
+			Releases file descriptor.
+
+		void SetProperty(string name, variant value)
+
+			Changes the value of the specified property. Only
+			properties that are listed a read-write can be changed.
+
+			On success this will emit a PropertyChanged signal.
+
+Signals		void PropertyChanged(string name, variant value)
+
+			This signal indicates a changed value of the given
+			property.
+
+Properties	object Device [readonly]
+
+			Device object which the transport is connected to.
+
+		boolean ReadLock [readonly]
+
+			Transport read lock.
+
+		boolean WriteLock [readonly]
+
+			Transport read lock.
+
+		uint16 IMTU [readonly]
+
+			Transport input MTU.
+
+		uint16 OMTU [readonly]
+
+			Transport output MTU.
+
+		string UUID [readonly]
+
+			UUID of the profile which the transport is for.
+
+		byte Codec [readonly]
+
+			Assigned mumber of codec that the transport support.
+			The values should match the profile specification which
+			is indicated by the UUID.
+
+		array{byte} Configuration [readonly]
+
+			Configuration blob, it is used as it is so the size and
+			byte order must match.
+
+		uint16 Delay [readwrite]
+
+			Optional. Transport delay in 1/10 of milisecond, this
+			property is only writeable when the transport was
+			acquired by the sender.
+
+		boolean NREC [readwrite]
+
+			Optional. Indicates if echo cancelling and noise
+			reduction functions are active in the transport, this
+			property is only writeable when the transport was
+			acquired by the sender.
+
+		boolean InbandRingtone [readwrite]
+
+			Optional. Indicates if the transport support sending
+			ringtones, this property is only writeable when the
+			transport was acquired by the sender.
-- 
1.7.1


^ permalink raw reply related

* [PATCH 00/10] Media API
From: Luiz Augusto von Dentz @ 2010-09-13 14:15 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.dentz-von@nokia.com>

Hi,

Now that DBus 1.4 has finally been released I guess it is time to integrate
the Media API that I've been working since the beginning of the year. For
those not aware of what it is about the discussion can be found here:

  http://thread.gmane.org/gmane.linux.bluez.kernel/4125

For now it is disabled by default to avoid a build dependency on DBus 1.4 and
to buy some time while Im working to getting it working reliably with
PulseAudio. To enable it just add the following to /etc/bluetooth/audio.conf
(won't work if DBus is < 1.3 but better use 1.3.1 or latter):

  Enable=<...,>Media

It can be used together with old unix socket, but I also add the possibility to
complete disable it by doing (highly suggested if the system is running PA):

  Disable=<...,>Socket

To register endpoint test/simple-endpoint can be used, note that it will not
stream anything, it basically configure a transport object which can be used by
e.g. gstreamer plugin:

  $./simple-endpoint
   dbus.Dictionary({'Codec': dbus.Byte(0), 'UUID': '0000110A-0000-1000-8000-00805F9B34FB', 'DelayReporting': True, 'Capabilities': dbus.Array([dbus.Byte(255), dbus.Byte(255), dbus.Byte(2), dbus.Byte(64)], signature=None)}, signature=None)
   SelectConfiguration (dbus.Array([dbus.Byte(255), dbus.Byte(255), dbus.Byte(2), dbus.Byte(32)], signature=dbus.Signature('y')))
   SetConfiguration (/org/bluez/16530/hci0/dev_00_0D_3C_B1_DD_56/fd0, dbus.Array([dbus.Byte(33), dbus.Byte(21), dbus.Byte(2), dbus.Byte(32)], signature=dbus.Signature('y')))

  $gst-launch-0.10 filesrc location=<file to stream> ! decodebin ! audioconvert ! sbcenc ! a2dpsink transport=/org/bluez/16530/hci0/dev_00_0D_3C_B1_DD_56/fd0

Or for mp3:

  $./simple-endpoint hci0 mp3source
   dbus.Dictionary({'Codec': dbus.Byte(1), 'UUID': '0000110A-0000-1000-8000-00805F9B34FB', 'Capabilities': dbus.Array([dbus.Byte(63), dbus.Byte(7), dbus.Byte(255), dbus.Byte(254)], signature=None)}, signature=None)
   SelectConfiguration (dbus.Array([dbus.Byte(63), dbus.Byte(7), dbus.Byte(255), dbus.Byte(254)], signature=dbus.Signature('y')))
   SetConfiguration (/org/bluez/15317/hci0/dev_00_0D_3C_B1_DD_56/fd2, dbus.Array([dbus.Byte(33), dbus.Byte(2), dbus.Byte(0), dbus.Byte(128)], signature=dbus.Signature('y')))

  $gst-launch-0.10 filesrc location=<file to stream> ! mp3parse ! a2dpsink transport=/org/bluez/15317/hci0/dev_00_0D_3C_B1_DD_56/fd2

Endpoints can be used with old unix socket so it should not break anything if
Media API got enabled but Socket doesn't got disabled, but note that PA will
probably try to use/lock if one register a sbcsource.

There are things that doesn't work though:

  - Simple-endpoint uses fixed configuration for sbc and mp3, also it should
  probably support streaming and more codecs via gstreamer to make it easier to
  test.
  - A2dp setconf callback need to be change since right now it expect a return
  from the endpoint but in case of MediaEndpoit this has to be async. For now
  it will block while waiting for SetConfiguration reply of the endpoint. Also
  to support BlueZ x BlueZ streams this has to take less than 4 sec. otherwise
  it will timeout on the requestor side, so timeout for SetConfiguration is set
  to 3 sec.
  - Properties such as Delay, NREC and InbandRingtone are not really writeable
  right now.

Luiz Augusto von Dentz (10):
  Add media API documentation
  Add rule to enabling talking to org.bluez.MediaEndpoint
  Add option to enable/disable unix ipc via audio.conf
  Add support for media transport in gstreamer plugin
  Add simple-endpoint test script
  Add initial implementation of org.bluez.Media spec
  Introduce headset_get_inband
  Update a2dp transport delay when it changes
  Remove local cache for nrec and inband
  Add proper checks for MediaTransport.SetProperty

 Makefile.am          |    6 +-
 audio/a2dp-codecs.h  |  116 ++++++++
 audio/a2dp.c         |  749 +++++++++++++++++++++++++++++++++++++++++--------
 audio/a2dp.h         |   15 +
 audio/avdtp.c        |   88 +++----
 audio/avdtp.h        |    5 +-
 audio/gsta2dpsink.c  |   33 ++-
 audio/gsta2dpsink.h  |    1 +
 audio/gstavdtpsink.c |  609 +++++++++++++++++++++++++++++++++++++++-
 audio/gstavdtpsink.h |    6 +
 audio/headset.c      |   10 +
 audio/headset.h      |    1 +
 audio/main.c         |    9 -
 audio/manager.c      |   66 +++++
 audio/manager.h      |    2 +
 audio/media.c        |  689 +++++++++++++++++++++++++++++++++++++++++++++
 audio/media.h        |   54 ++++
 audio/sink.c         |  179 ++-----------
 audio/source.c       |  174 ++----------
 audio/transport.c    |  758 ++++++++++++++++++++++++++++++++++++++++++++++++++
 audio/transport.h    |   36 +++
 audio/unix.c         |    1 +
 doc/media-api.txt    |  169 +++++++++++
 src/bluetooth.conf   |    1 +
 test/simple-endpoint |  126 +++++++++
 25 files changed, 3395 insertions(+), 508 deletions(-)
 create mode 100644 audio/a2dp-codecs.h
 create mode 100644 audio/media.c
 create mode 100644 audio/media.h
 create mode 100644 audio/transport.c
 create mode 100644 audio/transport.h
 create mode 100644 doc/media-api.txt
 create mode 100755 test/simple-endpoint


^ permalink raw reply

* [PATCH v3 2/2] Bluetooth: Implement LE Set Scan Enable cmd
From: Anderson Briglia @ 2010-09-13 13:22 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Anderson Briglia
In-Reply-To: <1284384122-8393-1-git-send-email-anderson.briglia@openbossa.org>

This patch implements LE Set Scan Enable command for dual
mode and Low Energy hci controllers. It also adds new HCI flags
in order to indicate the LE Scanning state for userland applications
and kernel itself.

Signed-off-by: Anderson Briglia <anderson.briglia@openbossa.org>
---
 include/net/bluetooth/hci.h |    5 +++++
 net/bluetooth/hci_event.c   |   27 +++++++++++++++++++++++++++
 2 files changed, 32 insertions(+), 0 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 20ef99a..740e5de 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -78,6 +78,7 @@ enum {
 	HCI_RAW,
 
 	HCI_LE_ADV,
+	HCI_LE_SCAN,
 };
 
 /* HCI ioctl defines */
@@ -600,6 +601,10 @@ struct hci_rp_read_bd_addr {
 	#define LE_ADVERTISE_ENABLED	0x01
 	#define LE_ADVERTISE_DISABLED	0x00
 
+#define HCI_OP_LE_SET_SCAN_ENABLE	0x200c
+	#define LE_SCAN_ENABLED		0x01
+	#define LE_SCAN_DISABLED	0x00
+
 /* ---- HCI Events ---- */
 #define HCI_EV_INQUIRY_COMPLETE		0x01
 
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 262a5b3..d3c68de 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -845,6 +845,29 @@ static void hci_cc_le_set_advertise(struct hci_dev *hdev, struct sk_buff *skb)
 	hci_req_complete(hdev, status);
 }
 
+static void hci_cc_le_set_scan(struct hci_dev *hdev, struct sk_buff *skb)
+{
+	__u8 status = *((__u8 *) skb->data);
+	void *sent;
+
+	BT_DBG("%s status 0x%x", hdev->name, status);
+
+	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
+	if (!sent)
+		return;
+
+	if (!status) {
+		__u8 param = *((__u8 *) sent);
+
+		if (param & LE_SCAN_ENABLED)
+			set_bit(HCI_LE_SCAN, &hdev->flags);
+		else
+			clear_bit(HCI_LE_SCAN, &hdev->flags);
+	}
+
+	hci_req_complete(hdev, status);
+}
+
 static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	__u8 status = *((__u8 *) skb->data);
@@ -1337,6 +1360,10 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
 		hci_cc_le_set_advertise(hdev, skb);
 		break;
 
+	case HCI_OP_LE_SET_SCAN_ENABLE:
+		hci_cc_le_set_scan(hdev, skb);
+		break;
+
 	default:
 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
 		break;
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH v3 1/2] Bluetooth: Implement LE Set Advertise Enable cmd
From: Anderson Briglia @ 2010-09-13 13:22 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Anderson Briglia

This patch implements LE Set Advertise Enable command for dual mode and
Low Energy hci controllers. It also adds new HCI flags in order to
indicate the Advertising state for userland applications and kernel
itself.

Signed-off-by: Anderson Briglia <anderson.briglia@openbossa.org>
---
 include/net/bluetooth/hci.h |    7 +++++++
 net/bluetooth/hci_event.c   |   27 +++++++++++++++++++++++++++
 2 files changed, 34 insertions(+), 0 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index bcbdd6d..20ef99a 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -76,6 +76,8 @@ enum {
 	HCI_INQUIRY,
 
 	HCI_RAW,
+
+	HCI_LE_ADV,
 };
 
 /* HCI ioctl defines */
@@ -593,6 +595,11 @@ struct hci_rp_read_bd_addr {
 	bdaddr_t bdaddr;
 } __packed;
 
+/* --- HCI LE Commands --- */
+#define HCI_OP_LE_SET_ADVERTISE_ENABLE	0x200a
+	#define LE_ADVERTISE_ENABLED	0x01
+	#define LE_ADVERTISE_DISABLED	0x00
+
 /* ---- HCI Events ---- */
 #define HCI_EV_INQUIRY_COMPLETE		0x01
 
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index bfef5ba..262a5b3 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -822,6 +822,29 @@ static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
 	hci_dev_unlock(hdev);
 }
 
+static void hci_cc_le_set_advertise(struct hci_dev *hdev, struct sk_buff *skb)
+{
+	__u8 status = *((__u8 *) skb->data);
+	void *sent;
+
+	BT_DBG("%s status 0x%x", hdev->name, status);
+
+	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADVERTISE_ENABLE);
+	if (!sent)
+		return;
+
+	if (!status) {
+		__u8 param = *((__u8 *) sent);
+
+		if (param & LE_ADVERTISE_ENABLED)
+			set_bit(HCI_LE_ADV, &hdev->flags);
+		else
+			clear_bit(HCI_LE_ADV, &hdev->flags);
+	}
+
+	hci_req_complete(hdev, status);
+}
+
 static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	__u8 status = *((__u8 *) skb->data);
@@ -1310,6 +1333,10 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
 		hci_cc_read_bd_addr(hdev, skb);
 		break;
 
+	case HCI_OP_LE_SET_ADVERTISE_ENABLE:
+		hci_cc_le_set_advertise(hdev, skb);
+		break;
+
 	default:
 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
 		break;
-- 
1.7.0.4


^ permalink raw reply related

* Re: [PATCH] Fix crash on gstreamer plugin if device doesn't support sbc
From: Johan Hedberg @ 2010-09-13 13:21 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
In-Reply-To: <1284381611-17203-1-git-send-email-luiz.dentz@gmail.com>

Hi Luiz,

On Mon, Sep 13, 2010, Luiz Augusto von Dentz wrote:
>  audio/gstavdtpsink.c |    3 +++
>  1 files changed, 3 insertions(+), 0 deletions(-)
> 
> diff --git a/audio/gstavdtpsink.c b/audio/gstavdtpsink.c
> index f0e5b76..b8c8832 100644
> --- a/audio/gstavdtpsink.c
> +++ b/audio/gstavdtpsink.c
> @@ -448,6 +448,9 @@ static GstStructure *gst_avdtp_sink_parse_sbc_caps(
>  	GValue *list;
>  	gboolean mono, stereo;
>  
> +	if (sbc == NULL)
> +		return NULL;
> +
>  	structure = gst_structure_empty_new("audio/x-sbc");
>  	value = g_value_init(g_new0(GValue, 1), G_TYPE_STRING);
>  

The patch has been pushed upstream. Thanks.

Johan

^ permalink raw reply

* Re: [RFC] BlueZ D-Bus Sim Access Profile Server API description
From: Johan Hedberg @ 2010-09-13 13:20 UTC (permalink / raw)
  To: Suraj Sumangala; +Cc: linux-bluetooth, Jothikumar.Mothilal
In-Reply-To: <4C8E0BA3.1010308@Atheros.com>

Hi,

> Should we have the method like,
> 	struct RequestATR(string command, variant param)

ATR doesn't take any parameters so it'd be just RequestATR()

> 	where, struct = { string, array{uint8} )

What do you need the string for? Wouldn't an array{uint8} suffice? A
D-Bus error return could be used when the ResultCode in the response
indicates failure.

Johan

^ permalink raw reply

* RE: [RFC] BlueZ D-Bus Sim Access Profile Server API description
From: Waldemar.Rymarkiewicz @ 2010-09-13 12:47 UTC (permalink / raw)
  To: suraj; +Cc: Suraj.Sumangala, linux-bluetooth, Jothikumar.Mothilal
In-Reply-To: <4C8E1942.40805@Atheros.com>

 Hi Suraj,

>The agent will be in a better position to take this decision 
>as it will be interfacing between actual card reader and SAP server.
>
>For example, if the agent is connected to an external card 
>reader and it has lost connection with the reader. It can ask 
>for an Immediate disconnection.

What will happen when dbus connection will be lost?  SAP server will start immediate disconnection. Right?

>If disconnection was triggered by a user action, it can decide 
>to call this API with Graceful as the parameter.

What exactly do you mean "triggerd by a user" ? Does agent interact with the user somehow?  In which way, any API for that? 

>One candidate would be when the MessageSize is changed.
>Another one will be with the "SimStatus" property. It makes 
>sense to raise his signal after the server sends the STATUS 
>IND response successfully.
>
>But, it is a fact that most of the Properties are set by the 
>Agent itself. So agent will know that they have changed.

Exactly.

Thanks,
/Waldek

^ permalink raw reply

* [PATCH] Fix crash on gstreamer plugin if device doesn't support sbc
From: Luiz Augusto von Dentz @ 2010-09-13 12:40 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.dentz-von@nokia.com>

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

diff --git a/audio/gstavdtpsink.c b/audio/gstavdtpsink.c
index f0e5b76..b8c8832 100644
--- a/audio/gstavdtpsink.c
+++ b/audio/gstavdtpsink.c
@@ -448,6 +448,9 @@ static GstStructure *gst_avdtp_sink_parse_sbc_caps(
 	GValue *list;
 	gboolean mono, stereo;
 
+	if (sbc == NULL)
+		return NULL;
+
 	structure = gst_structure_empty_new("audio/x-sbc");
 	value = g_value_init(g_new0(GValue, 1), G_TYPE_STRING);
 
-- 
1.7.1


^ permalink raw reply related

* Re: [RFC] BlueZ D-Bus Sim Access Profile Server API description
From: Suraj Sumangala @ 2010-09-13 12:29 UTC (permalink / raw)
  To: Waldemar.Rymarkiewicz@tieto.com
  Cc: Suraj Sumangala, linux-bluetooth@vger.kernel.org,
	Jothikumar Mothilal
In-Reply-To: <99B09243E1A5DA4898CDD8B700111448097968E653@EXMB04.eu.tieto.com>

Hi Waldek,

On 9/13/2010 5:41 PM, Waldemar.Rymarkiewicz@tieto.com wrote:
> Hi Suraj,
>
>> +		void Disconnect(string type)
>> +
>> +			This initiates a SAP disconnection from
>> SAP server.
>> +
>> +			The type parameter specifies the type
>> of disconnection.
>> +
>> +			"Graceful"  ->  lets the SAP client initiate a
>> +			garceful disconnection.
>> +
>> +			"Immediate" ->  disconnects the connection
>> +			immediately from the server.
>
> How agent will use this method? I mean when it is supposed to use gracefull and when immediate disconnection?

The agent will be in a better position to take this decision as it will 
be interfacing between actual card reader and SAP server.

For example, if the agent is connected to an external card reader and 
it has lost connection with the reader. It can ask for an Immediate 
disconnection.
If disconnection was triggered by a user action, it can decide to call 
this API with Graceful as the parameter.

>
>> +Signals		PropertyChanged(string name, variant value)
>> +
>> +			This signal indicates a changed value
>> of the given
>> +			property.
>
> Is the signal really needed?  Who is interested in keeping track on properties?

One candidate would be when the MessageSize is changed.
Another one will be with the "SimStatus" property. It makes sense to 
raise his signal after the server sends the STATUS IND response 
successfully.

But, it is a fact that most of the Properties are set by the Agent 
itself. So agent will know that they have changed.

>
> Thanks,
> /Waldek

Regards
Suraj


^ permalink raw reply

* Printing over BT without OBEX-BPP
From: Zaahir Khan @ 2010-09-13 12:24 UTC (permalink / raw)
  To: linux-bluetooth

Dear All,

We are having APM BT over UART.

Our object is to print over BT.

Is it possible to print without using OBEX-BPP?

Any help highly appreciated.

Thanks & regards,

Zaahir Khan

^ permalink raw reply

* RE: [RFC] BlueZ D-Bus Sim Access Profile Server API description
From: Waldemar.Rymarkiewicz @ 2010-09-13 12:11 UTC (permalink / raw)
  To: suraj, linux-bluetooth; +Cc: Jothikumar.Mothilal
In-Reply-To: <1284374584-12282-1-git-send-email-suraj@atheros.com>

Hi Suraj, 

>+		void Disconnect(string type)
>+
>+			This initiates a SAP disconnection from 
>SAP server.
>+
>+			The type parameter specifies the type 
>of disconnection.
>+
>+			"Graceful"  -> lets the SAP client initiate a
>+			garceful disconnection.
>+
>+			"Immediate" -> disconnects the connection
>+			immediately from the server.

How agent will use this method? I mean when it is supposed to use gracefull and when immediate disconnection?

>+Signals		PropertyChanged(string name, variant value)
>+
>+			This signal indicates a changed value 
>of the given
>+			property.

Is the signal really needed?  Who is interested in keeping track on properties?


Thanks,
/Waldek

^ permalink raw reply

* Re: [RFC] BlueZ D-Bus Sim Access Profile Server API description
From: Suraj Sumangala @ 2010-09-13 11:31 UTC (permalink / raw)
  To: linux-bluetooth, Jothikumar.Mothilal
In-Reply-To: <20100913105932.GA3566@jh-x301>

Hi Johan,

On 9/13/2010 4:29 PM, Johan Hedberg wrote:
> Hi Suraj,
>
> On Mon, Sep 13, 2010, Suraj Sumangala wrote:
>> +		void Response(string command, string result, object response)
>
> This method should be removed. Instead, you should use the methor return
> messages for the commands to relay the response information.

Ok,

Should we have the method like,
	struct RequestATR(string command, variant param)
	
	where, struct = { string, array{uint8} )
>
>> +Sim Access Server Agent hierarchy
>> +=================================
>> +
>> +Service         unique name
>> +Interface       org.bluez.SAPServerAgent
>> +Object path     freely definable
>> +
>> +Methods		Request(string command, object param)
>
> Since the set of SAP commands is fixed and rather short it'd be much
> simpler if you have a separate D-Bus method for each command
> (particularly from the method and method return signature perspective).
> You also seem to have some confusion about what an "object" type
> parameter is. It seems you're using it for some sort of variant type
> when it will only ever represent a simple object path.

Thanks, My mistake. I was referring to a variant type there.
>
> Johan

Regards
Suraj


^ permalink raw reply

* Re: [RFC] BlueZ D-Bus Sim Access Profile Server API description
From: Johan Hedberg @ 2010-09-13 10:59 UTC (permalink / raw)
  To: Suraj Sumangala; +Cc: linux-bluetooth, Jothikumar.Mothilal
In-Reply-To: <1284374584-12282-1-git-send-email-suraj@atheros.com>

Hi Suraj,

On Mon, Sep 13, 2010, Suraj Sumangala wrote:
> +		void Response(string command, string result, object response)

This method should be removed. Instead, you should use the methor return
messages for the commands to relay the response information.

> +Sim Access Server Agent hierarchy
> +=================================
> +
> +Service         unique name
> +Interface       org.bluez.SAPServerAgent
> +Object path     freely definable
> +
> +Methods		Request(string command, object param)

Since the set of SAP commands is fixed and rather short it'd be much
simpler if you have a separate D-Bus method for each command
(particularly from the method and method return signature perspective).
You also seem to have some confusion about what an "object" type
parameter is. It seems you're using it for some sort of variant type
when it will only ever represent a simple object path.

Johan

^ permalink raw reply

* [RFC] BlueZ D-Bus Sim Access Profile Server API description
From: Suraj Sumangala @ 2010-09-13 10:43 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Jothikumar.Mothilal, Suraj Sumangala

Hi,

Below is the Sim Access Profile server role API discription.
Please let me know your comments.

Regards
Suraj
---
 Makefile.am     |    2 +-
 doc/sap-api.txt |  216 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 217 insertions(+), 1 deletions(-)
 create mode 100644 doc/sap-api.txt

diff --git a/Makefile.am b/Makefile.am
index a8829d9..52537bc 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -350,7 +350,7 @@ EXTRA_DIST += doc/manager-api.txt \
 		doc/service-api.txt doc/agent-api.txt doc/attribute-api.txt \
 		doc/serial-api.txt doc/network-api.txt \
 		doc/input-api.txt doc/audio-api.txt doc/control-api.txt \
-		doc/hfp-api.txt doc/assigned-numbers.txt
+		doc/hfp-api.txt doc/assigned-numbers.txt doc/sap-api.txt
 
 AM_YFLAGS = -d
 
diff --git a/doc/sap-api.txt b/doc/sap-api.txt
new file mode 100644
index 0000000..9a684fa
--- /dev/null
+++ b/doc/sap-api.txt
@@ -0,0 +1,216 @@
+BlueZ D-Bus Sim Access Profile API description
+**********************************************
+
+Copyright (C) 2009-2010  Atheros Communication Ltd
+
+
+Sim Access Server hierarchy
+===========================
+
+Service	org.bluez
+Interface	org.bluez.SAPServer
+Object path	[variable prefix]/{hci0,hci1,...}
+
+This interface is available for devices which can function as the
+Server role of the Sim Access profiles.
+It is intended to be used with external stacks / handlers of the Sim Access
+protocol.
+
+
+Methods	void RegisterAgent(object agent)
+
+			This registers the Sim Access server agent.
+			This also registers the profile with the service
+			databse and start waiting for an RFCOMM connection
+			on the SAP server channel.
+
+			The object path defines the path the of the agent.
+
+			If an application disconnects from the bus all
+			of its registered agents will be removed.
+
+			Possible errors: org.bluez.Error.InvalidArguments
+					 org.bluez.Error.AlreadyExists
+					 org.bluez.Error.Failed
+
+		void UnregisterAgent(object agent)
+
+			This unregisters the agent that has been previously
+			registered. The object path parameter must match the
+			same value that has been used on registration.
+
+			Possible errors: org.bluez.Error.DoesNotExist
+					 org.bluez.Error.InvalidArguments
+					 org.bluez.Error.Failed
+
+		void Response(string command, string result, object response)
+
+			This sends a SAP response packet to a SAP sequest.
+
+			The command parameter specifies the SAP command for
+			which response is being sent.
+
+			The result parameter specifies the ResultCode for the
+			operation.
+
+			The object response specifies the response packet to
+			be sent if any.
+
+			Below mentioned are the parameters and possible value.
+
+			command     	  result	    	response
+			----------------------------------------------------
+
+			Connect		  OkSuccess		NA
+					  ConnectFailed
+				  	  OkOngoingCall
+
+			APDU		  OkSuccess		array{uint8}
+					  NoReason
+					  CardNotAccessible
+					  CardPoweredOff
+					  CardRemoved
+
+			APDU7816	  OkSuccess		array{uint8}
+					  NoReason
+					  CardNotAccessible
+					  CardPoweredOff
+					  CardRemoved
+
+			ATR		  OkSuccess		array{uint8}
+					  NoReason
+					  CardPoweredOff
+					  CardRemoved
+					  DataNotAvailable
+
+			SimPowerOn	  OkSuccess		NA
+					  NoReason
+					  CardNotAccessible
+					  CardRemoved
+					  CardPoweredOn
+
+			SimPowerOff	  OkSuccess		NA
+					  NoReason
+					  CardPoweredOff
+					  CardRemoved
+
+			Reset		  OkSuccess		NA
+					  NoReason
+					  CardNotAccessible
+					  CardPoweredOff
+					  CardRemoved
+
+			CardReaderStatus  OkSuccess		uint8
+					  NoReason
+					  DataNotAvailable
+
+			TransportProtocol OkSuccess		NA
+					  NotSupported
+
+			Disconnect	  NA	 		NA
+
+			Possible errors: org.bluez.Error.InvalidArguments
+					 org.bluez.Error.Failed
+
+		void Disconnect(string type)
+
+			This initiates a SAP disconnection from SAP server.
+
+			The type parameter specifies the type of disconnection.
+
+			"Graceful"  -> lets the SAP client initiate a
+			garceful disconnection.
+
+			"Immediate" -> disconnects the connection
+			immediately from the server.
+
+		void SetProperty(string name, variant value)
+
+			Changes the value of the specified property. Only
+			properties that are listed a read-write are changeable.
+			On success this will emit a PropertyChanged signal.
+
+			Possible Errors: org.bluez.Error.DoesNotExist
+					 org.bluez.Error.InvalidArguments
+
+		dict GetProperties()
+
+			Returns all properties for the interface. See the
+			properties section for available properties.
+
+			Possible Errors: org.bluez.Error.InvalidArguments
+
+Signals		PropertyChanged(string name, variant value)
+
+			This signal indicates a changed value of the given
+			property.
+
+Properties	string SimStatus [readwrite]
+
+			Specifies the availability of the SIM.
+
+			The possible value are
+
+			"UnknownError"
+			"CardReset"
+			"CardNotAccesible"
+			"CardRemoved"
+			"CardInsterted"
+			"CardRecovered"
+
+		uint16 MaxMessageSize [readwrite]
+
+			The maximum possible message size supported by
+			SAP server.
+
+		uint16 MinMessageSize [readwrite]
+
+			The minimum possible message size supported by
+			SAP server.
+
+		uint16 MessageSize [readonly]
+
+			The negotiated message size for the current connection.
+			This is valid only when there is an active
+			SAP connection.
+
+Sim Access Server Agent hierarchy
+=================================
+
+Service         unique name
+Interface       org.bluez.SAPServerAgent
+Object path     freely definable
+
+Methods		Request(string command, object param)
+
+			This method gets called whenever a SAP request is received
+			from SAP client. This will help deliver the
+			SAP request to the Agent.
+
+			The command parameter specifies the SAP request type
+			received.
+
+			The param parameter specifies the command parameter
+			packet received from SAP client.
+
+			Below mentioned is the parameters and possible value.
+
+			command     	  	parameter
+			----------------------------------------------------
+
+			Connect		  	NA
+			APDU		  	array{uint8}
+			APDU7816	  	array{uint8}
+			ATR		  	NA
+			SimPowerOn	  	NA
+			SimPowerOff	  	NA
+			Reset		  	NA
+			CardReaderStatus  	NA
+			TransportProtocol 	uint8
+			Disconnect		NA
+
+		void Release()
+
+			This method gets called whenever the service daemon
+			unregisters the agent or whenever the Adapter where
+			the SimAccessServerAgent registers itself is removed.
-- 
1.7.0.4


^ permalink raw reply related

* RE: MAP implementation status
From: Counihan, Tom @ 2010-09-13 10:11 UTC (permalink / raw)
  To: Radoslaw Jablonski, linux-bluetooth@vger.kernel.org
In-Reply-To: <4C88D729.7050803@nokia.com>

[-- Attachment #1: Type: text/plain, Size: 2074 bytes --]

Hi Radoslaw,

>-----Original Message-----
>From: linux-bluetooth-owner@vger.kernel.org [mailto:linux-bluetooth-
>owner@vger.kernel.org] On Behalf Of Radoslaw Jablonski
>Sent: 09 September 2010 13:47
>To: linux-bluetooth@vger.kernel.org
>Subject: MAP implementation status
>
>
>  Hi all,
>We plan to start implementation of Message Access Profile Server as
>obexd plugin. Before we start with coding part I need to check if
>someone else started implementing MAP Server, MNS Server of Map client.
>If some code is already available, then we could combine our forces to
>add MAP support for OBEXD.


This is something I've been focusing on recently.
Attached is my modest start to this.
My initial strategy - even though its IVI client side I'm most interested in - was to tackle server side, essentially bring up both sides of the interface incrementally.
I was going to employ a strategy of, instead of doing it in big bulk, dropping small unobtrusive patches into the trunk, so interested people could see and contribute to the activity.
I'm struggling in defining the right level of patch to upstream - maybe folks here can comment on the attached - is it of acceptable substance or would more meat be require to make it a meaningful contribution?

I've taken on board the suggestion from Marcel and Johan to focus on SMS data first. That makes sense to me. 
Hope the above and attached is of use.

Looking forward to hearing from you - any thoughts/insights/criticism are most welcome.

Regards
Tom
--------------------------------------------------------------
Intel Shannon Limited
Registered in Ireland
Registered Office: Collinstown Industrial Park, Leixlip, County Kildare
Registered Number: 308263
Business address: Dromore House, East Park, Shannon, Co. Clare

This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). Any review or distribution by others is strictly prohibited. If you are not the intended recipient, please contact the sender and delete all copies.


[-- Attachment #2: 0001-Initial-intro-for-MAP.patch --]
[-- Type: application/octet-stream, Size: 8107 bytes --]

From 66b42f3a3e1520d8cdb2b7549215224d0abde606 Mon Sep 17 00:00:00 2001
From: Tom Counihan <tom.counihan@intel.com>
Date: Sun, 5 Sep 2010 15:01:34 +0100
Subject: [PATCH] Initial intro for MAP

Bootstraping MAP implementation
---
 plugins/map.c |  232 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 plugins/sms.h |   49 ++++++++++++
 2 files changed, 281 insertions(+), 0 deletions(-)
 create mode 100644 plugins/map.c
 create mode 100644 plugins/sms.h

diff --git a/plugins/map.c b/plugins/map.c
new file mode 100644
index 0000000..2a483e7
--- /dev/null
+++ b/plugins/map.c
@@ -0,0 +1,232 @@
+/*
+ * OBEX Server
+ *
+ * Copyright (C) 2009-2010 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ *
+ * Author Name <tom.counihan@intel.com>
+ *  - FIXME: Short log of changes
+ *
+ *
+ * FIXME: DOCUMENTATION: entry points and code roadmap. What does
+ * it do, how does it work, etc.
+ * 	- Postpone Notification feature until rudimentary functionality up
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <glib.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <openobex/obex.h>
+#include <openobex/obex_const.h>
+
+#include "plugin.h"
+#include "log.h"
+#include "obex.h"
+#include "service.h"
+
+#define MAP_CHANNEL	16
+
+#define MAXLISTCOUNT_TAG	0x01
+#define STARTOFFSET_TAG	0x02
+#define FILTERMESSAGETYPE_TAG	0x03
+#define FILTERBEGINPERIOD_TAG	0x04
+#define ENDFILTERPERIODEND_TAG	0x05
+#define FILTERREADSTATUS_TAG	0x06
+#define FILTERRECIPIENT_TAG	0x07
+#define FILTERORIGINATOR_TAG	0x08
+#define FILTERPRIORITY_TAG	0x09
+#define ATTACHEMENT_TAG	0x0A
+#define TRANSPARENT_TAG 0x0B
+#define RETRY_TAG	0x0C
+#define NEWMESSAGE_TAG	0x0D
+#define NOTIFICATIONSTATUS_TAG	0x0E
+#define MASINSTANCEID_TAG	0x0F
+#define PARAMETERMASK_TAG	0x10
+#define FOLDERLISTINGSIZE_TAG	0x11
+#define MESSAGELISTINGSIZE_TAG	0x12
+#define SUBJECTLENGTH_TAG 0x13
+#define CHARSET_TAG 0x14
+#define FRACTIONREQUEST_TAG	0x15
+#define FRACTIONDELIVERED_TAG	0x16
+#define STATUSINDICATOR_TAG	0x17
+#define STATUSVALUE_TAG	0x18
+#define MSETIME_TAG	0x19
+
+/* The following length is in the unit of byte */
+#define MAXLISTCOUNT_LEN	2
+#define STARTOFFSET_LEN	2
+#define FILTERMESSAGETYPE_LEN	1
+#define FILTERREADSTATUS_LEN	1
+#define FILTERPRIORITY_LEN	1
+#define ATTACHEMENT_LEN	1
+#define TRANSPARENT_LEN 1
+#define RETRY_LEN	1
+#define NEWMESSAGE_LEN	1
+#define NOTIFICATIONSTATUS_LEN	1
+#define MASINSTANCEID_LEN	1
+#define PARAMETERMASK_LEN	4
+#define FOLDERLISTINGSIZE_LEN	2
+#define MESSAGELISTINGSIZE_LEN	2
+#define SUBJECTLENGTH_LEN 1
+#define CHARSET_LEN 1
+#define FRACTIONREQUEST_LEN	1
+#define FRACTIONDELIVERED_LEN	1
+#define STATUSINDICATOR_LEN	1
+#define STATUSVALUE_LEN	1
+
+#define MAP_RECORD "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>	\
+<record>								\
+  <attribute id=\"0x0001\">						\
+    <sequence>								\
+      <uuid value=\"0x1132\"/>						\
+    </sequence>								\
+  </attribute>								\
+									\
+  <attribute id=\"0x0004\">						\
+    <sequence>								\
+      <sequence>							\
+        <uuid value=\"0x0100\"/>					\
+      </sequence>							\
+      <sequence>							\
+        <uuid value=\"0x0003\"/>					\
+        <uint8 value=\"%u\" name=\"channel\"/>				\
+      </sequence>							\
+      <sequence>							\
+        <uuid value=\"0x0008\"/>					\
+      </sequence>							\
+    </sequence>								\
+  </attribute>								\
+									\
+  <attribute id=\"0x0009\">						\
+    <sequence>								\
+      <sequence>							\
+        <uuid value=\"0x1134\"/>					\
+        <uint16 value=\"0x0100\" name=\"version\"/>			\
+      </sequence>							\
+    </sequence>								\
+  </attribute>								\
+									\
+  <attribute id=\"0x0100\">						\
+    <text value=\"%s\" name=\"name\"/>					\
+  </attribute>								\
+									\
+  <attribute id=\"0x0316\">						\
+    <uint8 value=\"0x02\"/>						\
+  </attribute>								\
+</record>"
+
+
+static const uint8_t MAP_TARGET[TARGET_SIZE] = {
+			0xBB, 0x58, 0x2B, 0x40,  0x42, 0x0C, 0x11, 0xDB,
+			0xB0, 0xDE, 0x08, 0x00,  0x20, 0x0C, 0x9A, 0x66 };
+
+struct map_session {
+	struct apparam_field *params;
+	char *folder;
+	uint32_t find_handle;
+	GString *buffer;
+};
+
+/* TODO Fix this entry */
+struct cache_entry {
+	uint64_t handle;
+	char *id;
+	char *name;
+	char *sound;
+	char *tel;
+};
+
+
+static void *map_connect(struct obex_session *os, int *err)
+{
+	/* Rejects all connects for the moment */
+	struct map_session *map;
+
+	map = g_new0(struct map_session, 1);
+
+	return map;
+}
+
+static int map_get(struct obex_session *os, obex_object_t *obj,
+					gboolean *stream, void *user_data)
+{
+	/* Rejects all gets for the moment */
+	return -EBADR;
+}
+
+static int map_setpath(struct obex_session *os, obex_object_t *obj,
+		void *user_data)
+{
+	/* Rejects all set paths for the moment */
+	return -EBADR;
+}
+
+static void map_disconnect(struct obex_session *os, void *user_data)
+{
+	/* Rejects all disconnect for the moment */
+
+}
+
+static int map_chkput(struct obex_session *os, void *user_data)
+{
+	/* Rejects all PUTs */
+	return -EBADR;
+}
+
+
+static struct obex_service_driver map = {
+	.name = "Message Access server",
+	.service = OBEX_MAP,
+	.channel = MAP_CHANNEL,
+	.record = MAP_RECORD,
+	.target = MAP_TARGET,
+	.target_size = TARGET_SIZE,
+	.connect = map_connect,
+	.get = map_get,
+	.setpath = map_setpath,
+	.disconnect = map_disconnect,
+	.chkput = map_chkput
+};
+
+static int map_init(void)
+{
+	int err;
+
+
+	return 0;
+
+	return err;
+}
+static void map_exit(void)
+{
+	obex_service_driver_unregister(&map);
+
+}
+
+OBEX_PLUGIN_DEFINE(map, map_init, map_exit)
diff --git a/plugins/sms.h b/plugins/sms.h
new file mode 100644
index 0000000..8cc9a30
--- /dev/null
+++ b/plugins/sms.h
@@ -0,0 +1,49 @@
+/*
+ * OBEX Server
+ *
+ * Copyright (C) 2009-2010 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ *
+ * Author Name <tom.counihan@intel.com>
+ *  - FIXME: Short log of changes
+ *
+ *
+ * FIXME: DOCUMENTATION: entry points and code roadmap. What does
+ * it do, how does it work, etc.
+ */
+
+struct apparam_field {
+	/* FolderListing and MessageListing attributes */
+	uint16_t maxlistcount;
+	uint16_t liststartoffset;
+
+	/* MessageListing attributes only */
+	uint8_t subjectlength;
+	uint32_t parametermask;
+	uint8_t filtermessagetype;
+	uint8_t *filterperiodbegin;
+	uint8_t *filterperiodend;
+	uint8_t filterreadstatus;
+	uint8_t *filterrecipient;
+	uint8_t *filteroriginator;
+	uint8_t filterpriority;
+
+	/* Message function attributes only */
+	uint8_t attachement;
+	uint8_t charset;
+	uint8_t fractionrequest;
+};
-- 
1.7.1.1


^ permalink raw reply related

* Re: [PATCH V2 0/2] bluez: cleanup btio library
From: Johan Hedberg @ 2010-09-13  8:26 UTC (permalink / raw)
  To: Zhenhua Zhang; +Cc: linux-bluetooth
In-Reply-To: <1284365851-8066-1-git-send-email-zhenhua.zhang@intel.com>

Hi Zhenhua,

On Mon, Sep 13, 2010, Zhenhua Zhang wrote:
> These two patches are to cleanup BlueZ btio.[ch] in bluez source directory.

Thanks. These patches have also been pushed upstream.

Johan

^ permalink raw reply

* [PATCH V2 2/2] btio: Seperate btio.[ch] into btio directory
From: Zhenhua Zhang @ 2010-09-13  8:17 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1284365851-8066-1-git-send-email-zhenhua.zhang@intel.com>

Seperate btio.[ch] from src directory to btio sub-folder.
---
 Makefile.am          |    8 +++++---
 Makefile.tools       |    2 +-
 {src => btio}/btio.c |    0
 {src => btio}/btio.h |    0
 4 files changed, 6 insertions(+), 4 deletions(-)
 rename {src => btio}/btio.c (100%)
 rename {src => btio}/btio.h (100%)

diff --git a/Makefile.am b/Makefile.am
index 7895be2..a8829d9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -102,6 +102,8 @@ endif
 gdbus_sources = gdbus/gdbus.h gdbus/mainloop.c gdbus/watch.c \
 					gdbus/object.c gdbus/polkit.c
 
+btio_sources = btio/btio.h btio/btio.c
+
 builtin_modules =
 builtin_sources =
 builtin_nodist =
@@ -216,14 +218,14 @@ endif
 sbin_PROGRAMS += src/bluetoothd
 
 src_bluetoothd_SOURCES = $(gdbus_sources) $(builtin_sources) \
-			$(attrib_sources) \
+			$(attrib_sources) $(btio_sources) \
 			$(mcap_sources) \
 			src/main.c src/log.h src/log.c \
 			src/security.c src/rfkill.c src/hcid.h src/sdpd.h \
 			src/sdpd-server.c src/sdpd-request.c \
 			src/sdpd-service.c src/sdpd-database.c \
 			src/attrib-server.h src/attrib-server.c \
-			src/sdp-xml.h src/sdp-xml.c src/btio.h src/btio.c \
+			src/sdp-xml.h src/sdp-xml.c \
 			src/textfile.h src/textfile.c \
 			src/glib-helper.h src/glib-helper.c \
 			src/oui.h src/oui.c src/uinput.h src/ppoll.h \
@@ -357,7 +359,7 @@ AM_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ @CAPNG_CFLAGS@ \
 
 INCLUDES = -I$(builddir)/lib -I$(builddir)/src -I$(srcdir)/src \
 			-I$(srcdir)/audio -I$(srcdir)/sbc -I$(srcdir)/gdbus \
-			-I$(srcdir)/attrib
+			-I$(srcdir)/attrib -I$(srcdir)/btio
 
 if MCAP
 	INCLUDES += -I$(builddir)/health
diff --git a/Makefile.tools b/Makefile.tools
index 1c46542..14ecf31 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -170,7 +170,7 @@ test_bdaddr_LDADD = lib/libbluetooth.la
 
 test_agent_LDADD = @DBUS_LIBS@
 
-test_btiotest_SOURCES = test/btiotest.c src/btio.h src/btio.c
+test_btiotest_SOURCES = test/btiotest.c btio/btio.h btio/btio.c
 test_btiotest_LDADD = @GLIB_LIBS@ lib/libbluetooth.la
 
 test_test_textfile_SOURCES = test/test-textfile.c src/textfile.h src/textfile.c
diff --git a/src/btio.c b/btio/btio.c
similarity index 100%
rename from src/btio.c
rename to btio/btio.c
diff --git a/src/btio.h b/btio/btio.h
similarity index 100%
rename from src/btio.h
rename to btio/btio.h
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH V2 1/2] btio: Add ifndef/endif guard for btio.h
From: Zhenhua Zhang @ 2010-09-13  8:17 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1284365851-8066-1-git-send-email-zhenhua.zhang@intel.com>

To avoid circular inclusion of include file.
---
 src/btio.h |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/src/btio.h b/src/btio.h
index 81fda8e..d373ed1 100644
--- a/src/btio.h
+++ b/src/btio.h
@@ -21,6 +21,8 @@
  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  *
  */
+#ifndef BT_IO_H
+#define BT_IO_H
 
 #include <glib.h>
 
@@ -92,3 +94,4 @@ GIOChannel *bt_io_listen(BtIOType type, BtIOConnect connect,
 				GDestroyNotify destroy, GError **err,
 				BtIOOption opt1, ...);
 
+#endif
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH V2 0/2] bluez: cleanup btio library
From: Zhenhua Zhang @ 2010-09-13  8:17 UTC (permalink / raw)
  To: linux-bluetooth

Hi,

These two patches are to cleanup BlueZ btio.[ch] in bluez source directory.

Regards,
Zhenhua

^ permalink raw reply

* Re: [PATCH V2 0/2] cleanup btio library
From: Johan Hedberg @ 2010-09-13  8:16 UTC (permalink / raw)
  To: Zhenhua Zhang; +Cc: linux-bluetooth
In-Reply-To: <1284365042-7526-1-git-send-email-zhenhua.zhang@intel.com>

Hi Zhenhua,

On Mon, Sep 13, 2010, Zhenhua Zhang wrote:
> These two patches are to cleanup btio.[ch] in obex source directory.

Thanks. Both patches have been pushed to obexd upstream.

Johan

^ permalink raw reply

* [PATCH V2 2/2] btio: Seperate btio.[ch] into btio directory
From: Zhenhua Zhang @ 2010-09-13  8:04 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1284365042-7526-1-git-send-email-zhenhua.zhang@intel.com>

Seperate btio.[ch] from src directory to btio sub-folder.
---
 Makefile.am          |   19 ++++++++++---------
 {src => btio}/btio.c |    0
 {src => btio}/btio.h |    0
 3 files changed, 10 insertions(+), 9 deletions(-)
 rename {src => btio}/btio.c (100%)
 rename {src => btio}/btio.h (100%)

diff --git a/Makefile.am b/Makefile.am
index e6940bc..175747c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -19,6 +19,8 @@ gwobex_sources = gwobex/gw-obex.h gwobex/gw-obex.c \
 			gwobex/obex-xfer.h gwobex/obex-xfer.c \
 			gwobex/utils.h gwobex/utils.c gwobex/log.h
 
+btio_sources = btio/btio.h btio/btio.c
+
 libexec_PROGRAMS =
 
 if SERVER
@@ -66,11 +68,10 @@ builtin_nodist += plugins/phonebook.c
 
 libexec_PROGRAMS += src/obexd
 
-src_obexd_SOURCES = $(gdbus_sources) $(builtin_sources) \
+src_obexd_SOURCES = $(gdbus_sources) $(builtin_sources) $(btio_sources) \
 			src/main.c src/obexd.h src/plugin.h src/plugin.c \
-			src/log.h src/log.c src/btio.h src/btio.c \
-			src/dbus.h src/manager.c src/obex.h src/obex.c \
-			src/obex-priv.h \
+			src/log.h src/log.c src/dbus.h src/manager.c \
+			src/obex.h src/obex.c src/obex-priv.h \
 			src/mimetype.h src/mimetype.c \
 			src/service.h src/service.c \
 			src/transport.h src/transport.c \
@@ -108,13 +109,12 @@ service_in_files += client/obex-client.service.in
 
 libexec_PROGRAMS += client/obex-client
 
-client_obex_client_SOURCES = $(gdbus_sources) $(gwobex_sources) client/main.c \
-				client/session.h client/session.c \
+client_obex_client_SOURCES = $(gdbus_sources) $(gwobex_sources) $(btio_sources) \
+				client/main.c client/session.h client/session.c \
 				src/log.h src/log.c \
 				client/pbap.h client/pbap.c \
 				client/sync.h client/sync.c \
-				client/transfer.h client/transfer.c \
-				src/btio.c src/btio.h
+				client/transfer.h client/transfer.c
 
 client_obex_client_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ @OPENOBEX_LIBS@ @BLUEZ_LIBS@
 endif
@@ -127,7 +127,8 @@ AM_CFLAGS = @OPENOBEX_CFLAGS@ @BLUEZ_CFLAGS@ @EBOOK_CFLAGS@ \
 			-DOBEX_PLUGIN_BUILTIN -DPLUGINDIR=\""$(plugindir)"\"
 
 INCLUDES = -I$(builddir)/src -I$(srcdir)/src -I$(srcdir)/plugins \
-				-I$(srcdir)/gdbus -I$(srcdir)/gwobex
+				-I$(srcdir)/gdbus -I$(srcdir)/gwobex \
+				-I$(srcdir)/btio
 
 CLEANFILES = $(service_DATA) $(builtin_files)
 
diff --git a/src/btio.c b/btio/btio.c
similarity index 100%
rename from src/btio.c
rename to btio/btio.c
diff --git a/src/btio.h b/btio/btio.h
similarity index 100%
rename from src/btio.h
rename to btio/btio.h
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH V2 1/2] btio: Replace void * with gpointer
From: Zhenhua Zhang @ 2010-09-13  8:04 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1284365042-7526-1-git-send-email-zhenhua.zhang@intel.com>

To make it consistent with bluez btio.c.
---
 src/btio.c |   24 ++++++++++++------------
 src/btio.h |   10 +++++-----
 2 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/src/btio.c b/src/btio.c
index 42a3bcd..8b273ca 100644
--- a/src/btio.c
+++ b/src/btio.c
@@ -62,20 +62,20 @@ struct set_opts {
 
 struct connect {
 	BtIOConnect connect;
-	void *user_data;
+	gpointer user_data;
 	GDestroyNotify destroy;
 };
 
 struct accept {
 	BtIOConnect connect;
-	void *user_data;
+	gpointer user_data;
 	GDestroyNotify destroy;
 };
 
 struct server {
 	BtIOConnect connect;
 	BtIOConfirm confirm;
-	void *user_data;
+	gpointer user_data;
 	GDestroyNotify destroy;
 };
 
@@ -115,7 +115,7 @@ static gboolean check_nval(GIOChannel *io)
 }
 
 static gboolean accept_cb(GIOChannel *io, GIOCondition cond,
-							void *user_data)
+							gpointer user_data)
 {
 	struct accept *accept = user_data;
 	GError *err = NULL;
@@ -136,7 +136,7 @@ static gboolean accept_cb(GIOChannel *io, GIOCondition cond,
 }
 
 static gboolean connect_cb(GIOChannel *io, GIOCondition cond,
-							void *user_data)
+							gpointer user_data)
 {
 	struct connect *conn = user_data;
 	GError *gerr = NULL;
@@ -169,7 +169,7 @@ static gboolean connect_cb(GIOChannel *io, GIOCondition cond,
 }
 
 static gboolean server_cb(GIOChannel *io, GIOCondition cond,
-							void *user_data)
+							gpointer user_data)
 {
 	struct server *server = user_data;
 	int srv_sock, cli_sock;
@@ -201,7 +201,7 @@ static gboolean server_cb(GIOChannel *io, GIOCondition cond,
 }
 
 static void server_add(GIOChannel *io, BtIOConnect connect,
-				BtIOConfirm confirm, void *user_data,
+				BtIOConfirm confirm, gpointer user_data,
 				GDestroyNotify destroy)
 {
 	struct server *server;
@@ -219,7 +219,7 @@ static void server_add(GIOChannel *io, BtIOConnect connect,
 }
 
 static void connect_add(GIOChannel *io, BtIOConnect connect,
-				void *user_data, GDestroyNotify destroy)
+				gpointer user_data, GDestroyNotify destroy)
 {
 	struct connect *conn;
 	GIOCondition cond;
@@ -234,7 +234,7 @@ static void connect_add(GIOChannel *io, BtIOConnect connect,
 					(GDestroyNotify) connect_remove);
 }
 
-static void accept_add(GIOChannel *io, BtIOConnect connect, void *user_data,
+static void accept_add(GIOChannel *io, BtIOConnect connect, gpointer user_data,
 							GDestroyNotify destroy)
 {
 	struct accept *accept;
@@ -1046,7 +1046,7 @@ static gboolean get_valist(GIOChannel *io, BtIOType type, GError **err,
 	return FALSE;
 }
 
-gboolean bt_io_accept(GIOChannel *io, BtIOConnect connect, void *user_data,
+gboolean bt_io_accept(GIOChannel *io, BtIOConnect connect, gpointer user_data,
 					GDestroyNotify destroy, GError **err)
 {
 	int sock;
@@ -1195,7 +1195,7 @@ failed:
 }
 
 GIOChannel *bt_io_connect(BtIOType type, BtIOConnect connect,
-				void *user_data, GDestroyNotify destroy,
+				gpointer user_data, GDestroyNotify destroy,
 				GError **gerr, BtIOOption opt1, ...)
 {
 	GIOChannel *io;
@@ -1249,7 +1249,7 @@ GIOChannel *bt_io_connect(BtIOType type, BtIOConnect connect,
 }
 
 GIOChannel *bt_io_listen(BtIOType type, BtIOConnect connect,
-				BtIOConfirm confirm, void *user_data,
+				BtIOConfirm confirm, gpointer user_data,
 				GDestroyNotify destroy, GError **err,
 				BtIOOption opt1, ...)
 {
diff --git a/src/btio.h b/src/btio.h
index e9dcc9f..d373ed1 100644
--- a/src/btio.h
+++ b/src/btio.h
@@ -72,11 +72,11 @@ typedef enum {
 	BT_IO_SEC_HIGH,
 } BtIOSecLevel;
 
-typedef void (*BtIOConfirm)(GIOChannel *io, void *user_data);
+typedef void (*BtIOConfirm)(GIOChannel *io, gpointer user_data);
 
-typedef void (*BtIOConnect)(GIOChannel *io, GError *err, void *user_data);
+typedef void (*BtIOConnect)(GIOChannel *io, GError *err, gpointer user_data);
 
-gboolean bt_io_accept(GIOChannel *io, BtIOConnect connect, void *user_data,
+gboolean bt_io_accept(GIOChannel *io, BtIOConnect connect, gpointer user_data,
 					GDestroyNotify destroy, GError **err);
 
 gboolean bt_io_set(GIOChannel *io, BtIOType type, GError **err,
@@ -86,11 +86,11 @@ gboolean bt_io_get(GIOChannel *io, BtIOType type, GError **err,
 						BtIOOption opt1, ...);
 
 GIOChannel *bt_io_connect(BtIOType type, BtIOConnect connect,
-				void *user_data, GDestroyNotify destroy,
+				gpointer user_data, GDestroyNotify destroy,
 				GError **err, BtIOOption opt1, ...);
 
 GIOChannel *bt_io_listen(BtIOType type, BtIOConnect connect,
-				BtIOConfirm confirm, void *user_data,
+				BtIOConfirm confirm, gpointer user_data,
 				GDestroyNotify destroy, GError **err,
 				BtIOOption opt1, ...);
 
-- 
1.7.0.4


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox