Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH v2 18/20] unit/AVDTP: Add /TP/SIG/SMG/BV-22-C test
From: Luiz Augusto von Dentz @ 2013-11-25 14:54 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1385391283-10962-1-git-send-email-luiz.dentz@gmail.com>

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

Verify that the IUT (ACP) is able to accept an AVDTP_SUSPEND_CMD, after
the streaming procedure has been started, by reporting the suspension
and replying the returned confirmation.
---
 unit/test-avdtp.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/unit/test-avdtp.c b/unit/test-avdtp.c
index 804fdf5..88c2b01 100644
--- a/unit/test-avdtp.c
+++ b/unit/test-avdtp.c
@@ -569,6 +569,21 @@ int main(int argc, char *argv[])
 			raw_pdu(0xd0, 0x07, 0x04),
 			raw_pdu(0xd2, 0x07),
 			raw_pdu(0xe0, 0x09, 0x04));
+	define_test("/TP/SIG/SMG/BV-22-C", test_server,
+			raw_pdu(0x00, 0x01),
+			raw_pdu(0x02, 0x01, 0x04, 0x00),
+			raw_pdu(0x10, 0x02, 0x04),
+			raw_pdu(0x12, 0x02, 0x01, 0x00, 0x07, 0x06, 0x00, 0x00,
+				0xff, 0xff, 0x02, 0x40),
+			raw_pdu(0x20, 0x03, 0x04, 0x04, 0x01, 0x00, 0x07, 0x06,
+				0x00, 0x00, 0x21, 0x02, 0x02, 0x20),
+			raw_pdu(0x22, 0x03),
+			raw_pdu(0x30, 0x06, 0x04),
+			raw_pdu(0x32, 0x06),
+			raw_pdu(0x40, 0x07, 0x04),
+			raw_pdu(0x42, 0x07),
+			raw_pdu(0x50, 0x09, 0x04),
+			raw_pdu(0x52, 0x09));
 
 	return g_test_run();
 }
-- 
1.8.3.1


^ permalink raw reply related

* [PATCH v2 17/20] unit/AVDTP: Add /TP/SIG/SMG/BV-21-C test
From: Luiz Augusto von Dentz @ 2013-11-25 14:54 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1385391283-10962-1-git-send-email-luiz.dentz@gmail.com>

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

Verify that the IUT (INT) is able to initiate the suspension of a
streaming procedure, after the streaming procedure has been started, by
issuing the AVDTP_SUSPEND_CMD.
---
 unit/test-avdtp.c | 124 +++++++++++++-----------------------------------------
 1 file changed, 29 insertions(+), 95 deletions(-)

diff --git a/unit/test-avdtp.c b/unit/test-avdtp.c
index 4677e22..804fdf5 100644
--- a/unit/test-avdtp.c
+++ b/unit/test-avdtp.c
@@ -317,11 +317,15 @@ static void sep_start_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
 			struct avdtp_stream *stream, struct avdtp_error *err,
 			void *user_data)
 {
+	struct context *context = user_data;
 	int ret;
 
 	g_assert(err == NULL);
 
-	ret = avdtp_close(session, stream, FALSE);
+	if (g_str_equal(context->data->test_name, "/TP/SIG/SMG/BV-19-C"))
+		ret = avdtp_close(session, stream, FALSE);
+	else
+		ret = avdtp_suspend(session, stream);
 
 	g_assert_cmpint(ret, ==, 0);
 }
@@ -359,7 +363,8 @@ static void discover_cb(struct avdtp *session, GSList *seps,
 	uint8_t data[4] = { 0x21, 0x02, 2, 32 };
 	int ret;
 
-	if (!context)
+	if (g_str_equal(context->data->test_name, "/TP/SIG/SMG/BV-05-C") ||
+		g_str_equal(context->data->test_name, "/TP/SIG/SMG/BV-07-C"))
 		return;
 
 	g_assert(err == NULL);
@@ -391,92 +396,7 @@ static void discover_cb(struct avdtp *session, GSList *seps,
 	g_slist_free_full(caps, g_free);
 }
 
-static void test_discover(gconstpointer data)
-{
-	struct context *context = create_context(0x0100, data);
-
-	avdtp_discover(context->session, discover_cb, NULL);
-
-	execute_context(context);
-}
-
-static void test_get_capabilities(gconstpointer data)
-{
-	struct context *context = create_context(0x0100, data);
-
-	avdtp_discover(context->session, discover_cb, NULL);
-
-	execute_context(context);
-}
-
-static void test_set_configuration(gconstpointer data)
-{
-	struct context *context = create_context(0x0100, data);
-	struct avdtp_local_sep *sep;
-
-	sep = avdtp_register_sep(AVDTP_SEP_TYPE_SINK, AVDTP_MEDIA_TYPE_AUDIO,
-					0x00, FALSE, NULL, NULL, NULL);
-	context->sep = sep;
-
-	avdtp_discover(context->session, discover_cb, context);
-
-	execute_context(context);
-
-	avdtp_unregister_sep(sep);
-}
-
-static void test_get_configuration(gconstpointer data)
-{
-	struct context *context = create_context(0x0100, data);
-	struct avdtp_local_sep *sep;
-
-	sep = avdtp_register_sep(AVDTP_SEP_TYPE_SINK, AVDTP_MEDIA_TYPE_AUDIO,
-					0x00, FALSE, NULL, &sep_cfm,
-					context);
-	context->sep = sep;
-
-	avdtp_discover(context->session, discover_cb, context);
-
-	execute_context(context);
-
-	avdtp_unregister_sep(sep);
-}
-
-static void test_open(gconstpointer data)
-{
-	struct context *context = create_context(0x0100, data);
-	struct avdtp_local_sep *sep;
-
-	sep = avdtp_register_sep(AVDTP_SEP_TYPE_SINK, AVDTP_MEDIA_TYPE_AUDIO,
-					0x00, FALSE, NULL, &sep_cfm,
-					context);
-	context->sep = sep;
-
-	avdtp_discover(context->session, discover_cb, context);
-
-	execute_context(context);
-
-	avdtp_unregister_sep(sep);
-}
-
-static void test_start(gconstpointer data)
-{
-	struct context *context = create_context(0x0100, data);
-	struct avdtp_local_sep *sep;
-
-	sep = avdtp_register_sep(AVDTP_SEP_TYPE_SINK, AVDTP_MEDIA_TYPE_AUDIO,
-					0x00, FALSE, NULL, &sep_cfm,
-					context);
-	context->sep = sep;
-
-	avdtp_discover(context->session, discover_cb, context);
-
-	execute_context(context);
-
-	avdtp_unregister_sep(sep);
-}
-
-static void test_close(gconstpointer data)
+static void test_client(gconstpointer data)
 {
 	struct context *context = create_context(0x0100, data);
 	struct avdtp_local_sep *sep;
@@ -506,12 +426,12 @@ int main(int argc, char *argv[])
 	 * To verify that the following procedures are implemented according to
 	 * their specification in AVDTP.
 	 */
-	define_test("/TP/SIG/SMG/BV-05-C", test_discover,
+	define_test("/TP/SIG/SMG/BV-05-C", test_client,
 			raw_pdu(0x00, 0x01));
 	define_test("/TP/SIG/SMG/BV-06-C", test_server,
 			raw_pdu(0x00, 0x01),
 			raw_pdu(0x02, 0x01, 0x04, 0x00));
-	define_test("/TP/SIG/SMG/BV-07-C", test_get_capabilities,
+	define_test("/TP/SIG/SMG/BV-07-C", test_client,
 			raw_pdu(0x10, 0x01),
 			raw_pdu(0x12, 0x01, 0x04, 0x00),
 			raw_pdu(0x20, 0x02, 0x04));
@@ -521,7 +441,7 @@ int main(int argc, char *argv[])
 			raw_pdu(0x10, 0x02, 0x04),
 			raw_pdu(0x12, 0x02, 0x01, 0x00, 0x07, 0x06, 0x00, 0x00,
 				0xff, 0xff, 0x02, 0x40));
-	define_test("/TP/SIG/SMG/BV-09-C", test_set_configuration,
+	define_test("/TP/SIG/SMG/BV-09-C", test_client,
 			raw_pdu(0x30, 0x01),
 			raw_pdu(0x32, 0x01, 0x04, 0x00),
 			raw_pdu(0x40, 0x02, 0x04),
@@ -538,7 +458,7 @@ int main(int argc, char *argv[])
 			raw_pdu(0x20, 0x03, 0x04, 0x04, 0x01, 0x00, 0x07, 0x06,
 				0x00, 0x00, 0x21, 0x02, 0x02, 0x20),
 			raw_pdu(0x22, 0x03));
-	define_test("/TP/SIG/SMG/BV-11-C", test_get_configuration,
+	define_test("/TP/SIG/SMG/BV-11-C", test_client,
 			raw_pdu(0x60, 0x01),
 			raw_pdu(0x62, 0x01, 0x04, 0x00),
 			raw_pdu(0x70, 0x02, 0x04),
@@ -560,7 +480,7 @@ int main(int argc, char *argv[])
 			raw_pdu(0x30, 0x04, 0x04),
 			raw_pdu(0x32, 0x04, 0x01, 0x00, 0x07, 0x06, 0x00, 0x00,
 				0x21, 0x02, 0x02, 0x20));
-	define_test("/TP/SIG/SMG/BV-15-C", test_open,
+	define_test("/TP/SIG/SMG/BV-15-C", test_client,
 			raw_pdu(0xa0, 0x01),
 			raw_pdu(0xa2, 0x01, 0x04, 0x00),
 			raw_pdu(0xb0, 0x02, 0x04),
@@ -581,7 +501,7 @@ int main(int argc, char *argv[])
 			raw_pdu(0x22, 0x03),
 			raw_pdu(0x30, 0x06, 0x04),
 			raw_pdu(0x32, 0x06));
-	define_test("/TP/SIG/SMG/BV-17-C", test_start,
+	define_test("/TP/SIG/SMG/BV-17-C", test_client,
 			raw_pdu(0xe0, 0x01),
 			raw_pdu(0xe2, 0x01, 0x04, 0x00),
 			raw_pdu(0xf0, 0x02, 0x04),
@@ -606,7 +526,7 @@ int main(int argc, char *argv[])
 			raw_pdu(0x32, 0x06),
 			raw_pdu(0x40, 0x07, 0x04),
 			raw_pdu(0x42, 0x07));
-	define_test("/TP/SIG/SMG/BV-19-C", test_close,
+	define_test("/TP/SIG/SMG/BV-19-C", test_client,
 			raw_pdu(0x30, 0x01),
 			raw_pdu(0x32, 0x01, 0x04, 0x00),
 			raw_pdu(0x40, 0x02, 0x04),
@@ -635,6 +555,20 @@ int main(int argc, char *argv[])
 			raw_pdu(0x42, 0x07),
 			raw_pdu(0x50, 0x08, 0x04),
 			raw_pdu(0x52, 0x08));
+	define_test("/TP/SIG/SMG/BV-21-C", test_client,
+			raw_pdu(0x90, 0x01),
+			raw_pdu(0x92, 0x01, 0x04, 0x00),
+			raw_pdu(0xa0, 0x02, 0x04),
+			raw_pdu(0xa2, 0x02, 0x01, 0x00, 0x07, 0x06, 0x00, 0x00,
+				0xff, 0xff, 0x02, 0x40),
+			raw_pdu(0xb0, 0x03, 0x04, 0x04, 0x01, 0x00, 0x07, 0x06,
+				0x00, 0x00, 0x21, 0x02, 0x02, 0x20),
+			raw_pdu(0xb2, 0x03),
+			raw_pdu(0xc0, 0x06, 0x04),
+			raw_pdu(0xc2, 0x06),
+			raw_pdu(0xd0, 0x07, 0x04),
+			raw_pdu(0xd2, 0x07),
+			raw_pdu(0xe0, 0x09, 0x04));
 
 	return g_test_run();
 }
-- 
1.8.3.1


^ permalink raw reply related

* [PATCH v2 16/20] unit/AVDTP: Add /TP/SIG/SMG/BV-20-C test
From: Luiz Augusto von Dentz @ 2013-11-25 14:54 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1385391283-10962-1-git-send-email-luiz.dentz@gmail.com>

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

Verify that the IUT (ACP) is able to accept an AVDTP_CLOSE_CMD after the
streaming procedure has been started, by releasing all the resources
associated to the SEP, reporting of the closing and replying the
returned confirmation.
---
 unit/test-avdtp.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/unit/test-avdtp.c b/unit/test-avdtp.c
index c01e5fb..4677e22 100644
--- a/unit/test-avdtp.c
+++ b/unit/test-avdtp.c
@@ -620,6 +620,21 @@ int main(int argc, char *argv[])
 			raw_pdu(0x70, 0x07, 0x04),
 			raw_pdu(0x72, 0x07),
 			raw_pdu(0x80, 0x08, 0x04));
+	define_test("/TP/SIG/SMG/BV-20-C", test_server,
+			raw_pdu(0x00, 0x01),
+			raw_pdu(0x02, 0x01, 0x04, 0x00),
+			raw_pdu(0x10, 0x02, 0x04),
+			raw_pdu(0x12, 0x02, 0x01, 0x00, 0x07, 0x06, 0x00, 0x00,
+				0xff, 0xff, 0x02, 0x40),
+			raw_pdu(0x20, 0x03, 0x04, 0x04, 0x01, 0x00, 0x07, 0x06,
+				0x00, 0x00, 0x21, 0x02, 0x02, 0x20),
+			raw_pdu(0x22, 0x03),
+			raw_pdu(0x30, 0x06, 0x04),
+			raw_pdu(0x32, 0x06),
+			raw_pdu(0x40, 0x07, 0x04),
+			raw_pdu(0x42, 0x07),
+			raw_pdu(0x50, 0x08, 0x04),
+			raw_pdu(0x52, 0x08));
 
 	return g_test_run();
 }
-- 
1.8.3.1


^ permalink raw reply related

* [PATCH v2 15/20] unit/AVDTP: Add /TP/SIG/SMG/BV-19-C test
From: Luiz Augusto von Dentz @ 2013-11-25 14:54 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1385391283-10962-1-git-send-email-luiz.dentz@gmail.com>

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

Verify that the IUT (INT) is able to initiate the release of a streaming
procedure after the streaming procedure has been started, by issuing the
AVDTP_CLOSE_CMD, releasing all the resources associated to the SEP after
reception of the replied confirmation and reporting the closing.
---
 unit/test-avdtp.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 46 insertions(+), 5 deletions(-)

diff --git a/unit/test-avdtp.c b/unit/test-avdtp.c
index 615df00..c01e5fb 100644
--- a/unit/test-avdtp.c
+++ b/unit/test-avdtp.c
@@ -293,12 +293,8 @@ static void sep_setconf_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
 
 	if (g_str_equal(context->data->test_name, "/TP/SIG/SMG/BV-11-C"))
 		ret = avdtp_get_configuration(session, stream);
-	else if (g_str_equal(context->data->test_name, "/TP/SIG/SMG/BV-15-C"))
-		ret = avdtp_open(session, stream);
-	else if (g_str_equal(context->data->test_name, "/TP/SIG/SMG/BV-17-C"))
-		ret = avdtp_open(session, stream);
 	else
-		g_assert_not_reached();
+		ret = avdtp_open(session, stream);
 
 	g_assert_cmpint(ret, ==, 0);
 }
@@ -317,9 +313,23 @@ static void sep_open_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
 	g_assert_cmpint(ret, ==, 0);
 }
 
+static void sep_start_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
+			struct avdtp_stream *stream, struct avdtp_error *err,
+			void *user_data)
+{
+	int ret;
+
+	g_assert(err == NULL);
+
+	ret = avdtp_close(session, stream, FALSE);
+
+	g_assert_cmpint(ret, ==, 0);
+}
+
 static struct avdtp_sep_cfm sep_cfm = {
 	.set_configuration	= sep_setconf_cfm,
 	.open			= sep_open_cfm,
+	.start			= sep_start_cfm,
 };
 
 static void test_server(gconstpointer data)
@@ -466,6 +476,23 @@ static void test_start(gconstpointer data)
 	avdtp_unregister_sep(sep);
 }
 
+static void test_close(gconstpointer data)
+{
+	struct context *context = create_context(0x0100, data);
+	struct avdtp_local_sep *sep;
+
+	sep = avdtp_register_sep(AVDTP_SEP_TYPE_SINK, AVDTP_MEDIA_TYPE_AUDIO,
+					0x00, FALSE, NULL, &sep_cfm,
+					context);
+	context->sep = sep;
+
+	avdtp_discover(context->session, discover_cb, context);
+
+	execute_context(context);
+
+	avdtp_unregister_sep(sep);
+}
+
 int main(int argc, char *argv[])
 {
 	g_test_init(&argc, &argv, NULL);
@@ -579,6 +606,20 @@ int main(int argc, char *argv[])
 			raw_pdu(0x32, 0x06),
 			raw_pdu(0x40, 0x07, 0x04),
 			raw_pdu(0x42, 0x07));
+	define_test("/TP/SIG/SMG/BV-19-C", test_close,
+			raw_pdu(0x30, 0x01),
+			raw_pdu(0x32, 0x01, 0x04, 0x00),
+			raw_pdu(0x40, 0x02, 0x04),
+			raw_pdu(0x42, 0x02, 0x01, 0x00, 0x07, 0x06, 0x00, 0x00,
+				0xff, 0xff, 0x02, 0x40),
+			raw_pdu(0x50, 0x03, 0x04, 0x04, 0x01, 0x00, 0x07, 0x06,
+				0x00, 0x00, 0x21, 0x02, 0x02, 0x20),
+			raw_pdu(0x52, 0x03),
+			raw_pdu(0x60, 0x06, 0x04),
+			raw_pdu(0x62, 0x06),
+			raw_pdu(0x70, 0x07, 0x04),
+			raw_pdu(0x72, 0x07),
+			raw_pdu(0x80, 0x08, 0x04));
 
 	return g_test_run();
 }
-- 
1.8.3.1


^ permalink raw reply related

* [PATCH v2 14/20] unit/AVDTP: Add /TP/SIG/SMG/BV-18-C test
From: Luiz Augusto von Dentz @ 2013-11-25 14:54 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1385391283-10962-1-git-send-email-luiz.dentz@gmail.com>

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

To verify that the IUT (ACP) reports the reception of valid
AVDTP_START_CMD and replies the returned confirmation.
---
 unit/test-avdtp.c | 138 ++++++++++++++++++++++++++++++------------------------
 1 file changed, 76 insertions(+), 62 deletions(-)

diff --git a/unit/test-avdtp.c b/unit/test-avdtp.c
index 7d2c7bc..615df00 100644
--- a/unit/test-avdtp.c
+++ b/unit/test-avdtp.c
@@ -46,6 +46,7 @@ struct test_pdu {
 };
 
 struct test_data {
+	char *test_name;
 	struct test_pdu *pdu_list;
 };
 
@@ -64,20 +65,23 @@ struct test_data {
 			args, { }, { }					\
 		};							\
 		static struct test_data data;				\
+		data.test_name = g_strdup(name);			\
 		data.pdu_list = g_malloc(sizeof(pdus));			\
 		memcpy(data.pdu_list, pdus, sizeof(pdus));		\
-		g_test_add_data_func(name, &data, function);		\
+		g_test_add_data_func_full(name, &data, function, test_free); \
 	} while (0)
 
 struct context {
 	GMainLoop *main_loop;
 	struct avdtp *session;
 	struct avdtp_local_sep *sep;
+	struct avdtp_stream *stream;
 	guint source;
 	int fd;
 	int mtu;
+	gboolean pending_open;
 	unsigned int pdu_offset;
-	const struct test_pdu *pdu_list;
+	const struct test_data *data;
 };
 
 static void test_debug(const char *str, void *user_data)
@@ -87,6 +91,14 @@ static void test_debug(const char *str, void *user_data)
 	g_print("%s%s\n", prefix, str);
 }
 
+static void test_free(void *user_data)
+{
+	struct test_data *data = user_data;
+
+	g_free(data->test_name);
+	g_free(data->pdu_list);
+}
+
 static void context_quit(struct context *context)
 {
 	g_main_loop_quit(context->main_loop);
@@ -98,7 +110,7 @@ static gboolean send_pdu(gpointer user_data)
 	const struct test_pdu *pdu;
 	ssize_t len;
 
-	pdu = &context->pdu_list[context->pdu_offset++];
+	pdu = &context->data->pdu_list[context->pdu_offset++];
 
 	len = write(context->fd, pdu->data, pdu->size);
 
@@ -112,7 +124,7 @@ static gboolean send_pdu(gpointer user_data)
 
 static void context_process(struct context *context)
 {
-	if (!context->pdu_list[context->pdu_offset].valid) {
+	if (!context->data->pdu_list[context->pdu_offset].valid) {
 		context_quit(context);
 		return;
 	}
@@ -120,6 +132,17 @@ static void context_process(struct context *context)
 	g_idle_add(send_pdu, context);
 }
 
+static gboolean transport_open(struct avdtp_stream *stream)
+{
+	int fd;
+
+	fd = open("/dev/null", O_RDWR, 0);
+	if (fd < 0)
+		g_assert_not_reached();
+
+	return avdtp_stream_set_transport(stream, fd, 672, 672);
+}
+
 static gboolean test_handler(GIOChannel *channel, GIOCondition cond,
 							gpointer user_data)
 {
@@ -129,7 +152,7 @@ static gboolean test_handler(GIOChannel *channel, GIOCondition cond,
 	ssize_t len;
 	int fd;
 
-	pdu = &context->pdu_list[context->pdu_offset++];
+	pdu = &context->data->pdu_list[context->pdu_offset++];
 
 	if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP))
 		return FALSE;
@@ -147,12 +170,17 @@ static gboolean test_handler(GIOChannel *channel, GIOCondition cond,
 
 	g_assert(memcmp(buf, pdu->data, pdu->size) == 0);
 
+	if (context->pending_open) {
+		context->pending_open = FALSE;
+		g_assert(transport_open(context->stream));
+	}
+
 	context_process(context);
 
 	return TRUE;
 }
 
-static struct context *create_context(uint16_t version)
+static struct context *create_context(uint16_t version, gconstpointer data)
 {
 	struct context *context = g_new0(struct context, 1);
 	GIOChannel *channel;
@@ -181,6 +209,7 @@ static struct context *create_context(uint16_t version)
 	g_io_channel_unref(channel);
 
 	context->fd = sv[1];
+	context->data = data;
 
 	return context;
 }
@@ -227,8 +256,21 @@ static gboolean sep_getcap_ind(struct avdtp *session,
 	return TRUE;
 }
 
+static gboolean sep_open_ind(struct avdtp *session, struct avdtp_local_sep *sep,
+				struct avdtp_stream *stream, uint8_t *err,
+				void *user_data)
+{
+	struct context *context = user_data;
+
+	context->pending_open = TRUE;
+	context->stream = stream;
+
+	return TRUE;
+}
+
 static struct avdtp_sep_ind sep_ind = {
 	.get_capability		= sep_getcap_ind,
+	.open			= sep_open_ind,
 };
 
 static void sep_setconf_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
@@ -244,21 +286,19 @@ static void sep_setconf_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
 	if (!context)
 		return;
 
-	pdu = &context->pdu_list[context->pdu_offset];
+	pdu = &context->data->pdu_list[context->pdu_offset];
 
 	if (pdu->size < 2)
 		return;
 
-	switch (pdu->data[1]) {
-	case 0x04:
+	if (g_str_equal(context->data->test_name, "/TP/SIG/SMG/BV-11-C"))
 		ret = avdtp_get_configuration(session, stream);
-		break;
-	case 0x06:
+	else if (g_str_equal(context->data->test_name, "/TP/SIG/SMG/BV-15-C"))
 		ret = avdtp_open(session, stream);
-		break;
-	default:
+	else if (g_str_equal(context->data->test_name, "/TP/SIG/SMG/BV-17-C"))
+		ret = avdtp_open(session, stream);
+	else
 		g_assert_not_reached();
-	}
 
 	g_assert_cmpint(ret, ==, 0);
 }
@@ -271,11 +311,7 @@ static void sep_open_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
 
 	g_assert(err == NULL);
 
-	ret = open("/dev/null", O_RDWR, 0);
-	if (ret < 0)
-		g_assert_not_reached();
-
-	avdtp_stream_set_transport(stream, ret, 672, 672);
+	g_assert(transport_open(stream));
 
 	ret = avdtp_start(session, stream);
 	g_assert_cmpint(ret, ==, 0);
@@ -288,22 +324,17 @@ static struct avdtp_sep_cfm sep_cfm = {
 
 static void test_server(gconstpointer data)
 {
-	const struct test_data *test = data;
-	struct context *context = create_context(0x0100);
+	struct context *context = create_context(0x0100, data);
 	struct avdtp_local_sep *sep;
 
-	context->pdu_list = test->pdu_list;
-
 	sep = avdtp_register_sep(AVDTP_SEP_TYPE_SOURCE, AVDTP_MEDIA_TYPE_AUDIO,
-					0x00, TRUE, &sep_ind, NULL, NULL);
+					0x00, TRUE, &sep_ind, NULL, context);
 
 	g_idle_add(send_pdu, context);
 
 	execute_context(context);
 
 	avdtp_unregister_sep(sep);
-
-	g_free(test->pdu_list);
 }
 
 static void discover_cb(struct avdtp *session, GSList *seps,
@@ -352,40 +383,27 @@ static void discover_cb(struct avdtp *session, GSList *seps,
 
 static void test_discover(gconstpointer data)
 {
-	const struct test_data *test = data;
-	struct context *context = create_context(0x0100);
-
-	context->pdu_list = test->pdu_list;
+	struct context *context = create_context(0x0100, data);
 
 	avdtp_discover(context->session, discover_cb, NULL);
 
 	execute_context(context);
-
-	g_free(test->pdu_list);
 }
 
 static void test_get_capabilities(gconstpointer data)
 {
-	const struct test_data *test = data;
-	struct context *context = create_context(0x0100);
-
-	context->pdu_list = test->pdu_list;
+	struct context *context = create_context(0x0100, data);
 
 	avdtp_discover(context->session, discover_cb, NULL);
 
 	execute_context(context);
-
-	g_free(test->pdu_list);
 }
 
 static void test_set_configuration(gconstpointer data)
 {
-	const struct test_data *test = data;
-	struct context *context = create_context(0x0100);
+	struct context *context = create_context(0x0100, data);
 	struct avdtp_local_sep *sep;
 
-	context->pdu_list = test->pdu_list;
-
 	sep = avdtp_register_sep(AVDTP_SEP_TYPE_SINK, AVDTP_MEDIA_TYPE_AUDIO,
 					0x00, FALSE, NULL, NULL, NULL);
 	context->sep = sep;
@@ -395,18 +413,13 @@ static void test_set_configuration(gconstpointer data)
 	execute_context(context);
 
 	avdtp_unregister_sep(sep);
-
-	g_free(test->pdu_list);
 }
 
 static void test_get_configuration(gconstpointer data)
 {
-	const struct test_data *test = data;
-	struct context *context = create_context(0x0100);
+	struct context *context = create_context(0x0100, data);
 	struct avdtp_local_sep *sep;
 
-	context->pdu_list = test->pdu_list;
-
 	sep = avdtp_register_sep(AVDTP_SEP_TYPE_SINK, AVDTP_MEDIA_TYPE_AUDIO,
 					0x00, FALSE, NULL, &sep_cfm,
 					context);
@@ -417,18 +430,13 @@ static void test_get_configuration(gconstpointer data)
 	execute_context(context);
 
 	avdtp_unregister_sep(sep);
-
-	g_free(test->pdu_list);
 }
 
 static void test_open(gconstpointer data)
 {
-	const struct test_data *test = data;
-	struct context *context = create_context(0x0100);
+	struct context *context = create_context(0x0100, data);
 	struct avdtp_local_sep *sep;
 
-	context->pdu_list = test->pdu_list;
-
 	sep = avdtp_register_sep(AVDTP_SEP_TYPE_SINK, AVDTP_MEDIA_TYPE_AUDIO,
 					0x00, FALSE, NULL, &sep_cfm,
 					context);
@@ -439,18 +447,13 @@ static void test_open(gconstpointer data)
 	execute_context(context);
 
 	avdtp_unregister_sep(sep);
-
-	g_free(test->pdu_list);
 }
 
 static void test_start(gconstpointer data)
 {
-	const struct test_data *test = data;
-	struct context *context = create_context(0x0100);
+	struct context *context = create_context(0x0100, data);
 	struct avdtp_local_sep *sep;
 
-	context->pdu_list = test->pdu_list;
-
 	sep = avdtp_register_sep(AVDTP_SEP_TYPE_SINK, AVDTP_MEDIA_TYPE_AUDIO,
 					0x00, FALSE, NULL, &sep_cfm,
 					context);
@@ -461,8 +464,6 @@ static void test_start(gconstpointer data)
 	execute_context(context);
 
 	avdtp_unregister_sep(sep);
-
-	g_free(test->pdu_list);
 }
 
 int main(int argc, char *argv[])
@@ -565,6 +566,19 @@ int main(int argc, char *argv[])
 			raw_pdu(0x10, 0x06, 0x04),
 			raw_pdu(0x12, 0x06),
 			raw_pdu(0x20, 0x07, 0x04));
+	define_test("/TP/SIG/SMG/BV-18-C", test_server,
+			raw_pdu(0x00, 0x01),
+			raw_pdu(0x02, 0x01, 0x04, 0x00),
+			raw_pdu(0x10, 0x02, 0x04),
+			raw_pdu(0x12, 0x02, 0x01, 0x00, 0x07, 0x06, 0x00, 0x00,
+				0xff, 0xff, 0x02, 0x40),
+			raw_pdu(0x20, 0x03, 0x04, 0x04, 0x01, 0x00, 0x07, 0x06,
+				0x00, 0x00, 0x21, 0x02, 0x02, 0x20),
+			raw_pdu(0x22, 0x03),
+			raw_pdu(0x30, 0x06, 0x04),
+			raw_pdu(0x32, 0x06),
+			raw_pdu(0x40, 0x07, 0x04),
+			raw_pdu(0x42, 0x07));
 
 	return g_test_run();
 }
-- 
1.8.3.1


^ permalink raw reply related

* [PATCH v2 13/20] unit/AVDTP: Add /TP/SIG/SMG/BV-17-C test
From: Luiz Augusto von Dentz @ 2013-11-25 14:54 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1385391283-10962-1-git-send-email-luiz.dentz@gmail.com>

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

Verify that the IUT (INT) is able to start a streaming procedure after
the stream establishment is complete, by issuing the AVDTP_START_CMD,
reporting the replied confirmation and streaming packets.
---
 unit/test-avdtp.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 54 insertions(+)

diff --git a/unit/test-avdtp.c b/unit/test-avdtp.c
index 2bf782c..7d2c7bc 100644
--- a/unit/test-avdtp.c
+++ b/unit/test-avdtp.c
@@ -30,6 +30,7 @@
 #include <stdbool.h>
 #include <inttypes.h>
 #include <string.h>
+#include <fcntl.h>
 #include <sys/socket.h>
 
 #include <glib.h>
@@ -262,8 +263,27 @@ static void sep_setconf_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
 	g_assert_cmpint(ret, ==, 0);
 }
 
+static void sep_open_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
+			struct avdtp_stream *stream, struct avdtp_error *err,
+			void *user_data)
+{
+	int ret;
+
+	g_assert(err == NULL);
+
+	ret = open("/dev/null", O_RDWR, 0);
+	if (ret < 0)
+		g_assert_not_reached();
+
+	avdtp_stream_set_transport(stream, ret, 672, 672);
+
+	ret = avdtp_start(session, stream);
+	g_assert_cmpint(ret, ==, 0);
+}
+
 static struct avdtp_sep_cfm sep_cfm = {
 	.set_configuration	= sep_setconf_cfm,
+	.open			= sep_open_cfm,
 };
 
 static void test_server(gconstpointer data)
@@ -423,6 +443,28 @@ static void test_open(gconstpointer data)
 	g_free(test->pdu_list);
 }
 
+static void test_start(gconstpointer data)
+{
+	const struct test_data *test = data;
+	struct context *context = create_context(0x0100);
+	struct avdtp_local_sep *sep;
+
+	context->pdu_list = test->pdu_list;
+
+	sep = avdtp_register_sep(AVDTP_SEP_TYPE_SINK, AVDTP_MEDIA_TYPE_AUDIO,
+					0x00, FALSE, NULL, &sep_cfm,
+					context);
+	context->sep = sep;
+
+	avdtp_discover(context->session, discover_cb, context);
+
+	execute_context(context);
+
+	avdtp_unregister_sep(sep);
+
+	g_free(test->pdu_list);
+}
+
 int main(int argc, char *argv[])
 {
 	g_test_init(&argc, &argv, NULL);
@@ -511,6 +553,18 @@ int main(int argc, char *argv[])
 			raw_pdu(0x22, 0x03),
 			raw_pdu(0x30, 0x06, 0x04),
 			raw_pdu(0x32, 0x06));
+	define_test("/TP/SIG/SMG/BV-17-C", test_start,
+			raw_pdu(0xe0, 0x01),
+			raw_pdu(0xe2, 0x01, 0x04, 0x00),
+			raw_pdu(0xf0, 0x02, 0x04),
+			raw_pdu(0xf2, 0x02, 0x01, 0x00, 0x07, 0x06, 0x00, 0x00,
+				0xff, 0xff, 0x02, 0x40),
+			raw_pdu(0x00, 0x03, 0x04, 0x04, 0x01, 0x00, 0x07, 0x06,
+				0x00, 0x00, 0x21, 0x02, 0x02, 0x20),
+			raw_pdu(0x02, 0x03),
+			raw_pdu(0x10, 0x06, 0x04),
+			raw_pdu(0x12, 0x06),
+			raw_pdu(0x20, 0x07, 0x04));
 
 	return g_test_run();
 }
-- 
1.8.3.1


^ permalink raw reply related

* [PATCH v2 12/20] unit/AVDTP: Add /TP/SIG/SMG/BV-16-C test
From: Luiz Augusto von Dentz @ 2013-11-25 14:54 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1385391283-10962-1-git-send-email-luiz.dentz@gmail.com>

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

Verify that the IUT (ACP) reports the reception of valid AVDTP_OPEN_CMD
for transport sessions associated to a SEP and replies the returned
confirmation.
---
 unit/test-avdtp.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/unit/test-avdtp.c b/unit/test-avdtp.c
index 4e46987..2bf782c 100644
--- a/unit/test-avdtp.c
+++ b/unit/test-avdtp.c
@@ -500,6 +500,17 @@ int main(int argc, char *argv[])
 				0x00, 0x00, 0x21, 0x02, 0x02, 0x20),
 			raw_pdu(0xc2, 0x03),
 			raw_pdu(0xd0, 0x06, 0x04));
+	define_test("/TP/SIG/SMG/BV-16-C", test_server,
+			raw_pdu(0x00, 0x01),
+			raw_pdu(0x02, 0x01, 0x04, 0x00),
+			raw_pdu(0x10, 0x02, 0x04),
+			raw_pdu(0x12, 0x02, 0x01, 0x00, 0x07, 0x06, 0x00, 0x00,
+				0xff, 0xff, 0x02, 0x40),
+			raw_pdu(0x20, 0x03, 0x04, 0x04, 0x01, 0x00, 0x07, 0x06,
+				0x00, 0x00, 0x21, 0x02, 0x02, 0x20),
+			raw_pdu(0x22, 0x03),
+			raw_pdu(0x30, 0x06, 0x04),
+			raw_pdu(0x32, 0x06));
 
 	return g_test_run();
 }
-- 
1.8.3.1


^ permalink raw reply related

* [PATCH v2 11/20] unit/AVDTP: Add /TP/SIG/SMG/BV-15-C test
From: Luiz Augusto von Dentz @ 2013-11-25 14:54 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1385391283-10962-1-git-send-email-luiz.dentz@gmail.com>

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

Verify that the IUT (INT) is able to establish a stream connection to a
previously configured remote SEP by establishing one L2CAP channel
(AVDTP_OPEN_CMD), and reports the related confirmation.
---
 unit/test-avdtp.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 54 insertions(+), 2 deletions(-)

diff --git a/unit/test-avdtp.c b/unit/test-avdtp.c
index a266819..4e46987 100644
--- a/unit/test-avdtp.c
+++ b/unit/test-avdtp.c
@@ -40,7 +40,7 @@
 
 struct test_pdu {
 	bool valid;
-	const void *data;
+	const uint8_t *data;
 	size_t size;
 };
 
@@ -234,11 +234,31 @@ static void sep_setconf_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
 				struct avdtp_stream *stream,
 				struct avdtp_error *err, void *user_data)
 {
+	struct context *context = user_data;
+	const struct test_pdu *pdu;
 	int ret;
 
 	g_assert(err == NULL);
 
-	ret = avdtp_get_configuration(session, stream);
+	if (!context)
+		return;
+
+	pdu = &context->pdu_list[context->pdu_offset];
+
+	if (pdu->size < 2)
+		return;
+
+	switch (pdu->data[1]) {
+	case 0x04:
+		ret = avdtp_get_configuration(session, stream);
+		break;
+	case 0x06:
+		ret = avdtp_open(session, stream);
+		break;
+	default:
+		g_assert_not_reached();
+	}
+
 	g_assert_cmpint(ret, ==, 0);
 }
 
@@ -381,6 +401,28 @@ static void test_get_configuration(gconstpointer data)
 	g_free(test->pdu_list);
 }
 
+static void test_open(gconstpointer data)
+{
+	const struct test_data *test = data;
+	struct context *context = create_context(0x0100);
+	struct avdtp_local_sep *sep;
+
+	context->pdu_list = test->pdu_list;
+
+	sep = avdtp_register_sep(AVDTP_SEP_TYPE_SINK, AVDTP_MEDIA_TYPE_AUDIO,
+					0x00, FALSE, NULL, &sep_cfm,
+					context);
+	context->sep = sep;
+
+	avdtp_discover(context->session, discover_cb, context);
+
+	execute_context(context);
+
+	avdtp_unregister_sep(sep);
+
+	g_free(test->pdu_list);
+}
+
 int main(int argc, char *argv[])
 {
 	g_test_init(&argc, &argv, NULL);
@@ -448,6 +490,16 @@ int main(int argc, char *argv[])
 			raw_pdu(0x30, 0x04, 0x04),
 			raw_pdu(0x32, 0x04, 0x01, 0x00, 0x07, 0x06, 0x00, 0x00,
 				0x21, 0x02, 0x02, 0x20));
+	define_test("/TP/SIG/SMG/BV-15-C", test_open,
+			raw_pdu(0xa0, 0x01),
+			raw_pdu(0xa2, 0x01, 0x04, 0x00),
+			raw_pdu(0xb0, 0x02, 0x04),
+			raw_pdu(0xb2, 0x02, 0x01, 0x00, 0x07, 0x06, 0x00, 0x00,
+				0xff, 0xff, 0x02, 0x40),
+			raw_pdu(0xc0, 0x03, 0x04, 0x04, 0x01, 0x00, 0x07, 0x06,
+				0x00, 0x00, 0x21, 0x02, 0x02, 0x20),
+			raw_pdu(0xc2, 0x03),
+			raw_pdu(0xd0, 0x06, 0x04));
 
 	return g_test_run();
 }
-- 
1.8.3.1


^ permalink raw reply related

* [PATCH v2 10/20] unit/AVDTP: Add /TP/SIG/SMG/BV-12-C test
From: Luiz Augusto von Dentz @ 2013-11-25 14:54 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1385391283-10962-1-git-send-email-luiz.dentz@gmail.com>

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

Verify that the IUT (ACP) reports the reception of a valid get
configuration command for remote SEP and replies the returned
configuration.
---
 unit/test-avdtp.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/unit/test-avdtp.c b/unit/test-avdtp.c
index 1f43c08..a266819 100644
--- a/unit/test-avdtp.c
+++ b/unit/test-avdtp.c
@@ -368,7 +368,8 @@ static void test_get_configuration(gconstpointer data)
 	context->pdu_list = test->pdu_list;
 
 	sep = avdtp_register_sep(AVDTP_SEP_TYPE_SINK, AVDTP_MEDIA_TYPE_AUDIO,
-					0x00, FALSE, &sep_ind, &sep_cfm, NULL);
+					0x00, FALSE, NULL, &sep_cfm,
+					context);
 	context->sep = sep;
 
 	avdtp_discover(context->session, discover_cb, context);
@@ -435,6 +436,18 @@ int main(int argc, char *argv[])
 				0x00, 0x00, 0x21, 0x02, 0x02, 0x20),
 			raw_pdu(0x82, 0x03),
 			raw_pdu(0x90, 0x04, 0x04));
+	define_test("/TP/SIG/SMG/BV-12-C", test_server,
+			raw_pdu(0x00, 0x01),
+			raw_pdu(0x02, 0x01, 0x04, 0x00),
+			raw_pdu(0x10, 0x02, 0x04),
+			raw_pdu(0x12, 0x02, 0x01, 0x00, 0x07, 0x06, 0x00, 0x00,
+				0xff, 0xff, 0x02, 0x40),
+			raw_pdu(0x20, 0x03, 0x04, 0x04, 0x01, 0x00, 0x07, 0x06,
+				0x00, 0x00, 0x21, 0x02, 0x02, 0x20),
+			raw_pdu(0x22, 0x03),
+			raw_pdu(0x30, 0x04, 0x04),
+			raw_pdu(0x32, 0x04, 0x01, 0x00, 0x07, 0x06, 0x00, 0x00,
+				0x21, 0x02, 0x02, 0x20));
 
 	return g_test_run();
 }
-- 
1.8.3.1


^ permalink raw reply related

* [PATCH v2 09/20] unit/AVDTP: Add /TP/SIG/SMG/BV-11-C test
From: Luiz Augusto von Dentz @ 2013-11-25 14:54 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1385391283-10962-1-git-send-email-luiz.dentz@gmail.com>

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

Verify that the IUT (INT) is able to issue a valid get configuration
command for remote SEP and report the replied configuration.
---
 unit/test-avdtp.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/unit/test-avdtp.c b/unit/test-avdtp.c
index e39ed24..1f43c08 100644
--- a/unit/test-avdtp.c
+++ b/unit/test-avdtp.c
@@ -230,6 +230,22 @@ static struct avdtp_sep_ind sep_ind = {
 	.get_capability		= sep_getcap_ind,
 };
 
+static void sep_setconf_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
+				struct avdtp_stream *stream,
+				struct avdtp_error *err, void *user_data)
+{
+	int ret;
+
+	g_assert(err == NULL);
+
+	ret = avdtp_get_configuration(session, stream);
+	g_assert_cmpint(ret, ==, 0);
+}
+
+static struct avdtp_sep_cfm sep_cfm = {
+	.set_configuration	= sep_setconf_cfm,
+};
+
 static void test_server(gconstpointer data)
 {
 	const struct test_data *test = data;
@@ -343,6 +359,27 @@ static void test_set_configuration(gconstpointer data)
 	g_free(test->pdu_list);
 }
 
+static void test_get_configuration(gconstpointer data)
+{
+	const struct test_data *test = data;
+	struct context *context = create_context(0x0100);
+	struct avdtp_local_sep *sep;
+
+	context->pdu_list = test->pdu_list;
+
+	sep = avdtp_register_sep(AVDTP_SEP_TYPE_SINK, AVDTP_MEDIA_TYPE_AUDIO,
+					0x00, FALSE, &sep_ind, &sep_cfm, NULL);
+	context->sep = sep;
+
+	avdtp_discover(context->session, discover_cb, context);
+
+	execute_context(context);
+
+	avdtp_unregister_sep(sep);
+
+	g_free(test->pdu_list);
+}
+
 int main(int argc, char *argv[])
 {
 	g_test_init(&argc, &argv, NULL);
@@ -388,6 +425,16 @@ int main(int argc, char *argv[])
 			raw_pdu(0x20, 0x03, 0x04, 0x04, 0x01, 0x00, 0x07, 0x06,
 				0x00, 0x00, 0x21, 0x02, 0x02, 0x20),
 			raw_pdu(0x22, 0x03));
+	define_test("/TP/SIG/SMG/BV-11-C", test_get_configuration,
+			raw_pdu(0x60, 0x01),
+			raw_pdu(0x62, 0x01, 0x04, 0x00),
+			raw_pdu(0x70, 0x02, 0x04),
+			raw_pdu(0x72, 0x02, 0x01, 0x00, 0x07, 0x06, 0x00, 0x00,
+				0xff, 0xff, 0x02, 0x40),
+			raw_pdu(0x80, 0x03, 0x04, 0x04, 0x01, 0x00, 0x07, 0x06,
+				0x00, 0x00, 0x21, 0x02, 0x02, 0x20),
+			raw_pdu(0x82, 0x03),
+			raw_pdu(0x90, 0x04, 0x04));
 
 	return g_test_run();
 }
-- 
1.8.3.1


^ permalink raw reply related

* [PATCH v2 08/20] unit/AVDTP: Add /TP/SIG/SMG/BV-10-C test
From: Luiz Augusto von Dentz @ 2013-11-25 14:54 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1385391283-10962-1-git-send-email-luiz.dentz@gmail.com>

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

Verify that the IUT (ACP) reports the reception of a valid set
configuration command for remote SEP, and configures the SEP as
requested and replies the returned confirmation.
---
 unit/test-avdtp.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/unit/test-avdtp.c b/unit/test-avdtp.c
index b0991d9..e39ed24 100644
--- a/unit/test-avdtp.c
+++ b/unit/test-avdtp.c
@@ -379,6 +379,15 @@ int main(int argc, char *argv[])
 				0xff, 0xff, 0x02, 0x40),
 			raw_pdu(0x50, 0x03, 0x04, 0x04, 0x01, 0x00, 0x07, 0x06,
 				0x00, 0x00, 0x21, 0x02, 0x02, 0x20));
+	define_test("/TP/SIG/SMG/BV-10-C", test_server,
+			raw_pdu(0x00, 0x01),
+			raw_pdu(0x02, 0x01, 0x04, 0x00),
+			raw_pdu(0x10, 0x02, 0x04),
+			raw_pdu(0x12, 0x02, 0x01, 0x00, 0x07, 0x06, 0x00, 0x00,
+				0xff, 0xff, 0x02, 0x40),
+			raw_pdu(0x20, 0x03, 0x04, 0x04, 0x01, 0x00, 0x07, 0x06,
+				0x00, 0x00, 0x21, 0x02, 0x02, 0x20),
+			raw_pdu(0x22, 0x03));
 
 	return g_test_run();
 }
-- 
1.8.3.1


^ permalink raw reply related

* [PATCH v2 07/20] unit/AVDTP: Add /TP/SIG/SMG/BV-09-C test
From: Luiz Augusto von Dentz @ 2013-11-25 14:54 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1385391283-10962-1-git-send-email-luiz.dentz@gmail.com>

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

Verify that the IUT (INT) is able to issue a valid set configuration
command for remote SEP and reports the replied confirmation.
---
 unit/test-avdtp.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 68 insertions(+)

diff --git a/unit/test-avdtp.c b/unit/test-avdtp.c
index 0b92489..b0991d9 100644
--- a/unit/test-avdtp.c
+++ b/unit/test-avdtp.c
@@ -71,6 +71,7 @@ struct test_data {
 struct context {
 	GMainLoop *main_loop;
 	struct avdtp *session;
+	struct avdtp_local_sep *sep;
 	guint source;
 	int fd;
 	int mtu;
@@ -252,7 +253,45 @@ static void test_server(gconstpointer data)
 static void discover_cb(struct avdtp *session, GSList *seps,
 				struct avdtp_error *err, void *user_data)
 {
+	struct context *context = user_data;
+	struct avdtp_stream *stream;
+	struct avdtp_remote_sep *rsep;
+	struct avdtp_service_capability *media_transport, *media_codec;
+	struct avdtp_media_codec_capability *cap;
+	GSList *caps;
+	uint8_t data[4] = { 0x21, 0x02, 2, 32 };
+	int ret;
+
+	if (!context)
+		return;
+
+	g_assert(err == NULL);
+	g_assert_cmpint(g_slist_length(seps), !=, 0);
+
+	rsep = avdtp_find_remote_sep(session, context->sep);
+	g_assert(rsep != NULL);
+
+	media_transport = avdtp_service_cap_new(AVDTP_MEDIA_TRANSPORT,
+						NULL, 0);
+
+	caps = g_slist_append(NULL, media_transport);
+
+	cap = g_malloc0(sizeof(*cap) + sizeof(data));
+	cap->media_type = AVDTP_MEDIA_TYPE_AUDIO;
+	cap->media_codec_type = 0x00;
+	memcpy(cap->data, data, sizeof(data));
 
+	media_codec = avdtp_service_cap_new(AVDTP_MEDIA_CODEC, cap,
+						sizeof(*cap) + sizeof(data));
+
+	caps = g_slist_append(caps, media_codec);
+	g_free(cap);
+
+	ret = avdtp_set_configuration(session, rsep, context->sep, caps,
+								&stream);
+	g_assert_cmpint(ret, ==, 0);
+
+	g_slist_free_full(caps, g_free);
 }
 
 static void test_discover(gconstpointer data)
@@ -283,6 +322,27 @@ static void test_get_capabilities(gconstpointer data)
 	g_free(test->pdu_list);
 }
 
+static void test_set_configuration(gconstpointer data)
+{
+	const struct test_data *test = data;
+	struct context *context = create_context(0x0100);
+	struct avdtp_local_sep *sep;
+
+	context->pdu_list = test->pdu_list;
+
+	sep = avdtp_register_sep(AVDTP_SEP_TYPE_SINK, AVDTP_MEDIA_TYPE_AUDIO,
+					0x00, FALSE, NULL, NULL, NULL);
+	context->sep = sep;
+
+	avdtp_discover(context->session, discover_cb, context);
+
+	execute_context(context);
+
+	avdtp_unregister_sep(sep);
+
+	g_free(test->pdu_list);
+}
+
 int main(int argc, char *argv[])
 {
 	g_test_init(&argc, &argv, NULL);
@@ -311,6 +371,14 @@ int main(int argc, char *argv[])
 			raw_pdu(0x10, 0x02, 0x04),
 			raw_pdu(0x12, 0x02, 0x01, 0x00, 0x07, 0x06, 0x00, 0x00,
 				0xff, 0xff, 0x02, 0x40));
+	define_test("/TP/SIG/SMG/BV-09-C", test_set_configuration,
+			raw_pdu(0x30, 0x01),
+			raw_pdu(0x32, 0x01, 0x04, 0x00),
+			raw_pdu(0x40, 0x02, 0x04),
+			raw_pdu(0x42, 0x02, 0x01, 0x00, 0x07, 0x06, 0x00, 0x00,
+				0xff, 0xff, 0x02, 0x40),
+			raw_pdu(0x50, 0x03, 0x04, 0x04, 0x01, 0x00, 0x07, 0x06,
+				0x00, 0x00, 0x21, 0x02, 0x02, 0x20));
 
 	return g_test_run();
 }
-- 
1.8.3.1


^ permalink raw reply related

* [PATCH v2 06/20] unit/AVDTP: Add /TP/SIG/SMG/BV-08-C test
From: Luiz Augusto von Dentz @ 2013-11-25 14:54 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1385391283-10962-1-git-send-email-luiz.dentz@gmail.com>

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

Verify that the IUT (ACP) reports the reception of a valid query for
remote SEP capabilities and replies the returned capabilities.
---
 unit/test-avdtp.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 46 insertions(+), 2 deletions(-)

diff --git a/unit/test-avdtp.c b/unit/test-avdtp.c
index 81155a4..0b92489 100644
--- a/unit/test-avdtp.c
+++ b/unit/test-avdtp.c
@@ -195,26 +195,64 @@ static void execute_context(struct context *context)
 	g_free(context);
 }
 
+static gboolean sep_getcap_ind(struct avdtp *session,
+					struct avdtp_local_sep *sep,
+					gboolean get_all, GSList **caps,
+					uint8_t *err, void *user_data)
+{
+	struct avdtp_service_capability *media_transport, *media_codec;
+	struct avdtp_media_codec_capability *codec_caps;
+	uint8_t cap[4] = { 0xff, 0xff, 2, 64 };
+
+	*caps = NULL;
+
+	media_transport = avdtp_service_cap_new(AVDTP_MEDIA_TRANSPORT,
+						NULL, 0);
+
+	*caps = g_slist_append(*caps, media_transport);
+
+	codec_caps = g_malloc0(sizeof(*codec_caps) + sizeof(cap));
+	codec_caps->media_type = AVDTP_MEDIA_TYPE_AUDIO;
+	codec_caps->media_codec_type = 0x00;
+	memcpy(codec_caps->data, cap, sizeof(cap));
+
+	media_codec = avdtp_service_cap_new(AVDTP_MEDIA_CODEC, codec_caps,
+					sizeof(*codec_caps) + sizeof(cap));
+
+	*caps = g_slist_append(*caps, media_codec);
+	g_free(codec_caps);
+
+	return TRUE;
+}
+
+static struct avdtp_sep_ind sep_ind = {
+	.get_capability		= sep_getcap_ind,
+};
+
 static void test_server(gconstpointer data)
 {
 	const struct test_data *test = data;
 	struct context *context = create_context(0x0100);
+	struct avdtp_local_sep *sep;
 
 	context->pdu_list = test->pdu_list;
 
-	avdtp_register_sep(AVDTP_SEP_TYPE_SOURCE, AVDTP_MEDIA_TYPE_AUDIO, 0x00,
-							TRUE, NULL, NULL, NULL);
+	sep = avdtp_register_sep(AVDTP_SEP_TYPE_SOURCE, AVDTP_MEDIA_TYPE_AUDIO,
+					0x00, TRUE, &sep_ind, NULL, NULL);
 
 	g_idle_add(send_pdu, context);
 
 	execute_context(context);
 
+	avdtp_unregister_sep(sep);
+
 	g_free(test->pdu_list);
 }
 
 static void discover_cb(struct avdtp *session, GSList *seps,
 				struct avdtp_error *err, void *user_data)
 {
+
 }
 
 static void test_discover(gconstpointer data)
@@ -267,6 +305,12 @@ int main(int argc, char *argv[])
 			raw_pdu(0x10, 0x01),
 			raw_pdu(0x12, 0x01, 0x04, 0x00),
 			raw_pdu(0x20, 0x02, 0x04));
+	define_test("/TP/SIG/SMG/BV-08-C", test_server,
+			raw_pdu(0x00, 0x01),
+			raw_pdu(0x02, 0x01, 0x04, 0x00),
+			raw_pdu(0x10, 0x02, 0x04),
+			raw_pdu(0x12, 0x02, 0x01, 0x00, 0x07, 0x06, 0x00, 0x00,
+				0xff, 0xff, 0x02, 0x40));
 
 	return g_test_run();
 }
-- 
1.8.3.1


^ permalink raw reply related

* [PATCH v2 05/20] unit/AVDTP: Add /TP/SIG/SMG/BV-07-C test
From: Luiz Augusto von Dentz @ 2013-11-25 14:54 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1385391283-10962-1-git-send-email-luiz.dentz@gmail.com>

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

Verify that the IUT (INT) is able to issue a valid query for remote SEP
capabilities and reports the replied ones.
---
 unit/test-avdtp.c | 23 +++++++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/unit/test-avdtp.c b/unit/test-avdtp.c
index 5623153..81155a4 100644
--- a/unit/test-avdtp.c
+++ b/unit/test-avdtp.c
@@ -198,11 +198,12 @@ static void execute_context(struct context *context)
 static void test_server(gconstpointer data)
 {
 	const struct test_data *test = data;
-	struct context *context = create_context();
+	struct context *context = create_context(0x0100);
 
 	context->pdu_list = test->pdu_list;
+
 	avdtp_register_sep(AVDTP_SEP_TYPE_SOURCE, AVDTP_MEDIA_TYPE_AUDIO, 0x00,
-				TRUE, NULL, NULL, NULL);
+							TRUE, NULL, NULL, NULL);
 
 	g_idle_add(send_pdu, context);
 
@@ -230,6 +231,20 @@ static void test_discover(gconstpointer data)
 	g_free(test->pdu_list);
 }
 
+static void test_get_capabilities(gconstpointer data)
+{
+	const struct test_data *test = data;
+	struct context *context = create_context(0x0100);
+
+	context->pdu_list = test->pdu_list;
+
+	avdtp_discover(context->session, discover_cb, NULL);
+
+	execute_context(context);
+
+	g_free(test->pdu_list);
+}
+
 int main(int argc, char *argv[])
 {
 	g_test_init(&argc, &argv, NULL);
@@ -248,6 +263,10 @@ int main(int argc, char *argv[])
 	define_test("/TP/SIG/SMG/BV-06-C", test_server,
 			raw_pdu(0x00, 0x01),
 			raw_pdu(0x02, 0x01, 0x04, 0x00));
+	define_test("/TP/SIG/SMG/BV-07-C", test_get_capabilities,
+			raw_pdu(0x10, 0x01),
+			raw_pdu(0x12, 0x01, 0x04, 0x00),
+			raw_pdu(0x20, 0x02, 0x04));
 
 	return g_test_run();
 }
-- 
1.8.3.1


^ permalink raw reply related

* [PATCH v2 04/20] unit/AVDTP: Add /TP/SIG/SMG/BV-06-C test
From: Luiz Augusto von Dentz @ 2013-11-25 14:54 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1385391283-10962-1-git-send-email-luiz.dentz@gmail.com>

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

Verify that the IUT (ACP) reports the reception of a valid stream
discover command and replies the returned list of SEPs and media types.
---
 unit/test-avdtp.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/unit/test-avdtp.c b/unit/test-avdtp.c
index 2dc9424..5623153 100644
--- a/unit/test-avdtp.c
+++ b/unit/test-avdtp.c
@@ -195,6 +195,22 @@ static void execute_context(struct context *context)
 	g_free(context);
 }
 
+static void test_server(gconstpointer data)
+{
+	const struct test_data *test = data;
+	struct context *context = create_context();
+
+	context->pdu_list = test->pdu_list;
+	avdtp_register_sep(AVDTP_SEP_TYPE_SOURCE, AVDTP_MEDIA_TYPE_AUDIO, 0x00,
+				TRUE, NULL, NULL, NULL);
+
+	g_idle_add(send_pdu, context);
+
+	execute_context(context);
+
+	g_free(test->pdu_list);
+}
+
 static void discover_cb(struct avdtp *session, GSList *seps,
 				struct avdtp_error *err, void *user_data)
 {
@@ -229,6 +245,9 @@ int main(int argc, char *argv[])
 	 */
 	define_test("/TP/SIG/SMG/BV-05-C", test_discover,
 			raw_pdu(0x00, 0x01));
+	define_test("/TP/SIG/SMG/BV-06-C", test_server,
+			raw_pdu(0x00, 0x01),
+			raw_pdu(0x02, 0x01, 0x04, 0x00));
 
 	return g_test_run();
 }
-- 
1.8.3.1


^ permalink raw reply related

* [PATCH v2 03/20] unit/AVDTP: Add /TP/SIG/SMG/BV-05-C test
From: Luiz Augusto von Dentz @ 2013-11-25 14:54 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1385391283-10962-1-git-send-email-luiz.dentz@gmail.com>

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

Verify that the IUT (INT) is able to issue a valid stream discover command
and report the replied SEPs and media types.
---
 Makefile.am       |   8 ++
 unit/test-avdtp.c | 234 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 242 insertions(+)
 create mode 100644 unit/test-avdtp.c

diff --git a/Makefile.am b/Makefile.am
index 328ccdb..2bb2eb5 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -249,6 +249,14 @@ unit_test_sdp_SOURCES = unit/test-sdp.c \
 				src/sdpd-service.c src/sdpd-request.c
 unit_test_sdp_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
 
+unit_tests += unit/test-avdtp
+
+unit_test_avdtp_SOURCES = unit/test-avdtp.c \
+				src/shared/util.h src/shared/util.c \
+				src/log.h src/log.c \
+				android/avdtp.c android/avdtp.h
+unit_test_avdtp_LDADD = @GLIB_LIBS@
+
 unit_tests += unit/test-gdbus-client
 
 unit_test_gdbus_client_SOURCES = unit/test-gdbus-client.c
diff --git a/unit/test-avdtp.c b/unit/test-avdtp.c
new file mode 100644
index 0000000..2dc9424
--- /dev/null
+++ b/unit/test-avdtp.c
@@ -0,0 +1,234 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2012  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 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <inttypes.h>
+#include <string.h>
+#include <sys/socket.h>
+
+#include <glib.h>
+
+#include "src/shared/util.h"
+#include "src/log.h"
+#include "android/avdtp.h"
+
+struct test_pdu {
+	bool valid;
+	const void *data;
+	size_t size;
+};
+
+struct test_data {
+	struct test_pdu *pdu_list;
+};
+
+#define data(args...) ((const unsigned char[]) { args })
+
+#define raw_pdu(args...) \
+	{							\
+		.valid = true,					\
+		.data = data(args),				\
+		.size = sizeof(data(args)),			\
+	}
+
+#define define_test(name, function, args...) \
+	do {								\
+		const struct test_pdu pdus[] = {			\
+			args, { }, { }					\
+		};							\
+		static struct test_data data;				\
+		data.pdu_list = g_malloc(sizeof(pdus));			\
+		memcpy(data.pdu_list, pdus, sizeof(pdus));		\
+		g_test_add_data_func(name, &data, function);		\
+	} while (0)
+
+struct context {
+	GMainLoop *main_loop;
+	struct avdtp *session;
+	guint source;
+	int fd;
+	int mtu;
+	unsigned int pdu_offset;
+	const struct test_pdu *pdu_list;
+};
+
+static void test_debug(const char *str, void *user_data)
+{
+	const char *prefix = user_data;
+
+	g_print("%s%s\n", prefix, str);
+}
+
+static void context_quit(struct context *context)
+{
+	g_main_loop_quit(context->main_loop);
+}
+
+static gboolean send_pdu(gpointer user_data)
+{
+	struct context *context = user_data;
+	const struct test_pdu *pdu;
+	ssize_t len;
+
+	pdu = &context->pdu_list[context->pdu_offset++];
+
+	len = write(context->fd, pdu->data, pdu->size);
+
+	if (g_test_verbose())
+		util_hexdump('<', pdu->data, len, test_debug, "AVDTP: ");
+
+	g_assert(len == (ssize_t) pdu->size);
+
+	return FALSE;
+}
+
+static void context_process(struct context *context)
+{
+	if (!context->pdu_list[context->pdu_offset].valid) {
+		context_quit(context);
+		return;
+	}
+
+	g_idle_add(send_pdu, context);
+}
+
+static gboolean test_handler(GIOChannel *channel, GIOCondition cond,
+							gpointer user_data)
+{
+	struct context *context = user_data;
+	const struct test_pdu *pdu;
+	unsigned char buf[512];
+	ssize_t len;
+	int fd;
+
+	pdu = &context->pdu_list[context->pdu_offset++];
+
+	if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP))
+		return FALSE;
+
+	fd = g_io_channel_unix_get_fd(channel);
+
+	len = read(fd, buf, sizeof(buf));
+
+	g_assert(len > 0);
+
+	if (g_test_verbose())
+		util_hexdump('>', buf, len, test_debug, "AVDTP: ");
+
+	g_assert((size_t) len == pdu->size);
+
+	g_assert(memcmp(buf, pdu->data, pdu->size) == 0);
+
+	context_process(context);
+
+	return TRUE;
+}
+
+static struct context *create_context(uint16_t version)
+{
+	struct context *context = g_new0(struct context, 1);
+	GIOChannel *channel;
+	int err, sv[2];
+
+	context->main_loop = g_main_loop_new(NULL, FALSE);
+	g_assert(context->main_loop);
+
+	err = socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0, sv);
+	g_assert(err == 0);
+
+	context->session = avdtp_new(sv[0], 672, 672, version);
+	g_assert(context->session != NULL);
+
+	channel = g_io_channel_unix_new(sv[1]);
+
+	g_io_channel_set_close_on_unref(channel, TRUE);
+	g_io_channel_set_encoding(channel, NULL, NULL);
+	g_io_channel_set_buffered(channel, FALSE);
+
+	context->source = g_io_add_watch(channel,
+				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+				test_handler, context);
+	g_assert(context->source > 0);
+
+	g_io_channel_unref(channel);
+
+	context->fd = sv[1];
+
+	return context;
+}
+
+static void execute_context(struct context *context)
+{
+	g_main_loop_run(context->main_loop);
+
+	g_source_remove(context->source);
+	avdtp_unref(context->session);
+
+	g_main_loop_unref(context->main_loop);
+
+	g_free(context);
+}
+
+static void discover_cb(struct avdtp *session, GSList *seps,
+				struct avdtp_error *err, void *user_data)
+{
+}
+
+static void test_discover(gconstpointer data)
+{
+	const struct test_data *test = data;
+	struct context *context = create_context(0x0100);
+
+	context->pdu_list = test->pdu_list;
+
+	avdtp_discover(context->session, discover_cb, NULL);
+
+	execute_context(context);
+
+	g_free(test->pdu_list);
+}
+
+int main(int argc, char *argv[])
+{
+	g_test_init(&argc, &argv, NULL);
+
+	if (g_test_verbose())
+		__btd_log_init("*", 0);
+
+	/*
+	 * Stream Management Service
+	 *
+	 * To verify that the following procedures are implemented according to
+	 * their specification in AVDTP.
+	 */
+	define_test("/TP/SIG/SMG/BV-05-C", test_discover,
+			raw_pdu(0x00, 0x01));
+
+	return g_test_run();
+}
-- 
1.8.3.1


^ permalink raw reply related

* [PATCH v2 02/20] android/AVDTP: Strip dependencies
From: Luiz Augusto von Dentz @ 2013-11-25 14:54 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1385391283-10962-1-git-send-email-luiz.dentz@gmail.com>

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

This strips AVDTP code of any dependency of core and btio to make it
transport agnostic.
---
 android/Android.mk  |   1 +
 android/Makefile.am |   1 +
 android/a2dp.c      |  23 ++
 android/avdtp.c     | 757 +++++-----------------------------------------------
 android/avdtp.h     |  28 +-
 5 files changed, 102 insertions(+), 708 deletions(-)

diff --git a/android/Android.mk b/android/Android.mk
index 616a338..c4d722d 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -25,6 +25,7 @@ LOCAL_SRC_FILES := \
 	hidhost.c \
 	socket.c \
 	ipc.c ipc.h \
+	avdtp.c \
 	a2dp.c \
 	pan.c \
 	../src/log.c \
diff --git a/android/Makefile.am b/android/Makefile.am
index 5f6b1a3..94d231f 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -19,6 +19,7 @@ android_bluetoothd_SOURCES = android/main.c \
 				android/bluetooth.h android/bluetooth.c \
 				android/hidhost.h android/hidhost.c \
 				android/ipc.h android/ipc.c \
+				android/avdtp.h android/avdtp.c \
 				android/a2dp.h android/a2dp.c \
 				android/socket.h android/socket.c \
 				android/pan.h android/pan.c \
diff --git a/android/a2dp.c b/android/a2dp.c
index 55a433e..2251001 100644
--- a/android/a2dp.c
+++ b/android/a2dp.c
@@ -43,6 +43,7 @@
 #include "ipc.h"
 #include "utils.h"
 #include "bluetooth.h"
+#include "avdtp.h"
 
 #define L2CAP_PSM_AVDTP 0x19
 #define SVC_HINT_CAPTURING 0x08
@@ -58,6 +59,7 @@ struct a2dp_device {
 	uint8_t		state;
 	GIOChannel	*io;
 	guint		watch;
+	struct avdtp	*session;
 };
 
 static int device_cmp(gconstpointer s, gconstpointer user_data)
@@ -70,6 +72,9 @@ static int device_cmp(gconstpointer s, gconstpointer user_data)
 
 static void a2dp_device_free(struct a2dp_device *dev)
 {
+	if (dev->session)
+		avdtp_unref(dev->session);
+
 	if (dev->watch > 0)
 		g_source_remove(dev->watch);
 
@@ -129,6 +134,9 @@ static void signaling_connect_cb(GIOChannel *chan, GError *err,
 							gpointer user_data)
 {
 	struct a2dp_device *dev = user_data;
+	uint16_t imtu, omtu;
+	GError *gerr = NULL;
+	int fd;
 
 	if (err) {
 		bt_a2dp_notify_state(dev, HAL_A2DP_STATE_DISCONNECTED);
@@ -136,6 +144,21 @@ static void signaling_connect_cb(GIOChannel *chan, GError *err,
 		return;
 	}
 
+	bt_io_get(chan, &gerr,
+			BT_IO_OPT_IMTU, &imtu,
+			BT_IO_OPT_OMTU, &omtu,
+			BT_IO_OPT_INVALID);
+	if (gerr) {
+		bt_a2dp_notify_state(dev, HAL_A2DP_STATE_DISCONNECTED);
+		error("%s", gerr->message);
+		g_error_free(gerr);
+		return;
+	}
+
+	/* FIXME: Add proper version */
+	fd = g_io_channel_unix_get_fd(chan);
+	dev->session = avdtp_new(fd, imtu, omtu, 0x0100);
+
 	dev->watch = g_io_add_watch(dev->io, G_IO_HUP | G_IO_ERR | G_IO_NVAL,
 								watch_cb, dev);
 
diff --git a/android/avdtp.c b/android/avdtp.c
index b7a7d9c..ac08acd 100644
--- a/android/avdtp.c
+++ b/android/avdtp.c
@@ -33,23 +33,14 @@
 #include <errno.h>
 #include <unistd.h>
 #include <assert.h>
-
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/sdp.h>
-#include <bluetooth/sdp_lib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
 
 #include <glib.h>
-#include <btio/btio.h>
 
 #include "log.h"
-
-#include "lib/uuid.h"
-#include "src/adapter.h"
-#include "src/device.h"
-
 #include "avdtp.h"
-#include "sink.h"
-#include "source.h"
 
 #define AVDTP_PSM 25
 
@@ -321,13 +312,6 @@ struct avdtp_remote_sep {
 	struct avdtp_stream *stream;
 };
 
-struct avdtp_server {
-	struct btd_adapter *adapter;
-	GIOChannel *io;
-	GSList *seps;
-	GSList *sessions;
-};
-
 struct avdtp_local_sep {
 	avdtp_state_t state;
 	struct avdtp_stream *stream;
@@ -338,7 +322,6 @@ struct avdtp_local_sep {
 	struct avdtp_sep_ind *ind;
 	struct avdtp_sep_cfm *cfm;
 	void *user_data;
-	struct avdtp_server *server;
 };
 
 struct stream_callback {
@@ -347,13 +330,6 @@ struct stream_callback {
 	unsigned int id;
 };
 
-struct avdtp_state_callback {
-	avdtp_session_state_cb cb;
-	struct btd_device *dev;
-	unsigned int id;
-	void *user_data;
-};
-
 struct discover_callback {
 	unsigned int id;
 	avdtp_discover_cb_t cb;
@@ -390,9 +366,6 @@ struct avdtp {
 	uint16_t version;
 
 	struct avdtp_server *server;
-	struct btd_device *device;
-
-	avdtp_session_state_t state;
 
 	guint auth_id;
 
@@ -417,16 +390,9 @@ struct avdtp {
 
 	struct discover_callback *discover;
 	struct pending_req *req;
-
-	guint dc_timer;
-
-	/* Attempt stream setup instead of disconnecting */
-	gboolean stream_setup;
 };
 
-static GSList *servers = NULL;
-
-static GSList *state_callbacks = NULL;
+static GSList *lseps = NULL;
 
 static int send_request(struct avdtp *session, gboolean priority,
 			struct avdtp_stream *stream, uint8_t signal_id,
@@ -444,18 +410,6 @@ static void avdtp_sep_set_state(struct avdtp *session,
 				struct avdtp_local_sep *sep,
 				avdtp_state_t state);
 
-static struct avdtp_server *find_server(GSList *list, struct btd_adapter *a)
-{
-	for (; list; list = list->next) {
-		struct avdtp_server *server = list->data;
-
-		if (server->adapter == a)
-			return server;
-	}
-
-	return NULL;
-}
-
 static const char *avdtp_statestr(avdtp_state_t state)
 {
 	switch (state) {
@@ -701,24 +655,6 @@ static struct avdtp_remote_sep *find_remote_sep(GSList *seps, uint8_t seid)
 	return NULL;
 }
 
-static void avdtp_set_state(struct avdtp *session,
-					avdtp_session_state_t new_state)
-{
-	GSList *l;
-	avdtp_session_state_t old_state = session->state;
-
-	session->state = new_state;
-
-	for (l = state_callbacks; l != NULL; l = l->next) {
-		struct avdtp_state_callback *cb = l->data;
-
-		if (session->device != cb->dev)
-			continue;
-
-		cb->cb(cb->dev, session, old_state, new_state, cb->user_data);
-	}
-}
-
 static void stream_free(void *data)
 {
 	struct avdtp_stream *stream = data;
@@ -767,47 +703,11 @@ static gboolean transport_cb(GIOChannel *chan, GIOCondition cond,
 	return FALSE;
 }
 
-static int get_send_buffer_size(int sk)
-{
-	int size;
-	socklen_t optlen = sizeof(size);
-
-	if (getsockopt(sk, SOL_SOCKET, SO_SNDBUF, &size, &optlen) < 0) {
-		int err = -errno;
-		error("getsockopt(SO_SNDBUF) failed: %s (%d)", strerror(-err),
-									-err);
-		return err;
-	}
-
-	/*
-	 * Doubled value is returned by getsockopt since kernel uses that
-	 * space for its own purposes (see man 7 socket, bookkeeping overhead
-	 * for SO_SNDBUF).
-	 */
-	return size / 2;
-}
-
-static int set_send_buffer_size(int sk, int size)
-{
-	socklen_t optlen = sizeof(size);
-
-	if (setsockopt(sk, SOL_SOCKET, SO_SNDBUF, &size, optlen) < 0) {
-		int err = -errno;
-		error("setsockopt(SO_SNDBUF) failed: %s (%d)", strerror(-err),
-									-err);
-		return err;
-	}
-
-	return 0;
-}
-
 static void handle_transport_connect(struct avdtp *session, GIOChannel *io,
 					uint16_t imtu, uint16_t omtu)
 {
 	struct avdtp_stream *stream = session->pending_open;
 	struct avdtp_local_sep *sep = stream->lsep;
-	int sk, buf_size, min_buf_size;
-	GError *err = NULL;
 
 	session->pending_open = NULL;
 
@@ -816,15 +716,8 @@ static void handle_transport_connect(struct avdtp *session, GIOChannel *io,
 		stream->timer = 0;
 	}
 
-	if (io == NULL) {
-		if (!stream->open_acp && sep->cfm && sep->cfm->open) {
-			struct avdtp_error err;
-			avdtp_error_init(&err, AVDTP_ERRNO, EIO);
-			sep->cfm->open(session, sep, NULL, &err,
-					sep->user_data);
-		}
+	if (io == NULL)
 		return;
-	}
 
 	if (stream->io == NULL)
 		stream->io = g_io_channel_ref(io);
@@ -832,35 +725,6 @@ static void handle_transport_connect(struct avdtp *session, GIOChannel *io,
 	stream->omtu = omtu;
 	stream->imtu = imtu;
 
-	/* Apply special settings only if local SEP is of type SRC */
-	if (sep->info.type != AVDTP_SEP_TYPE_SOURCE)
-		goto proceed;
-
-	bt_io_set(stream->io, &err, BT_IO_OPT_FLUSHABLE, TRUE,
-							BT_IO_OPT_INVALID);
-	if (err != NULL) {
-		error("Enabling flushable packets failed: %s", err->message);
-		g_error_free(err);
-	} else
-		DBG("Flushable packets enabled");
-
-	sk = g_io_channel_unix_get_fd(stream->io);
-	buf_size = get_send_buffer_size(sk);
-	if (buf_size < 0)
-		goto proceed;
-
-	DBG("sk %d, omtu %d, send buffer size %d", sk, omtu, buf_size);
-	min_buf_size = omtu * 2;
-	if (buf_size < min_buf_size) {
-		DBG("send buffer size to be increassed to %d",
-				min_buf_size);
-		set_send_buffer_size(sk, min_buf_size);
-	}
-
-proceed:
-	if (!stream->open_acp && sep->cfm && sep->cfm->open)
-		sep->cfm->open(session, sep, stream, NULL, sep->user_data);
-
 	avdtp_sep_set_state(session, sep, AVDTP_STATE_OPEN);
 
 	stream->io_id = g_io_add_watch(io, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
@@ -1071,25 +935,6 @@ static void release_stream(struct avdtp_stream *stream, struct avdtp *session)
 	avdtp_sep_set_state(session, sep, AVDTP_STATE_IDLE);
 }
 
-static int avdtp_cancel_authorization(struct avdtp *session)
-{
-	int err;
-
-	if (session->state != AVDTP_SESSION_STATE_CONNECTING)
-		return 0;
-
-	if (session->auth_id == 0)
-		return 0;
-
-	err = btd_cancel_authorization(session->auth_id);
-	if (err < 0)
-		return err;
-
-	session->auth_id = 0;
-
-	return 0;
-}
-
 static void sep_free(gpointer data)
 {
 	struct avdtp_remote_sep *sep = data;
@@ -1098,13 +943,6 @@ static void sep_free(gpointer data)
 	g_free(sep);
 }
 
-static void remove_disconnect_timer(struct avdtp *session)
-{
-	g_source_remove(session->dc_timer);
-	session->dc_timer = 0;
-	session->stream_setup = FALSE;
-}
-
 static void avdtp_free(void *data)
 {
 	struct avdtp *session = data;
@@ -1123,9 +961,6 @@ static void avdtp_free(void *data)
 		session->io_id = 0;
 	}
 
-	if (session->dc_timer)
-		remove_disconnect_timer(session);
-
 	if (session->req)
 		pending_req_free(session->req);
 
@@ -1140,68 +975,19 @@ static void avdtp_free(void *data)
 
 static void connection_lost(struct avdtp *session, int err)
 {
-	struct avdtp_server *server = session->server;
-	char address[18];
-
-	ba2str(device_get_address(session->device), address);
-	DBG("Disconnected from %s", address);
-
-	if (err != EACCES)
-		avdtp_cancel_authorization(session);
+	DBG("Disconnected: %s (%d)", strerror(err), err);
 
 	g_slist_foreach(session->streams, (GFunc) release_stream, session);
 	session->streams = NULL;
 
 	finalize_discovery(session, err);
 
-	avdtp_set_state(session, AVDTP_SESSION_STATE_DISCONNECTED);
-
 	if (session->ref > 0)
 		return;
 
-	server->sessions = g_slist_remove(server->sessions, session);
-	btd_device_unref(session->device);
 	avdtp_free(session);
 }
 
-static gboolean disconnect_timeout(gpointer user_data)
-{
-	struct avdtp *session = user_data;
-	struct btd_service *service;
-	gboolean stream_setup;
-
-	session->dc_timer = 0;
-
-	stream_setup = session->stream_setup;
-	session->stream_setup = FALSE;
-
-	service = btd_device_get_service(session->device, A2DP_SINK_UUID);
-	if (service && stream_setup) {
-		sink_setup_stream(service, session);
-		return FALSE;
-	}
-
-	service = btd_device_get_service(session->device, A2DP_SOURCE_UUID);
-	if (service && stream_setup) {
-		source_setup_stream(service, session);
-		return FALSE;
-	}
-
-	connection_lost(session, ETIMEDOUT);
-
-	return FALSE;
-}
-
-static void set_disconnect_timer(struct avdtp *session)
-{
-	if (session->dc_timer)
-		remove_disconnect_timer(session);
-
-	session->dc_timer = g_timeout_add_seconds(DISCONNECT_TIMEOUT,
-						disconnect_timeout,
-						session);
-}
-
 void avdtp_unref(struct avdtp *session)
 {
 	if (!session)
@@ -1214,24 +1000,25 @@ void avdtp_unref(struct avdtp *session)
 	if (session->ref > 0)
 		return;
 
-	set_disconnect_timer(session);
+	finalize_discovery(session, ECONNABORTED);
+
+	avdtp_free(session);
 }
 
 struct avdtp *avdtp_ref(struct avdtp *session)
 {
 	session->ref++;
+
 	DBG("%p: ref=%d", session, session->ref);
-	if (session->dc_timer)
-		remove_disconnect_timer(session);
+
 	return session;
 }
 
-static struct avdtp_local_sep *find_local_sep_by_seid(struct avdtp_server *server,
-							uint8_t seid)
+static struct avdtp_local_sep *find_local_sep_by_seid(uint8_t seid)
 {
 	GSList *l;
 
-	for (l = server->seps; l != NULL; l = g_slist_next(l)) {
+	for (l = lseps; l != NULL; l = g_slist_next(l)) {
 		struct avdtp_local_sep *sep = l->data;
 
 		if (sep->info.seid == seid)
@@ -1334,7 +1121,7 @@ static gboolean avdtp_discover_cmd(struct avdtp *session, uint8_t transaction,
 	struct seid_info *seps;
 	gboolean ret;
 
-	sep_count = g_slist_length(session->server->seps);
+	sep_count = g_slist_length(lseps);
 
 	if (sep_count == 0) {
 		uint8_t err = AVDTP_NOT_SUPPORTED_COMMAND;
@@ -1346,7 +1133,7 @@ static gboolean avdtp_discover_cmd(struct avdtp *session, uint8_t transaction,
 
 	seps = g_new0(struct seid_info, sep_count);
 
-	for (l = session->server->seps, i = 0; l != NULL; l = l->next, i++) {
+	for (l = lseps, i = 0; l != NULL; l = l->next, i++) {
 		struct avdtp_local_sep *sep = l->data;
 
 		memcpy(&seps[i], &sep->info, sizeof(struct seid_info));
@@ -1376,7 +1163,7 @@ static gboolean avdtp_getcap_cmd(struct avdtp *session, uint8_t transaction,
 		goto failed;
 	}
 
-	sep = find_local_sep_by_seid(session->server, req->acp_seid);
+	sep = find_local_sep_by_seid(req->acp_seid);
 	if (!sep) {
 		err = AVDTP_BAD_ACP_SEID;
 		goto failed;
@@ -1445,7 +1232,6 @@ static gboolean avdtp_setconf_cmd(struct avdtp *session, uint8_t transaction,
 	struct avdtp_local_sep *sep;
 	struct avdtp_stream *stream;
 	uint8_t err, category = 0x00;
-	struct btd_service *service;
 	GSList *l;
 
 	if (size < sizeof(struct setconf_req)) {
@@ -1453,7 +1239,7 @@ static gboolean avdtp_setconf_cmd(struct avdtp *session, uint8_t transaction,
 		return FALSE;
 	}
 
-	sep = find_local_sep_by_seid(session->server, req->acp_seid);
+	sep = find_local_sep_by_seid(req->acp_seid);
 	if (!sep) {
 		err = AVDTP_BAD_ACP_SEID;
 		goto failed;
@@ -1464,37 +1250,6 @@ static gboolean avdtp_setconf_cmd(struct avdtp *session, uint8_t transaction,
 		goto failed;
 	}
 
-	switch (sep->info.type) {
-	case AVDTP_SEP_TYPE_SOURCE:
-		service = btd_device_get_service(session->device,
-							A2DP_SINK_UUID);
-		if (service == NULL) {
-			btd_device_add_uuid(session->device, A2DP_SINK_UUID);
-			service = btd_device_get_service(session->device,
-							A2DP_SINK_UUID);
-			if (service == NULL) {
-				error("Unable to get a audio sink object");
-				err = AVDTP_BAD_STATE;
-				goto failed;
-			}
-		}
-		break;
-	case AVDTP_SEP_TYPE_SINK:
-		service = btd_device_get_service(session->device,
-							A2DP_SOURCE_UUID);
-		if (service == NULL) {
-			btd_device_add_uuid(session->device, A2DP_SOURCE_UUID);
-			service = btd_device_get_service(session->device,
-							A2DP_SOURCE_UUID);
-			if (service == NULL) {
-				error("Unable to get a audio source object");
-				err = AVDTP_BAD_STATE;
-				goto failed;
-			}
-		}
-		break;
-	}
-
 	stream = g_new0(struct avdtp_stream, 1);
 	stream->session = session;
 	stream->lsep = sep;
@@ -1568,7 +1323,7 @@ static gboolean avdtp_getconf_cmd(struct avdtp *session, uint8_t transaction,
 
 	memset(buf, 0, sizeof(buf));
 
-	sep = find_local_sep_by_seid(session->server, req->acp_seid);
+	sep = find_local_sep_by_seid(req->acp_seid);
 	if (!sep) {
 		err = AVDTP_BAD_ACP_SEID;
 		goto failed;
@@ -1684,7 +1439,7 @@ static gboolean avdtp_open_cmd(struct avdtp *session, uint8_t transaction,
 		return FALSE;
 	}
 
-	sep = find_local_sep_by_seid(session->server, req->acp_seid);
+	sep = find_local_sep_by_seid(req->acp_seid);
 	if (!sep) {
 		err = AVDTP_BAD_ACP_SEID;
 		goto failed;
@@ -1744,8 +1499,7 @@ static gboolean avdtp_start_cmd(struct avdtp *session, uint8_t transaction,
 	for (i = 0; i < seid_count; i++, seid++) {
 		failed_seid = seid->seid;
 
-		sep = find_local_sep_by_seid(session->server,
-					req->first_seid.seid);
+		sep = find_local_sep_by_seid(req->first_seid.seid);
 		if (!sep || !sep->stream) {
 			err = AVDTP_BAD_ACP_SEID;
 			goto failed;
@@ -1795,7 +1549,7 @@ static gboolean avdtp_close_cmd(struct avdtp *session, uint8_t transaction,
 		return FALSE;
 	}
 
-	sep = find_local_sep_by_seid(session->server, req->acp_seid);
+	sep = find_local_sep_by_seid(req->acp_seid);
 	if (!sep || !sep->stream) {
 		err = AVDTP_BAD_ACP_SEID;
 		goto failed;
@@ -1856,8 +1610,7 @@ static gboolean avdtp_suspend_cmd(struct avdtp *session, uint8_t transaction,
 	for (i = 0; i < seid_count; i++, seid++) {
 		failed_seid = seid->seid;
 
-		sep = find_local_sep_by_seid(session->server,
-					req->first_seid.seid);
+		sep = find_local_sep_by_seid(req->first_seid.seid);
 		if (!sep || !sep->stream) {
 			err = AVDTP_BAD_ACP_SEID;
 			goto failed;
@@ -1904,7 +1657,7 @@ static gboolean avdtp_abort_cmd(struct avdtp *session, uint8_t transaction,
 		return FALSE;
 	}
 
-	sep = find_local_sep_by_seid(session->server, req->acp_seid);
+	sep = find_local_sep_by_seid(req->acp_seid);
 	if (!sep || !sep->stream)
 		return TRUE;
 
@@ -1942,7 +1695,7 @@ static gboolean avdtp_delayreport_cmd(struct avdtp *session,
 		return FALSE;
 	}
 
-	sep = find_local_sep_by_seid(session->server, req->acp_seid);
+	sep = find_local_sep_by_seid(req->acp_seid);
 	if (!sep || !sep->stream) {
 		err = AVDTP_BAD_ACP_SEID;
 		goto failed;
@@ -2265,281 +2018,30 @@ failed:
 	return FALSE;
 }
 
-static struct avdtp *find_session(GSList *list, struct btd_device *device)
-{
-	for (; list != NULL; list = g_slist_next(list)) {
-		struct avdtp *s = list->data;
-
-		if (s->device == device)
-			return s;
-	}
-
-	return NULL;
-}
-
-static uint16_t get_version(struct avdtp *session)
+struct avdtp *avdtp_new(int fd, size_t imtu, size_t omtu, uint16_t version)
 {
-	const sdp_record_t *rec;
-	sdp_list_t *protos;
-	sdp_data_t *proto_desc;
-	uint16_t ver = 0x0100;
-
-	rec = btd_device_get_record(session->device, A2DP_SINK_UUID);
-	if (!rec)
-		rec = btd_device_get_record(session->device, A2DP_SOURCE_UUID);
-
-	if (!rec)
-		return ver;
-
-	if (sdp_get_access_protos(rec, &protos) < 0)
-		return ver;
-
-	proto_desc = sdp_get_proto_desc(protos, AVDTP_UUID);
-	if (proto_desc && proto_desc->dtd == SDP_UINT16)
-		ver = proto_desc->val.uint16;
-
-	sdp_list_foreach(protos, (sdp_list_func_t) sdp_list_free, NULL);
-	sdp_list_free(protos, NULL);
-
-	return ver;
-}
-
-static struct avdtp *avdtp_get_internal(struct btd_device *device)
-{
-	struct avdtp_server *server;
 	struct avdtp *session;
-
-	server = find_server(servers, device_get_adapter(device));
-	if (server == NULL)
-		return NULL;
-
-	session = find_session(server->sessions, device);
-	if (session)
-		return session;
+	GIOCondition cond = G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
 
 	session = g_new0(struct avdtp, 1);
-
-	session->server = server;
-	session->device = btd_device_ref(device);
-	/* We don't use avdtp_set_state() here since this isn't a state change
-	 * but just setting of the initial state */
-	session->state = AVDTP_SESSION_STATE_DISCONNECTED;
-
-	session->version = get_version(session);
-
-	server->sessions = g_slist_append(server->sessions, session);
-
-	return session;
-}
-
-struct avdtp *avdtp_get(struct btd_device *device)
-{
-	struct avdtp *session;
-
-	session = avdtp_get_internal(device);
-
-	if (!session)
-		return NULL;
-
-	return avdtp_ref(session);
-}
-
-static void avdtp_connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
-{
-	struct avdtp *session = user_data;
-	char address[18];
-	int err_no = EIO;
-
-	if (err) {
-		err_no = err->code;
-		error("%s", err->message);
-		goto failed;
-	}
-
-	if (!session->io)
-		session->io = g_io_channel_ref(chan);
-
-	bt_io_get(chan, &err,
-			BT_IO_OPT_OMTU, &session->omtu,
-			BT_IO_OPT_IMTU, &session->imtu,
-			BT_IO_OPT_INVALID);
-	if (err) {
-		err_no = err->code;
-		error("%s", err->message);
-		goto failed;
-	}
-
-	ba2str(device_get_address(session->device), address);
-	DBG("AVDTP: connected %s channel to %s",
-			session->pending_open ? "transport" : "signaling",
-			address);
-
-	if (session->state == AVDTP_SESSION_STATE_CONNECTING) {
-		DBG("AVDTP imtu=%u, omtu=%u", session->imtu, session->omtu);
-
-		session->buf = g_malloc0(MAX(session->imtu, session->omtu));
-		avdtp_set_state(session, AVDTP_SESSION_STATE_CONNECTED);
-
-		if (session->io_id)
-			g_source_remove(session->io_id);
-
-		/* This watch should be low priority since otherwise the
-		 * connect callback might be dispatched before the session
-		 * callback if the kernel wakes us up at the same time for
-		 * them. This could happen if a headset is very quick in
-		 * sending the Start command after connecting the stream
-		 * transport channel.
-		 */
-		session->io_id = g_io_add_watch_full(chan,
-						G_PRIORITY_LOW,
-						G_IO_IN | G_IO_ERR | G_IO_HUP
-						| G_IO_NVAL,
+	session->io = g_io_channel_unix_new(fd);
+	session->version = version;
+	session->imtu = imtu;
+	session->omtu = omtu;
+	session->buf = g_malloc0(MAX(session->imtu, session->omtu));
+
+	/* This watch should be low priority since otherwise the
+	 * connect callback might be dispatched before the session
+	 * callback if the kernel wakes us up at the same time for
+	 * them. This could happen if a headset is very quick in
+	 * sending the Start command after connecting the stream
+	 * transport channel.
+	 */
+	session->io_id = g_io_add_watch_full(session->io, G_PRIORITY_LOW, cond,
 						(GIOFunc) session_cb, session,
 						NULL);
 
-		if (session->stream_setup)
-			set_disconnect_timer(session);
-	} else if (session->pending_open)
-		handle_transport_connect(session, chan, session->imtu,
-								session->omtu);
-	else
-		goto failed;
-
-	process_queue(session);
-
-	return;
-
-failed:
-	if (session->pending_open) {
-		struct avdtp_stream *stream = session->pending_open;
-
-		handle_transport_connect(session, NULL, 0, 0);
-
-		if (avdtp_abort(session, stream) < 0)
-			avdtp_sep_set_state(session, stream->lsep,
-						AVDTP_STATE_IDLE);
-	} else
-		connection_lost(session, err_no);
-}
-
-static void auth_cb(DBusError *derr, void *user_data)
-{
-	struct avdtp *session = user_data;
-	GError *err = NULL;
-
-	if (derr && dbus_error_is_set(derr)) {
-		error("Access denied: %s", derr->message);
-		connection_lost(session, EACCES);
-		return;
-	}
-
-	if (!bt_io_accept(session->io, avdtp_connect_cb, session, NULL,
-								&err)) {
-		error("bt_io_accept: %s", err->message);
-		connection_lost(session, EACCES);
-		g_error_free(err);
-		return;
-	}
-
-	/* This is so that avdtp_connect_cb will know to do the right thing
-	 * with respect to the disconnect timer */
-	session->stream_setup = TRUE;
-}
-
-static void avdtp_confirm_cb(GIOChannel *chan, gpointer data)
-{
-	struct avdtp *session;
-	char address[18];
-	bdaddr_t src, dst;
-	GError *err = NULL;
-	struct btd_device *device;
-
-	bt_io_get(chan, &err,
-			BT_IO_OPT_SOURCE_BDADDR, &src,
-			BT_IO_OPT_DEST_BDADDR, &dst,
-			BT_IO_OPT_DEST, address,
-			BT_IO_OPT_INVALID);
-	if (err) {
-		error("%s", err->message);
-		g_error_free(err);
-		goto drop;
-	}
-
-	DBG("AVDTP: incoming connect from %s", address);
-
-	device = adapter_find_device(adapter_find(&src), &dst);
-	if (!device)
-		goto drop;
-
-	session = avdtp_get_internal(device);
-	if (!session)
-		goto drop;
-
-	/* This state (ie, session is already *connecting*) happens when the
-	 * device initiates a connect (really a config'd L2CAP channel) even
-	 * though there is a connect we initiated in progress. In sink.c &
-	 * source.c, this state is referred to as XCASE connect:connect.
-	 * Abort the device's channel in favor of our own.
-	 */
-	if (session->state == AVDTP_SESSION_STATE_CONNECTING) {
-		DBG("connect already in progress (XCASE connect:connect)");
-		goto drop;
-	}
-
-	if (session->pending_open && session->pending_open->open_acp) {
-		if (!bt_io_accept(chan, avdtp_connect_cb, session, NULL, NULL))
-			goto drop;
-		return;
-	}
-
-	if (session->io) {
-		error("Refusing unexpected connect from %s", address);
-		goto drop;
-	}
-
-	btd_device_add_uuid(device, ADVANCED_AUDIO_UUID);
-
-	session->io = g_io_channel_ref(chan);
-	avdtp_set_state(session, AVDTP_SESSION_STATE_CONNECTING);
-
-	session->io_id = g_io_add_watch(chan, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
-					(GIOFunc) session_cb, session);
-
-	session->auth_id = btd_request_authorization(&src, &dst,
-							ADVANCED_AUDIO_UUID,
-							auth_cb, session);
-	if (session->auth_id == 0) {
-		avdtp_set_state(session, AVDTP_SESSION_STATE_DISCONNECTED);
-		goto drop;
-	}
-
-	return;
-
-drop:
-	g_io_channel_shutdown(chan, TRUE, NULL);
-}
-
-static GIOChannel *l2cap_connect(struct avdtp *session)
-{
-	GError *err = NULL;
-	GIOChannel *io;
-
-	io = bt_io_connect(avdtp_connect_cb, session,
-				NULL, &err,
-				BT_IO_OPT_SOURCE_BDADDR,
-				adapter_get_address(session->server->adapter),
-				BT_IO_OPT_DEST_BDADDR,
-				device_get_address(session->device),
-				BT_IO_OPT_PSM, AVDTP_PSM,
-				BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
-				BT_IO_OPT_INVALID);
-	if (!io) {
-		error("%s", err->message);
-		g_error_free(err);
-		return NULL;
-	}
-
-	return io;
+	return avdtp_ref(session);
 }
 
 static void queue_request(struct avdtp *session, struct pending_req *req,
@@ -2676,17 +2178,7 @@ static int send_req(struct avdtp *session, gboolean priority,
 	static int transaction = 0;
 	int err;
 
-	if (session->state == AVDTP_SESSION_STATE_DISCONNECTED) {
-		session->io = l2cap_connect(session);
-		if (!session->io) {
-			err = -EIO;
-			goto failed;
-		}
-		avdtp_set_state(session, AVDTP_SESSION_STATE_CONNECTING);
-	}
-
-	if (session->state < AVDTP_SESSION_STATE_CONNECTED ||
-			session->req != NULL) {
+	if (session->req != NULL) {
 		queue_request(session, req, priority);
 		return 0;
 	}
@@ -2859,14 +2351,11 @@ static gboolean avdtp_open_resp(struct avdtp *session, struct avdtp_stream *stre
 {
 	struct avdtp_local_sep *sep = stream->lsep;
 
-	stream->io = l2cap_connect(session);
-	if (!stream->io) {
-		avdtp_sep_set_state(session, sep, AVDTP_STATE_IDLE);
-		return FALSE;
-	}
-
 	session->pending_open = stream;
 
+	if (!stream->open_acp && sep->cfm && sep->cfm->open)
+		sep->cfm->open(session, sep, stream, NULL, sep->user_data);
+
 	return TRUE;
 }
 
@@ -2876,14 +2365,14 @@ static gboolean avdtp_start_resp(struct avdtp *session,
 {
 	struct avdtp_local_sep *sep = stream->lsep;
 
-	if (sep->cfm && sep->cfm->start)
-		sep->cfm->start(session, sep, stream, NULL, sep->user_data);
-
 	/* We might be in STREAMING already if both sides send START_CMD at the
 	 * same time and the one in SNK role doesn't reject it as it should */
 	if (sep->state != AVDTP_STATE_STREAMING)
 		avdtp_sep_set_state(session, sep, AVDTP_STATE_STREAMING);
 
+	if (sep->cfm && sep->cfm->start)
+		sep->cfm->start(session, sep, stream, NULL, sep->user_data);
+
 	return TRUE;
 }
 
@@ -3223,6 +2712,24 @@ struct avdtp_remote_sep *avdtp_stream_get_remote_sep(
 	return NULL;
 }
 
+gboolean avdtp_stream_set_transport(struct avdtp_stream *stream, int fd,
+						size_t imtu, size_t omtu)
+{
+	GIOChannel *io;
+
+	if (stream != stream->session->pending_open)
+		return FALSE;
+
+	io = g_io_channel_unix_new(fd);
+
+	handle_transport_connect(stream->session, io, imtu, omtu);
+
+	g_io_channel_unref(io);
+
+	return TRUE;
+
+}
+
 gboolean avdtp_stream_get_transport(struct avdtp_stream *stream, int *sock,
 					uint16_t *imtu, uint16_t *omtu,
 					GSList **caps)
@@ -3375,9 +2882,6 @@ int avdtp_get_configuration(struct avdtp *session, struct avdtp_stream *stream)
 {
 	struct seid_req req;
 
-	if (session->state < AVDTP_SESSION_STATE_CONNECTED)
-		return -EINVAL;
-
 	memset(&req, 0, sizeof(req));
 	req.acp_seid = stream->rseid;
 
@@ -3410,9 +2914,6 @@ int avdtp_set_configuration(struct avdtp *session,
 	struct avdtp_service_capability *cap;
 	GSList *l;
 
-	if (session->state != AVDTP_SESSION_STATE_CONNECTED)
-		return -ENOTCONN;
-
 	if (!(lsep && rsep))
 		return -EINVAL;
 
@@ -3610,7 +3111,8 @@ int avdtp_abort(struct avdtp *session, struct avdtp_stream *stream)
 	if (stream->lsep->state == AVDTP_STATE_ABORTING)
 		return -EINVAL;
 
-	if (session->req && stream == session->req->stream)
+	if (session->req && session->req->timeout > 0 &&
+						stream == session->req->stream)
 		return cancel_request(session, ECANCELED);
 
 	memset(&req, 0, sizeof(req));
@@ -3649,108 +3151,43 @@ int avdtp_delay_report(struct avdtp *session, struct avdtp_stream *stream,
 							&req, sizeof(req));
 }
 
-static GIOChannel *avdtp_server_socket(const bdaddr_t *src, gboolean master)
-{
-	GError *err = NULL;
-	GIOChannel *io;
-
-	io = bt_io_listen(NULL, avdtp_confirm_cb,
-				NULL, NULL, &err,
-				BT_IO_OPT_SOURCE_BDADDR, src,
-				BT_IO_OPT_PSM, AVDTP_PSM,
-				BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
-				BT_IO_OPT_MASTER, master,
-				BT_IO_OPT_INVALID);
-	if (!io) {
-		error("%s", err->message);
-		g_error_free(err);
-	}
-
-	return io;
-}
-
-static struct avdtp_server *avdtp_server_init(struct btd_adapter *adapter)
-{
-	struct avdtp_server *server;
-
-	server = g_new0(struct avdtp_server, 1);
-
-	server->io = avdtp_server_socket(adapter_get_address(adapter), TRUE);
-	if (!server->io) {
-		g_free(server);
-		return NULL;
-	}
-
-	server->adapter = btd_adapter_ref(adapter);
-
-	servers = g_slist_append(servers, server);
-
-	return server;
-}
-
-struct avdtp_local_sep *avdtp_register_sep(struct btd_adapter *adapter,
-						uint8_t type,
-						uint8_t media_type,
+struct avdtp_local_sep *avdtp_register_sep(uint8_t type, uint8_t media_type,
 						uint8_t codec_type,
 						gboolean delay_reporting,
 						struct avdtp_sep_ind *ind,
 						struct avdtp_sep_cfm *cfm,
 						void *user_data)
 {
-	struct avdtp_server *server;
 	struct avdtp_local_sep *sep;
 
-	server = find_server(servers, adapter);
-	if (!server) {
-		server = avdtp_server_init(adapter);
-		if (!server)
-			return NULL;
-	}
-
-	if (g_slist_length(server->seps) > MAX_SEID)
+	if (g_slist_length(lseps) > MAX_SEID)
 		return NULL;
 
 	sep = g_new0(struct avdtp_local_sep, 1);
 
 	sep->state = AVDTP_STATE_IDLE;
-	sep->info.seid = g_slist_length(server->seps) + 1;
+	sep->info.seid = g_slist_length(lseps) + 1;
 	sep->info.type = type;
 	sep->info.media_type = media_type;
 	sep->codec = codec_type;
 	sep->ind = ind;
 	sep->cfm = cfm;
 	sep->user_data = user_data;
-	sep->server = server;
 	sep->delay_reporting = TRUE;
 
 	DBG("SEP %p registered: type:%d codec:%d seid:%d", sep,
 			sep->info.type, sep->codec, sep->info.seid);
-	server->seps = g_slist_append(server->seps, sep);
+	lseps = g_slist_append(lseps, sep);
 
 	return sep;
 }
 
-static void avdtp_server_destroy(struct avdtp_server *server)
-{
-	g_slist_free_full(server->sessions, avdtp_free);
-
-	servers = g_slist_remove(servers, server);
-
-	g_io_channel_shutdown(server->io, TRUE, NULL);
-	g_io_channel_unref(server->io);
-	btd_adapter_unref(server->adapter);
-	g_free(server);
-}
-
 int avdtp_unregister_sep(struct avdtp_local_sep *sep)
 {
-	struct avdtp_server *server;
-
 	if (!sep)
 		return -EINVAL;
 
-	server = sep->server;
-	server->seps = g_slist_remove(server->seps, sep);
+	lseps = g_slist_remove(lseps, sep);
 
 	if (sep->stream)
 		release_stream(sep->stream, sep->stream->session);
@@ -3760,11 +3197,6 @@ int avdtp_unregister_sep(struct avdtp_local_sep *sep)
 
 	g_free(sep);
 
-	if (server->seps)
-		return 0;
-
-	avdtp_server_destroy(server);
-
 	return 0;
 }
 
@@ -3818,50 +3250,7 @@ avdtp_state_t avdtp_sep_get_state(struct avdtp_local_sep *sep)
 	return sep->state;
 }
 
-struct btd_adapter *avdtp_get_adapter(struct avdtp *session)
-{
-	return session->server->adapter;
-}
-
-struct btd_device *avdtp_get_device(struct avdtp *session)
-{
-	return session->device;
-}
-
 gboolean avdtp_has_stream(struct avdtp *session, struct avdtp_stream *stream)
 {
 	return g_slist_find(session->streams, stream) ? TRUE : FALSE;
 }
-
-unsigned int avdtp_add_state_cb(struct btd_device *dev,
-				avdtp_session_state_cb cb, void *user_data)
-{
-	struct avdtp_state_callback *state_cb;
-	static unsigned int id = 0;
-
-	state_cb = g_new(struct avdtp_state_callback, 1);
-	state_cb->cb = cb;
-	state_cb->dev = dev;
-	state_cb->id = ++id;
-	state_cb->user_data = user_data;
-
-	state_callbacks = g_slist_append(state_callbacks, state_cb);
-
-	return state_cb->id;
-}
-
-gboolean avdtp_remove_state_cb(unsigned int id)
-{
-	GSList *l;
-
-	for (l = state_callbacks; l != NULL; l = l->next) {
-		struct avdtp_state_callback *cb = l->data;
-		if (cb && cb->id == id) {
-			state_callbacks = g_slist_remove(state_callbacks, cb);
-			g_free(cb);
-			return TRUE;
-		}
-	}
-
-	return FALSE;
-}
diff --git a/android/avdtp.h b/android/avdtp.h
index 390c154..9760875 100644
--- a/android/avdtp.h
+++ b/android/avdtp.h
@@ -22,12 +22,6 @@
  *
  */
 
-typedef enum {
-	AVDTP_SESSION_STATE_DISCONNECTED,
-	AVDTP_SESSION_STATE_CONNECTING,
-	AVDTP_SESSION_STATE_CONNECTED
-} avdtp_session_state_t;
-
 struct avdtp;
 struct avdtp_stream;
 struct avdtp_local_sep;
@@ -116,12 +110,6 @@ struct avdtp_media_codec_capability {
 #error "Unknown byte order"
 #endif
 
-typedef void (*avdtp_session_state_cb) (struct btd_device *dev,
-					struct avdtp *session,
-					avdtp_session_state_t old_state,
-					avdtp_session_state_t new_state,
-					void *user_data);
-
 typedef void (*avdtp_stream_state_cb) (struct avdtp_stream *stream,
 					avdtp_state_t old_state,
 					avdtp_state_t new_state,
@@ -213,7 +201,7 @@ struct avdtp_sep_ind {
 typedef void (*avdtp_discover_cb_t) (struct avdtp *session, GSList *seps,
 					struct avdtp_error *err, void *user_data);
 
-struct avdtp *avdtp_get(struct btd_device *device);
+struct avdtp *avdtp_new(int fd, size_t imtu, size_t omtu, uint16_t version);
 
 void avdtp_unref(struct avdtp *session);
 struct avdtp *avdtp_ref(struct avdtp *session);
@@ -235,6 +223,8 @@ gboolean avdtp_stream_remove_cb(struct avdtp *session,
 				struct avdtp_stream *stream,
 				unsigned int id);
 
+gboolean avdtp_stream_set_transport(struct avdtp_stream *stream, int fd,
+						size_t imtu, size_t omtu);
 gboolean avdtp_stream_get_transport(struct avdtp_stream *stream, int *sock,
 					uint16_t *imtu, uint16_t *omtu,
 					GSList **caps);
@@ -245,11 +235,6 @@ gboolean avdtp_stream_has_capabilities(struct avdtp_stream *stream,
 struct avdtp_remote_sep *avdtp_stream_get_remote_sep(
 						struct avdtp_stream *stream);
 
-unsigned int avdtp_add_state_cb(struct btd_device *dev,
-				avdtp_session_state_cb cb, void *user_data);
-
-gboolean avdtp_remove_state_cb(unsigned int id);
-
 int avdtp_set_configuration(struct avdtp *session,
 				struct avdtp_remote_sep *rsep,
 				struct avdtp_local_sep *lsep,
@@ -268,9 +253,7 @@ int avdtp_abort(struct avdtp *session, struct avdtp_stream *stream);
 int avdtp_delay_report(struct avdtp *session, struct avdtp_stream *stream,
 							uint16_t delay);
 
-struct avdtp_local_sep *avdtp_register_sep(struct btd_adapter *adapter,
-						uint8_t type,
-						uint8_t media_type,
+struct avdtp_local_sep *avdtp_register_sep(uint8_t type, uint8_t media_type,
 						uint8_t codec_type,
 						gboolean delay_reporting,
 						struct avdtp_sep_ind *ind,
@@ -290,6 +273,3 @@ const char *avdtp_strerror(struct avdtp_error *err);
 uint8_t avdtp_error_category(struct avdtp_error *err);
 int avdtp_error_error_code(struct avdtp_error *err);
 int avdtp_error_posix_errno(struct avdtp_error *err);
-
-struct btd_adapter *avdtp_get_adapter(struct avdtp *session);
-struct btd_device *avdtp_get_device(struct avdtp *session);
-- 
1.8.3.1


^ permalink raw reply related

* [PATCH v2 00/20] Initial AVDTP for Android
From: Luiz Augusto von Dentz @ 2013-11-25 14:54 UTC (permalink / raw)
  To: linux-bluetooth

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

The code is based on the current implementation available in
profiles/audio/avdtp.{c,h} but it is transport agnostic and does not
contain any external dependency except glib for IO handling.

Both the signaling and the transport connection has to be handled by
the upper layer, that is why it is not modified in place to avoid
breaking current implemention until this work is considered stable.

Two new function are added:

  - avdtp_new: Creates AVDTP session and attach signaling transport
  - avdtp_stream_set_transport: Set stream transport

Both receives a fd as parameter so in future it should be possible to
replace the IO handling.

This set also includes a initial test set based on the current AVDTP
test specification, once merged more tests will be added as well,
then the intent is to make this used by audio plugin.

Note: It is possible to track back to the original code by doing:
git log --follow or git blame -C -C.

v2: Add a separate commit to copy existing AVDTP files

Luiz Augusto von Dentz (20):
  android: Add copy of current AVDTP implemention
  android/AVDTP: Strip dependencies
  unit/AVDTP: Add /TP/SIG/SMG/BV-05-C test
  unit/AVDTP: Add /TP/SIG/SMG/BV-06-C test
  unit/AVDTP: Add /TP/SIG/SMG/BV-07-C test
  unit/AVDTP: Add /TP/SIG/SMG/BV-08-C test
  unit/AVDTP: Add /TP/SIG/SMG/BV-09-C test
  unit/AVDTP: Add /TP/SIG/SMG/BV-10-C test
  unit/AVDTP: Add /TP/SIG/SMG/BV-11-C test
  unit/AVDTP: Add /TP/SIG/SMG/BV-12-C test
  unit/AVDTP: Add /TP/SIG/SMG/BV-15-C test
  unit/AVDTP: Add /TP/SIG/SMG/BV-16-C test
  unit/AVDTP: Add /TP/SIG/SMG/BV-17-C test
  unit/AVDTP: Add /TP/SIG/SMG/BV-18-C test
  unit/AVDTP: Add /TP/SIG/SMG/BV-19-C test
  unit/AVDTP: Add /TP/SIG/SMG/BV-20-C test
  unit/AVDTP: Add /TP/SIG/SMG/BV-21-C test
  unit/AVDTP: Add /TP/SIG/SMG/BV-22-C test
  unit/AVDTP: Add /TP/SIG/SMG/BV-23-C test
  unit/AVDTP: Add /TP/SIG/SMG/BV-24-C test

 Makefile.am         |    8 +
 android/Makefile.am |    1 +
 android/a2dp.c      |   23 +
 android/avdtp.c     | 3256 +++++++++++++++++++++++++++++++++++++++++++++++++++
 android/avdtp.h     |  275 +++++
 unit/test-avdtp.c   |  612 ++++++++++
 6 files changed, 4175 insertions(+)
 create mode 100644 android/avdtp.c
 create mode 100644 android/avdtp.h
 create mode 100644 unit/test-avdtp.c

-- 
1.8.3.1


^ permalink raw reply

* Re: [PATCH 1/4] android: Add CAP_NET_RAW capability
From: Johan Hedberg @ 2013-11-25 14:25 UTC (permalink / raw)
  To: Ravi kumar Veeramally; +Cc: linux-bluetooth
In-Reply-To: <52935B51.403@linux.intel.com>

Hi Ravi,

On Mon, Nov 25, 2013, Ravi kumar Veeramally wrote:
> On 25.11.2013 16:01, Johan Hedberg wrote:
> >Hi Ravi,
> >
> >On Mon, Nov 25, 2013, Ravi kumar Veeramally wrote:
> >>CAP_NET_RAW capability is required to up the bnep interfaces
> >>in android environment.
> >>---
> >>  android/main.c | 1 +
> >>  1 file changed, 1 insertion(+)
> >>
> >>diff --git a/android/main.c b/android/main.c
> >>index c9733f3..bfd2a87 100644
> >>--- a/android/main.c
> >>+++ b/android/main.c
> >>@@ -506,6 +506,7 @@ static bool set_capabilities(void)
> >>  	header.pid = 0;
> >>  	cap.effective = cap.permitted =
> >>+		CAP_TO_MASK(CAP_NET_RAW) |
> >>  		CAP_TO_MASK(CAP_NET_ADMIN) |
> >>  		CAP_TO_MASK(CAP_NET_BIND_SERVICE);
> >>  	cap.inheritable = 0;
> >Would you then say that commit 9bda7e8c2130de9a3340ebd0e6cc1dedc2eae338
> >is incorrect? A quick grep doesn't show any instances of checking this
> >capability in the BNEP code of the kernel. Exactly which system call is
> >it that needs it?
>    bnep_if_up from profiles/network/common.c
>  ---
>         ifr.ifr_flags |= IFF_UP;
>         ifr.ifr_flags |= IFF_MULTICAST;
> 
>         err = ioctl(sk, SIOCSIFFLAGS, (caddr_t) &ifr);
> ---
>  requires this capability in android environment only.
>  this code is under android macro.

So you've verified that under "normal" Linux this ioctl does not require
the NET_RAW capability?

> >If you answered positively to my first question, please send a patch for
> >that as well.
>  I didn't understand this, sorry.

My first question was: "Would you then say that
commit 9bda7e8c2130de9a3340ebd0e6cc1dedc2eae338 is incorrect?". Do you
not understand that question or what I asked you to do in case the
answer is "yes"?

Johan

^ permalink raw reply

* Re: [PATCH 1/4] android: Add CAP_NET_RAW capability
From: Ravi kumar Veeramally @ 2013-11-25 14:14 UTC (permalink / raw)
  To: linux-bluetooth, johan.hedberg
In-Reply-To: <20131125140154.GA24659@x220.p-661hnu-f1>

Hi Johan,

On 25.11.2013 16:01, Johan Hedberg wrote:
> Hi Ravi,
>
> On Mon, Nov 25, 2013, Ravi kumar Veeramally wrote:
>> CAP_NET_RAW capability is required to up the bnep interfaces
>> in android environment.
>> ---
>>   android/main.c | 1 +
>>   1 file changed, 1 insertion(+)
>>
>> diff --git a/android/main.c b/android/main.c
>> index c9733f3..bfd2a87 100644
>> --- a/android/main.c
>> +++ b/android/main.c
>> @@ -506,6 +506,7 @@ static bool set_capabilities(void)
>>   	header.pid = 0;
>>   
>>   	cap.effective = cap.permitted =
>> +		CAP_TO_MASK(CAP_NET_RAW) |
>>   		CAP_TO_MASK(CAP_NET_ADMIN) |
>>   		CAP_TO_MASK(CAP_NET_BIND_SERVICE);
>>   	cap.inheritable = 0;
> Would you then say that commit 9bda7e8c2130de9a3340ebd0e6cc1dedc2eae338
> is incorrect? A quick grep doesn't show any instances of checking this
> capability in the BNEP code of the kernel. Exactly which system call is
> it that needs it?
    bnep_if_up from profiles/network/common.c
  ---
         ifr.ifr_flags |= IFF_UP;
         ifr.ifr_flags |= IFF_MULTICAST;

         err = ioctl(sk, SIOCSIFFLAGS, (caddr_t) &ifr);
---
  requires this capability in android environment only.
  this code is under android macro.
> If you answered positively to my first question, please send a patch for
> that as well.
  I didn't understand this, sorry.

  Thanks,
  Ravi.

^ permalink raw reply

* [PATCHv10 4/4] android/socket: Check create_rfsock returns valid structure
From: Andrei Emeltchenko @ 2013-11-25 14:10 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1385388625-3156-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

---
 android/socket.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/android/socket.c b/android/socket.c
index 0817b5c..66b240d 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -647,6 +647,12 @@ static void accept_cb(GIOChannel *io, GError *err, gpointer user_data)
 
 	sock_acc = g_io_channel_unix_get_fd(io);
 	rfsock_acc = create_rfsock(sock_acc, &hal_fd);
+	if (!rfsock_acc) {
+		g_io_channel_shutdown(io, TRUE, NULL);
+		g_io_channel_unref(io);
+		return;
+	}
+
 	connections = g_list_append(connections, rfsock_acc);
 
 	DBG("rfsock: fd %d real_sock %d chan %u sock %d",
@@ -905,8 +911,11 @@ static int handle_connect(void *buf)
 
 	DBG("");
 
-	android2bdaddr(cmd->bdaddr, &dst);
 	rfsock = create_rfsock(-1, &hal_fd);
+	if (!rfsock)
+		return -1;
+
+	android2bdaddr(cmd->bdaddr, &dst);
 	bacpy(&rfsock->dst, &dst);
 
 	memset(&uuid, 0, sizeof(uuid));
-- 
1.8.3.2


^ permalink raw reply related

* [PATCHv10 3/4] android/socket: Handle Android events for server socket
From: Andrei Emeltchenko @ 2013-11-25 14:10 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1385388625-3156-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Add watch for tracking events from Android framework for server socket.
---
 android/socket.c | 27 ++++++++++++++++++++++++++-
 1 file changed, 26 insertions(+), 1 deletion(-)

diff --git a/android/socket.c b/android/socket.c
index 447e0f1..0817b5c 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -596,6 +596,24 @@ static bool sock_send_accept(struct rfcomm_sock *rfsock, bdaddr_t *bdaddr,
 	return true;
 }
 
+static gboolean sock_server_stack_event_cb(GIOChannel *io, GIOCondition cond,
+								gpointer data)
+{
+	struct rfcomm_sock *rfsock = data;
+
+	DBG("");
+
+	if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
+		error("Socket error: sock %d cond %d",
+					g_io_channel_unix_get_fd(io), cond);
+		cleanup_rfsock(rfsock);
+
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
 static void accept_cb(GIOChannel *io, GError *err, gpointer user_data)
 {
 	struct rfcomm_sock *rfsock = user_data;
@@ -665,7 +683,8 @@ static int handle_listen(void *buf)
 	struct profile_info *profile;
 	struct rfcomm_sock *rfsock;
 	BtIOSecLevel sec_level;
-	GIOChannel *io;
+	GIOChannel *io, *io_stack;
+	GIOCondition cond;
 	GError *err = NULL;
 	int hal_fd;
 	int chan;
@@ -708,6 +727,12 @@ static int handle_listen(void *buf)
 
 	rfsock->srv_io = io;
 
+	/* Handle events from Android */
+	cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
+	io_stack = g_io_channel_unix_new(rfsock->fd);
+	g_io_add_watch(io_stack, cond, sock_server_stack_event_cb, rfsock);
+	g_io_channel_unref(io_stack);
+
 	DBG("real_sock %d fd %d hal_fd %d", rfsock->real_sock, rfsock->fd,
 								hal_fd);
 
-- 
1.8.3.2


^ permalink raw reply related

* [PATCHv10 2/4] android/socket: Keep server iochannel reference
From: Andrei Emeltchenko @ 2013-11-25 14:10 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1385388625-3156-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

server io channel reference will be stored in rfsock structure
and might be deleted when Android end closes connection or when
HAL makes cleanup() call.
---
 android/socket.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/android/socket.c b/android/socket.c
index e31e391..447e0f1 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -70,6 +70,8 @@ struct rfcomm_sock {
 	guint rfcomm_watch;
 	guint stack_watch;
 
+	GIOChannel *srv_io;
+
 	bdaddr_t dst;
 	uint32_t service_handle;
 
@@ -121,6 +123,11 @@ static void cleanup_rfsock(struct rfcomm_sock *rfsock)
 	if (rfsock->service_handle)
 		bt_adapter_remove_record(rfsock->service_handle);
 
+	if (rfsock->srv_io) {
+		g_io_channel_shutdown(rfsock->srv_io, TRUE, NULL);
+		g_io_channel_unref(rfsock->srv_io);
+	}
+
 	g_free(rfsock);
 }
 
@@ -699,9 +706,7 @@ static int handle_listen(void *buf)
 	rfsock->real_sock = g_io_channel_unix_get_fd(io);
 	servers = g_list_append(servers, rfsock);
 
-	/* TODO: Add server watch */
-	g_io_channel_set_close_on_unref(io, TRUE);
-	g_io_channel_unref(io);
+	rfsock->srv_io = io;
 
 	DBG("real_sock %d fd %d hal_fd %d", rfsock->real_sock, rfsock->fd,
 								hal_fd);
-- 
1.8.3.2


^ permalink raw reply related

* [PATCHv10 1/4] android/socket: Use security level for connect / listen
From: Andrei Emeltchenko @ 2013-11-25 14:10 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <20131125134005.GB19445@x220.p-661hnu-f1>

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Use MEDIUM security level for connections without profile and default
sec_level for others. rfsock now has pointer to profile info.
---
 android/socket.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/android/socket.c b/android/socket.c
index 83e6996..e31e391 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -60,6 +60,8 @@ GList *servers = NULL;
 /* Simple list of RFCOMM connected sockets */
 GList *connections = NULL;
 
+struct profile_info;
+
 struct rfcomm_sock {
 	int fd;		/* descriptor for communication with Java framework */
 	int real_sock;	/* real RFCOMM socket */
@@ -70,6 +72,8 @@ struct rfcomm_sock {
 
 	bdaddr_t dst;
 	uint32_t service_handle;
+
+	struct profile_info *profile;
 };
 
 static struct rfcomm_sock *create_rfsock(int sock, int *hal_fd)
@@ -667,7 +671,7 @@ static int handle_listen(void *buf)
 			return -1;
 		else {
 			chan = cmd->channel;
-			sec_level = BT_IO_SEC_LOW;
+			sec_level = BT_IO_SEC_MEDIUM;
 		}
 	} else {
 		chan = profile->channel;
@@ -786,6 +790,7 @@ fail:
 static void sdp_search_cb(sdp_list_t *recs, int err, gpointer data)
 {
 	struct rfcomm_sock *rfsock = data;
+	BtIOSecLevel sec_level = BT_IO_SEC_MEDIUM;
 	GError *gerr = NULL;
 	sdp_list_t *list;
 	GIOChannel *io;
@@ -829,11 +834,14 @@ static void sdp_search_cb(sdp_list_t *recs, int err, gpointer data)
 
 	DBG("Got RFCOMM channel %d", chan);
 
+	if (rfsock->profile)
+		sec_level = rfsock->profile->sec_level;
+
 	io = bt_io_connect(connect_cb, rfsock, NULL, &gerr,
 				BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
 				BT_IO_OPT_DEST_BDADDR, &rfsock->dst,
 				BT_IO_OPT_CHANNEL, chan,
-				BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
+				BT_IO_OPT_SEC_LEVEL, sec_level,
 				BT_IO_OPT_INVALID);
 	if (!io) {
 		error("Failed connect: %s", gerr->message);
@@ -875,6 +883,8 @@ static int handle_connect(void *buf)
 	uuid.type = SDP_UUID128;
 	memcpy(&uuid.value.uuid128, cmd->uuid, sizeof(uint128_t));
 
+	rfsock->profile = get_profile_by_uuid(cmd->uuid);
+
 	if (bt_search_service(&adapter_addr, &dst, &uuid, sdp_search_cb, rfsock,
 								NULL) < 0) {
 		error("Failed to search SDP records");
-- 
1.8.3.2


^ permalink raw reply related

* Re: [PATCH 1/4] android: Add CAP_NET_RAW capability
From: Johan Hedberg @ 2013-11-25 14:01 UTC (permalink / raw)
  To: Ravi kumar Veeramally; +Cc: linux-bluetooth
In-Reply-To: <1385387369-3015-2-git-send-email-ravikumar.veeramally@linux.intel.com>

Hi Ravi,

On Mon, Nov 25, 2013, Ravi kumar Veeramally wrote:
> CAP_NET_RAW capability is required to up the bnep interfaces
> in android environment.
> ---
>  android/main.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/android/main.c b/android/main.c
> index c9733f3..bfd2a87 100644
> --- a/android/main.c
> +++ b/android/main.c
> @@ -506,6 +506,7 @@ static bool set_capabilities(void)
>  	header.pid = 0;
>  
>  	cap.effective = cap.permitted =
> +		CAP_TO_MASK(CAP_NET_RAW) |
>  		CAP_TO_MASK(CAP_NET_ADMIN) |
>  		CAP_TO_MASK(CAP_NET_BIND_SERVICE);
>  	cap.inheritable = 0;

Would you then say that commit 9bda7e8c2130de9a3340ebd0e6cc1dedc2eae338
is incorrect? A quick grep doesn't show any instances of checking this
capability in the BNEP code of the kernel. Exactly which system call is
it that needs it?

If you answered positively to my first question, please send a patch for
that as well.

Johan

^ permalink raw reply


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