Linux bluetooth development
 help / color / mirror / Atom feed
* Re: [PATCH v2 00/11] Audio HAL implementation
From: Luiz Augusto von Dentz @ 2014-01-16 14:13 UTC (permalink / raw)
  To: Andrzej Kaczmarek; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <1389809037-11575-1-git-send-email-andrzej.kaczmarek@tieto.com>

Hi Andrzej,

On Wed, Jan 15, 2014 at 8:03 PM, Andrzej Kaczmarek
<andrzej.kaczmarek@tieto.com> wrote:
> Hi,
>
> changes v1 -> v2
> - fixed comments from Luiz
> - removed "codec_" prefix from function related to SBC codec
> - additional patch to implement set_parameters for audio device
>   (A2dpSuspend is initialized this way)
> - changes dummy buffer size to 20*512 which is inline with Bluedroid
>   (AudioFlinger does crash when closing output stream when set to 512)
>
>
> Andrzej Kaczmarek (10):
>   android/hal-audio: Add support to register audio endpoints
>   android/hal-audio: Add support to unregister audio endpoints
>   android/hal-audio: Add support to open output stream
>   android/hal-audio: Add support to close output stream
>   android/hal-audio: Add support to resume output stream
>   android/hal-audio: Add support to suspend output stream
>   android/hal-audio: Handle audio preset from stream
>   android/hal-audio: Fix module loading
>   android/hal-audio: Fix AudioFlinger crash
>   android/hal-audio: Implement set_parameters for device
>
> Lukasz Rymanowski (1):
>   android/hal-audio: Add audio_ipc_cmd
>
>  android/Makefile.am |   1 +
>  android/hal-audio.c | 729 +++++++++++++++++++++++++++++++++++++++++++++++++---
>  2 files changed, 696 insertions(+), 34 deletions(-)
>
> --
> 1.8.5.2

Pushed, thanks.

-- 
Luiz Augusto von Dentz

^ permalink raw reply

* Re: [PATCH v2] android/bluetooth: Fix discovering new devices
From: Johan Hedberg @ 2014-01-16 13:50 UTC (permalink / raw)
  To: Szymon Janc; +Cc: linux-bluetooth
In-Reply-To: <1389879325-21217-1-git-send-email-szymon.janc@tieto.com>

Hi Szymon,

On Thu, Jan 16, 2014, Szymon Janc wrote:
> @@ -983,12 +994,15 @@ static void update_found_device(const bdaddr_t *bdaddr, uint8_t bdaddr_type,
>  	eir_parse(&eir, data, data_len);
>  
>  	dev = find_device(bdaddr);
> -	if (!dev) {
> +	if (!dev || !dev->found) {

I think this would still deserve a code comment here explaining why
dev->found is important. Other than that the patch is fine, so feel free
to push it yourself once you've added the comment.

Johan

^ permalink raw reply

* [PATCH v2] android/bluetooth: Fix discovering new devices
From: Szymon Janc @ 2014-01-16 13:35 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

Device found events should be send also for known devices if this is
new discovery session. Otherwise Android will ignore those devices.
---
V2: report bonded devices in same way as non-bonded


 android/bluetooth.c | 22 ++++++++++++++++++----
 1 file changed, 18 insertions(+), 4 deletions(-)

diff --git a/android/bluetooth.c b/android/bluetooth.c
index f1e5458..b235cbd 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -90,6 +90,8 @@ struct device {
 	uint32_t timestamp;
 
 	GSList *uuids;
+
+	bool found; /* if device is found in current discovery session */
 };
 
 struct browse_req {
@@ -903,6 +905,13 @@ static void user_passkey_notify_callback(uint16_t index, uint16_t length,
 	send_ssp_request(&ev->addr.bdaddr, HAL_SSP_VARIANT_NOTIF, ev->passkey);
 }
 
+static void clear_device_found(gpointer data, gpointer user_data)
+{
+	struct device *dev = data;
+
+	dev->found = false;
+}
+
 static void mgmt_discovering_event(uint16_t index, uint16_t length,
 					const void *param, void *user_data)
 {
@@ -924,10 +933,12 @@ static void mgmt_discovering_event(uint16_t index, uint16_t length,
 
 	DBG("new discovering state %u", ev->discovering);
 
-	if (adapter.discovering)
+	if (adapter.discovering) {
 		cp.state = HAL_DISCOVERY_STATE_STARTED;
-	else
+	} else {
+		g_slist_foreach(devices, clear_device_found, NULL);
 		cp.state = HAL_DISCOVERY_STATE_STOPPED;
+	}
 
 	ipc_send_notif(HAL_SERVICE_ID_BLUETOOTH,
 			HAL_EV_DISCOVERY_STATE_CHANGED, sizeof(cp), &cp);
@@ -983,12 +994,15 @@ static void update_found_device(const bdaddr_t *bdaddr, uint8_t bdaddr_type,
 	eir_parse(&eir, data, data_len);
 
 	dev = find_device(bdaddr);
-	if (!dev) {
+	if (!dev || !dev->found) {
 		struct hal_ev_device_found *ev = (void *) buf;
 		bdaddr_t android_bdaddr;
 		uint8_t android_type;
 
-		dev = create_device(bdaddr, bdaddr_type);
+		if (!dev)
+			dev = create_device(bdaddr, bdaddr_type);
+
+		dev->found = true;
 
 		size += sizeof(*ev);
 
-- 
1.8.3.2


^ permalink raw reply related

* Re: [PATCHv3 08/19] emulator/bthost: Add rfcomm_mcc_recv stub
From: Johan Hedberg @ 2014-01-16 12:04 UTC (permalink / raw)
  To: Marcin Kraglak; +Cc: linux-bluetooth
In-Reply-To: <1389345509-27206-9-git-send-email-marcin.kraglak@tieto.com>

Hi Marcin,

On Fri, Jan 10, 2014, Marcin Kraglak wrote:
> It will handle mcc frames in bthost.
> ---
>  emulator/bthost.c | 19 +++++++++++++++++++
>  1 file changed, 19 insertions(+)

All patches are pushed with lots of cleanups on top.

This one I couldn't quite understand.

> diff --git a/emulator/bthost.c b/emulator/bthost.c
> index 242ce19..591aae9 100644
> --- a/emulator/bthost.c
> +++ b/emulator/bthost.c
> @@ -1387,10 +1387,29 @@ static void rfcomm_dm_recv(struct bthost *bthost, struct btconn *conn,
>  {
>  }
>  
> +static void rfcomm_mcc_recv(struct bthost *bthost, struct btconn *conn,
> +			struct l2conn *l2conn, const void *data, uint16_t len)
> +{
> +}
> +
>  static void rfcomm_uih_recv(struct bthost *bthost, struct btconn *conn,
>  				struct l2conn *l2conn, const void *data,
>  				uint16_t len)
>  {
> +	const struct rfcomm_cmd *hdr = data;
> +	const void *p;
> +	uint8_t ea;
> +
> +	ea = RFCOMM_TEST_EA(hdr->length) ? true : false;
> +
> +	if (!RFCOMM_GET_DLCI(hdr->address)) {
> +		if (ea)
> +			p = data + sizeof(struct rfcomm_hdr);
> +		else
> +			p = data + sizeof(struct rfcomm_hdr) + sizeof(uint8_t);
> +
> +		rfcomm_mcc_recv(bthost, conn, l2conn, p, p - data);
> +	}

(first of all, the above got already cleaned up to a slightly simpler
form upstream)

This "p - data" seems to be the length of data that rfcomm mcc_recv
should consume starting at p, right? In that case "p - data" will become
sizeof(struct rfcomm_hdr) or sizeof(struct rfcomm_hdr) +
sizeof(uint8_t), i.e. not the amount of data after p but the amount of
data before p! I.e. shouldn't you be subtracting these amounts from len
instead to get what you need to pass to rfcomm_mcc_recv?

In general, I think you'd be better off with not doing this kind of
pointer arithmetic to begin with (as it already lead to this bug).
Instead just use clear "len" variables for tracking the amount of data
behind some pointer. Also, you seem to be missing lots of checks for
such length variables in the code before accessing the data behind the
pointer. Please fix that too (the only reason why your code was working
is that rfcomm_mcc_recv never checks the length variable).

Johan

^ permalink raw reply

* Re: [PATCH] android/bluetooth: Fix discovering new devices
From: Szymon Janc @ 2014-01-16 10:22 UTC (permalink / raw)
  To: Johan Hedberg; +Cc: linux-bluetooth
In-Reply-To: <20140114113920.GD4709@x220.p-661hnu-f1>

Hi Johan,

On Tuesday 14 of January 2014 13:39:20 Johan Hedberg wrote:
> Hi Szymon,
> 
> On Tue, Jan 14, 2014, Szymon Janc wrote:
> > +	} else {
> > +		GSList *l;
> > +
> > +		for(l = devices; l; l = g_slist_next(l)) {
> 
> Coding style thing here (space after 'for'). You might wanna consider a
> helper function and g_slist_foreach here tough.
> 
> > +static bool device_found_needed(struct device *dev)
> > +{
> > +	if (!dev)
> > +		return true;
> > +
> > +	if (dev->bond_state == HAL_BOND_STATE_BONDED)
> > +		return false;
> > +
> > +	return !dev->found;
> > +}
> 
> I think you should provide lots more code comments here with proper
> explanations of each if-statement. E.g. your commit message doesn't
> mention anything about bonded devices and yet you have a check for this
> state here.

Now I think this check is not really needed, if paired remote is responding to
inquiry then just notify HAL as with any other device found.

I'll send V2 shortly.


-- 
Best regards, 
Szymon Janc

^ permalink raw reply

* [PATCHv3 5/5] android/unit: Add /android_ipc/send_cmd_3 test case
From: Marcin Kraglak @ 2014-01-16 10:05 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389866702-30697-1-git-send-email-marcin.kraglak@tieto.com>

This case will register service, next unregister it and send
command. Expected status is raise SIGTERM.
---
 android/test-ipc.c | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/android/test-ipc.c b/android/test-ipc.c
index 930f9f4..1fde61b 100644
--- a/android/test-ipc.c
+++ b/android/test-ipc.c
@@ -306,6 +306,16 @@ static gboolean register_service(gpointer user_data)
 	return FALSE;
 }
 
+static gboolean unregister_service(gpointer user_data)
+{
+	struct context *context = user_data;
+	const struct test_data *test_data = context->data;
+
+	ipc_unregister(test_data->service);
+
+	return FALSE;
+}
+
 static void test_cmd(gconstpointer data)
 {
 	struct context *context = create_context(data);
@@ -336,6 +346,21 @@ static void test_cmd_reg(gconstpointer data)
 	ipc_cleanup();
 }
 
+static void test_cmd_reg_1(gconstpointer data)
+{
+	struct context *context = create_context(data);
+
+	ipc_init();
+
+	g_idle_add(register_service, context);
+	g_idle_add(unregister_service, context);
+	g_idle_add(send_cmd, context);
+
+	execute_context(context);
+
+	ipc_cleanup();
+}
+
 static void test_cmd_handler(const void *buf, uint16_t len)
 {
 	ipc_send_rsp(0, 1, 0);
@@ -367,6 +392,15 @@ static const struct test_data test_cmd_2 = {
 	.handlers_size = 1
 };
 
+static const struct test_data test_cmd_3 = {
+	.cmd = &test_cmd_1_hdr,
+	.cmd_size = sizeof(test_cmd_1_hdr),
+	.service = 0,
+	.handlers = cmd_handlers,
+	.handlers_size = 1,
+	.expected_signal = SIGTERM
+};
+
 int main(int argc, char *argv[])
 {
 	g_test_init(&argc, &argv, NULL);
@@ -378,6 +412,8 @@ int main(int argc, char *argv[])
 	g_test_add_data_func("/android_ipc/send_cmd_1", &test_cmd_1, test_cmd);
 	g_test_add_data_func("/android_ipc/send_cmd_2", &test_cmd_2,
 							test_cmd_reg);
+	g_test_add_data_func("/android_ipc/send_cmd_3", &test_cmd_3,
+							test_cmd_reg_1);
 
 	return g_test_run();
 }
-- 
1.8.3.1


^ permalink raw reply related

* [PATCHv3 4/5] android/unit: Add /android_ipc/send_cmd_2 test case
From: Marcin Kraglak @ 2014-01-16 10:05 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389866702-30697-1-git-send-email-marcin.kraglak@tieto.com>

This will test sending command to previously registered service.
---
 android/test-ipc.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 62 insertions(+)

diff --git a/android/test-ipc.c b/android/test-ipc.c
index 99f8559..930f9f4 100644
--- a/android/test-ipc.c
+++ b/android/test-ipc.c
@@ -46,6 +46,9 @@ struct test_data {
 	uint32_t expected_signal;
 	const struct hal_hdr *cmd;
 	uint16_t cmd_size;
+	uint8_t service;
+	const struct ipc_handler *handlers;
+	uint8_t handlers_size;
 };
 
 struct context {
@@ -74,11 +77,23 @@ static void context_quit(struct context *context)
 static gboolean cmd_watch(GIOChannel *io, GIOCondition cond,
 						gpointer user_data)
 {
+	struct context *context = user_data;
+	const struct test_data *test_data = context->data;
+	uint8_t buf[128];
+	int sk;
+
 	if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
 		g_assert(FALSE);
 		return FALSE;
 	}
 
+	sk = g_io_channel_unix_get_fd(io);
+
+	g_assert(read(sk, buf, sizeof(buf)) == test_data->cmd_size);
+	g_assert(!memcmp(test_data->cmd, buf, test_data->cmd_size));
+
+	context_quit(context);
+
 	return TRUE;
 }
 
@@ -280,6 +295,17 @@ static gboolean send_cmd(gpointer user_data)
 	return FALSE;
 }
 
+static gboolean register_service(gpointer user_data)
+{
+	struct context *context = user_data;
+	const struct test_data *test_data = context->data;
+
+	ipc_register(test_data->service, test_data->handlers,
+						test_data->handlers_size);
+
+	return FALSE;
+}
+
 static void test_cmd(gconstpointer data)
 {
 	struct context *context = create_context(data);
@@ -293,6 +319,28 @@ static void test_cmd(gconstpointer data)
 	ipc_cleanup();
 }
 
+static void test_cmd_reg(gconstpointer data)
+{
+	struct context *context = create_context(data);
+	const struct test_data *test_data = context->data;
+
+	ipc_init();
+
+	g_idle_add(register_service, context);
+	g_idle_add(send_cmd, context);
+
+	execute_context(context);
+
+	ipc_unregister(test_data->service);
+
+	ipc_cleanup();
+}
+
+static void test_cmd_handler(const void *buf, uint16_t len)
+{
+	ipc_send_rsp(0, 1, 0);
+}
+
 static const struct test_data test_init_1 = {};
 
 static const struct hal_hdr test_cmd_1_hdr = {
@@ -307,6 +355,18 @@ static const struct test_data test_cmd_1 = {
 	.expected_signal = SIGTERM
 };
 
+static const struct ipc_handler cmd_handlers[] = {
+	{ test_cmd_handler, false, 0 }
+};
+
+static const struct test_data test_cmd_2 = {
+	.cmd = &test_cmd_1_hdr,
+	.cmd_size = sizeof(test_cmd_1_hdr),
+	.service = 0,
+	.handlers = cmd_handlers,
+	.handlers_size = 1
+};
+
 int main(int argc, char *argv[])
 {
 	g_test_init(&argc, &argv, NULL);
@@ -316,6 +376,8 @@ int main(int argc, char *argv[])
 
 	g_test_add_data_func("/android_ipc/init", &test_init_1, test_init);
 	g_test_add_data_func("/android_ipc/send_cmd_1", &test_cmd_1, test_cmd);
+	g_test_add_data_func("/android_ipc/send_cmd_2", &test_cmd_2,
+							test_cmd_reg);
 
 	return g_test_run();
 }
-- 
1.8.3.1


^ permalink raw reply related

* [PATCHv3 3/5] android/unit: Add /android_ipc/send_cmd_1 test case
From: Marcin Kraglak @ 2014-01-16 10:05 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389866702-30697-1-git-send-email-marcin.kraglak@tieto.com>

This test case will check if ipc lib will raise SIGTERM
after sending command to not registered service.
---
 android/test-ipc.c | 46 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 45 insertions(+), 1 deletion(-)

diff --git a/android/test-ipc.c b/android/test-ipc.c
index 6ac1175..99f8559 100644
--- a/android/test-ipc.c
+++ b/android/test-ipc.c
@@ -44,6 +44,8 @@
 
 struct test_data {
 	uint32_t expected_signal;
+	const struct hal_hdr *cmd;
+	uint16_t cmd_size;
 };
 
 struct context {
@@ -95,6 +97,7 @@ static gboolean connect_handler(GIOChannel *io, GIOCondition cond,
 						gpointer user_data)
 {
 	struct context *context = user_data;
+	const struct test_data *test_data = context->data;
 	GIOChannel *new_io;
 	GIOCondition watch_cond;
 	int sk;
@@ -126,7 +129,7 @@ static gboolean connect_handler(GIOChannel *io, GIOCondition cond,
 		context->cmd_io = new_io;
 	}
 
-	if (context->cmd_source && context->notif_source)
+	if (context->cmd_source && context->notif_source && !test_data->cmd)
 		context_quit(context);
 
 	return TRUE;
@@ -262,8 +265,48 @@ static void test_init(gconstpointer data)
 	ipc_cleanup();
 }
 
+static gboolean send_cmd(gpointer user_data)
+{
+	struct context *context = user_data;
+	const struct test_data *test_data = context->data;
+	int sk;
+
+	sk = g_io_channel_unix_get_fd(context->cmd_io);
+	g_assert(sk >= 0);
+
+	g_assert(write(sk, test_data->cmd, test_data->cmd_size) ==
+						test_data->cmd_size);
+
+	return FALSE;
+}
+
+static void test_cmd(gconstpointer data)
+{
+	struct context *context = create_context(data);
+
+	ipc_init();
+
+	g_idle_add(send_cmd, context);
+
+	execute_context(context);
+
+	ipc_cleanup();
+}
+
 static const struct test_data test_init_1 = {};
 
+static const struct hal_hdr test_cmd_1_hdr = {
+	.service_id = 0,
+	.opcode = 1,
+	.len = 0
+};
+
+static const struct test_data test_cmd_1 = {
+	.cmd = &test_cmd_1_hdr,
+	.cmd_size = sizeof(test_cmd_1_hdr),
+	.expected_signal = SIGTERM
+};
+
 int main(int argc, char *argv[])
 {
 	g_test_init(&argc, &argv, NULL);
@@ -272,6 +315,7 @@ int main(int argc, char *argv[])
 		__btd_log_init("*", 0);
 
 	g_test_add_data_func("/android_ipc/init", &test_init_1, test_init);
+	g_test_add_data_func("/android_ipc/send_cmd_1", &test_cmd_1, test_cmd);
 
 	return g_test_run();
 }
-- 
1.8.3.1


^ permalink raw reply related

* [PATCHv3 2/5] android/ipc: Remove watches on cleanup
From: Marcin Kraglak @ 2014-01-16 10:04 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389866702-30697-1-git-send-email-marcin.kraglak@tieto.com>

Remove watches on cleanup. It will avoid receiving
events after cleanup.
---
 android/ipc.c | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/android/ipc.c b/android/ipc.c
index ed3ef3c..d6b96e3 100644
--- a/android/ipc.c
+++ b/android/ipc.c
@@ -45,6 +45,9 @@ static struct service_handler services[HAL_SERVICE_ID_MAX + 1];
 static GIOChannel *cmd_io = NULL;
 static GIOChannel *notif_io = NULL;
 
+static guint cmd_watch = 0;
+static guint notif_watch = 0;
+
 int ipc_handle_msg(struct service_handler *handlers, size_t max_index,
 						const void *buf, ssize_t len)
 {
@@ -192,11 +195,11 @@ static gboolean notif_connect_cb(GIOChannel *io, GIOCondition cond,
 
 	cond = G_IO_ERR | G_IO_HUP | G_IO_NVAL;
 
-	g_io_add_watch(io, cond, notif_watch_cb, NULL);
+	notif_watch = g_io_add_watch(io, cond, notif_watch_cb, NULL);
 
 	cond = G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
 
-	g_io_add_watch(cmd_io, cond, cmd_watch_cb, NULL);
+	cmd_watch = g_io_add_watch(cmd_io, cond, cmd_watch_cb, NULL);
 
 	info("IPC: successfully connected");
 
@@ -232,12 +235,22 @@ void ipc_init(void)
 
 void ipc_cleanup(void)
 {
+	if (cmd_watch) {
+		g_source_remove(cmd_watch);
+		cmd_watch = 0;
+	}
+
 	if (cmd_io) {
 		g_io_channel_shutdown(cmd_io, TRUE, NULL);
 		g_io_channel_unref(cmd_io);
 		cmd_io = NULL;
 	}
 
+	if (notif_watch) {
+		g_source_remove(notif_watch);
+		notif_watch = 0;
+	}
+
 	if (notif_io) {
 		g_io_channel_shutdown(notif_io, TRUE, NULL);
 		g_io_channel_unref(notif_io);
-- 
1.8.3.1


^ permalink raw reply related

* [PATCHv3 1/5] android/unit: Add android IPC unit tests
From: Marcin Kraglak @ 2014-01-16 10:04 UTC (permalink / raw)
  To: linux-bluetooth

It will test ipc library. First test case will check
ipc_init() call.
---
 .gitignore          |   1 +
 android/Makefile.am |   8 ++
 android/test-ipc.c  | 277 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 286 insertions(+)
 create mode 100644 android/test-ipc.c

diff --git a/.gitignore b/.gitignore
index ac76fe2..ddd562a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -114,3 +114,4 @@ android/bluetoothd
 android/haltest
 android/android-tester
 android/bluetoothd-snoop
+android/test-ipc
diff --git a/android/Makefile.am b/android/Makefile.am
index cd4a526..0c61317 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -117,6 +117,14 @@ android_android_tester_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
 
 android_android_tester_LDFLAGS = -pthread -ldl
 
+noinst_PROGRAMS += android/test-ipc
+
+android_test_ipc_SOURCES = android/test-ipc.c \
+				src/shared/util.h src/shared/util.c \
+				src/log.h src/log.c \
+				android/ipc.c android/ipc.h
+android_test_ipc_LDADD = @GLIB_LIBS@
+
 plugin_LTLIBRARIES += android/audio.a2dp.default.la
 
 android_audio_a2dp_default_la_SOURCES = android/audio-msg.h \
diff --git a/android/test-ipc.c b/android/test-ipc.c
new file mode 100644
index 0000000..6ac1175
--- /dev/null
+++ b/android/test-ipc.c
@@ -0,0 +1,277 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2014  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 <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <inttypes.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/signalfd.h>
+
+#include <glib.h>
+#include "src/shared/util.h"
+#include "src/log.h"
+#include "android/hal-msg.h"
+#include "android/ipc.h"
+
+struct test_data {
+	uint32_t expected_signal;
+};
+
+struct context {
+	GMainLoop *main_loop;
+
+	int sk;
+
+	guint source;
+	guint cmd_source;
+	guint notif_source;
+
+	GIOChannel *cmd_io;
+	GIOChannel *notif_io;
+	GIOChannel *signal_io;
+
+	guint signal_source;
+
+	const struct test_data *data;
+};
+
+static void context_quit(struct context *context)
+{
+	g_main_loop_quit(context->main_loop);
+}
+
+static gboolean cmd_watch(GIOChannel *io, GIOCondition cond,
+						gpointer user_data)
+{
+	if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
+		g_assert(FALSE);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static gboolean notif_watch(GIOChannel *io, GIOCondition cond,
+							gpointer user_data)
+{
+	if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
+		g_assert(FALSE);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static gboolean connect_handler(GIOChannel *io, GIOCondition cond,
+						gpointer user_data)
+{
+	struct context *context = user_data;
+	GIOChannel *new_io;
+	GIOCondition watch_cond;
+	int sk;
+
+	if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
+		g_assert(FALSE);
+		return FALSE;
+	}
+
+	g_assert(!context->cmd_source || !context->notif_source);
+
+	sk = accept(context->sk, NULL, NULL);
+	g_assert(sk >= 0);
+
+	new_io = g_io_channel_unix_new(sk);
+
+	watch_cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
+
+	if (context->cmd_source && !context->notif_source) {
+		context->notif_source = g_io_add_watch(new_io, watch_cond,
+							notif_watch, context);
+		g_assert(context->notif_source > 0);
+		context->notif_io = new_io;
+	}
+
+	if (!context->cmd_source) {
+		context->cmd_source = g_io_add_watch(new_io, watch_cond,
+							cmd_watch, context);
+		context->cmd_io = new_io;
+	}
+
+	if (context->cmd_source && context->notif_source)
+		context_quit(context);
+
+	return TRUE;
+}
+
+static gboolean signal_handler(GIOChannel *channel, GIOCondition cond,
+							gpointer user_data)
+{
+	struct context *context = user_data;
+	const struct test_data *test_data = context->data;
+	struct signalfd_siginfo si;
+	ssize_t result;
+	int fd;
+
+	if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP))
+		return FALSE;
+
+	fd = g_io_channel_unix_get_fd(channel);
+
+	result = read(fd, &si, sizeof(si));
+	if (result != sizeof(si))
+		return FALSE;
+
+	g_assert(test_data->expected_signal == si.ssi_signo);
+	context_quit(context);
+	return TRUE;
+}
+
+static guint setup_signalfd(gpointer user_data)
+{
+	GIOChannel *channel;
+	guint source;
+	sigset_t mask;
+	int ret;
+	int fd;
+
+	sigemptyset(&mask);
+	sigaddset(&mask, SIGINT);
+	sigaddset(&mask, SIGTERM);
+
+	ret = sigprocmask(SIG_BLOCK, &mask, NULL);
+	g_assert(ret == 0);
+
+	fd = signalfd(-1, &mask, 0);
+	g_assert(fd >= 0);
+
+	channel = g_io_channel_unix_new(fd);
+
+	g_io_channel_set_close_on_unref(channel, TRUE);
+	g_io_channel_set_encoding(channel, NULL, NULL);
+	g_io_channel_set_buffered(channel, FALSE);
+
+	source = g_io_add_watch(channel,
+				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+				signal_handler, user_data);
+
+	g_io_channel_unref(channel);
+
+	return source;
+}
+
+static struct context *create_context(gconstpointer data)
+{
+	struct context *context = g_new0(struct context, 1);
+	struct sockaddr_un addr;
+	GIOChannel *io;
+	int ret, sk;
+
+	context->main_loop = g_main_loop_new(NULL, FALSE);
+	g_assert(context->main_loop);
+
+	context->signal_source = setup_signalfd(context);
+	g_assert(context->signal_source);
+
+	sk = socket(AF_LOCAL, SOCK_SEQPACKET, 0);
+	g_assert(sk >= 0);
+
+	memset(&addr, 0, sizeof(addr));
+	addr.sun_family = AF_UNIX;
+
+	memcpy(addr.sun_path, BLUEZ_HAL_SK_PATH, sizeof(BLUEZ_HAL_SK_PATH));
+
+	ret = bind(sk, (struct sockaddr *) &addr, sizeof(addr));
+	g_assert(ret == 0);
+
+	ret = listen(sk, 5);
+	g_assert(ret == 0);
+
+	io = g_io_channel_unix_new(sk);
+
+	g_io_channel_set_close_on_unref(io, TRUE);
+
+	context->source = g_io_add_watch(io,
+				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+				connect_handler, context);
+	g_assert(context->source > 0);
+
+	g_io_channel_unref(io);
+
+	context->sk = sk;
+	context->data = data;
+
+	return context;
+}
+
+static void execute_context(struct context *context)
+{
+	g_main_loop_run(context->main_loop);
+
+	g_io_channel_shutdown(context->notif_io, true, NULL);
+	g_io_channel_shutdown(context->cmd_io, true, NULL);
+	g_io_channel_unref(context->cmd_io);
+	g_io_channel_unref(context->notif_io);
+
+	g_source_remove(context->notif_source);
+	g_source_remove(context->signal_source);
+	g_source_remove(context->cmd_source);
+	g_source_remove(context->source);
+
+	g_main_loop_unref(context->main_loop);
+
+	g_free(context);
+}
+
+static void test_init(gconstpointer data)
+{
+	struct context *context = create_context(data);
+
+	ipc_init();
+
+	execute_context(context);
+
+	ipc_cleanup();
+}
+
+static const struct test_data test_init_1 = {};
+
+int main(int argc, char *argv[])
+{
+	g_test_init(&argc, &argv, NULL);
+
+	if (g_test_verbose())
+		__btd_log_init("*", 0);
+
+	g_test_add_data_func("/android_ipc/init", &test_init_1, test_init);
+
+	return g_test_run();
+}
-- 
1.8.3.1


^ permalink raw reply related

* [PATCH 3/3] android/ipc: Add PTS test results document for AVCTP
From: Jakub Tyszkowski @ 2014-01-16 10:01 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389866462-7993-1-git-send-email-jakub.tyszkowski@tieto.com>

This will allow for better tracking of current state of implementation.
---
 android/Makefile.am   |  1 +
 android/pts-avctp.txt | 41 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 42 insertions(+)
 create mode 100644 android/pts-avctp.txt

diff --git a/android/Makefile.am b/android/Makefile.am
index 95ed7a7..f030bd4 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -149,5 +149,6 @@ EXTRA_DIST += android/Android.mk android/hal-ipc-api.txt android/README \
 		android/pics-a2dp.txt android/pixit-a2dp.txt \
 		android/pics-avctp.txt android/pixit-avctp.txt \
 		android/pts-a2dp.txt android/pts-avrcp.txt \
+		android/pts-avctp.txt \
 
 		android/pts-l2cap.txt
diff --git a/android/pts-avctp.txt b/android/pts-avctp.txt
new file mode 100644
index 0000000..c057a10
--- /dev/null
+++ b/android/pts-avctp.txt
@@ -0,0 +1,41 @@
+PTS test results for AVCTP
+
+PTS version: 5.0
+Tested: --not yet tested--
+
+Results:
+PASS	test passed
+FAIL	test failed
+INC	test is inconclusive
+N/A	test is disabled due to PICS setup
+
+		Controller (CT)
+-------------------------------------------------------------------------------
+Test Name		Result	Notes
+-------------------------------------------------------------------------------
+TC_CT_CCM_BV_01_C	N/A
+TC_CT_CCM_BV_02_C	N/A
+TC_CT_CCM_BV_03_C	N/A
+TC_CT_CCM_BV_04_C	N/A
+TC_CT_CCM_BI_01_C	N/A
+TC_CT_NFR_BV_01_C	N/A
+TC_CT_NFR_BV_04_C	N/A
+TC_CT_FRA_BV_01_C	N/A
+TC_CT_FRA_BV_04_C	N/A
+-------------------------------------------------------------------------------
+
+
+		Target (TG)
+-------------------------------------------------------------------------------
+Test Name		Result	Notes
+-------------------------------------------------------------------------------
+TC_TG_CCM_BV_01_C	INC
+TC_TG_CCM_BV_02_C	INC
+TC_TG_CCM_BV_03_C	INC
+TC_TG_CCM_BV_04_C	INC
+TC_TG_NFR_BV_02_C	INC
+TC_TG_NFR_BV_03_C	INC
+TC_TG_NFR_BI_01_C	INC
+TC_TG_FRA_BV_02_C	INC
+TC_TG_FRA_BV_03_C	INC
+-------------------------------------------------------------------------------
-- 
1.8.5.2


^ permalink raw reply related

* [PATCH 2/3] android/pts: Add PTS test results document for AVRCP
From: Jakub Tyszkowski @ 2014-01-16 10:01 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389866462-7993-1-git-send-email-jakub.tyszkowski@tieto.com>

This will allow for better tracking of current state of implementation.
---
 android/Makefile.am   |   2 +-
 android/pts-avrcp.txt | 194 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 195 insertions(+), 1 deletion(-)
 create mode 100644 android/pts-avrcp.txt

diff --git a/android/Makefile.am b/android/Makefile.am
index 0ce0188..95ed7a7 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -148,6 +148,6 @@ EXTRA_DIST += android/Android.mk android/hal-ipc-api.txt android/README \
 		android/pics-avrcp.txt android/pixit-avrcp.txt \
 		android/pics-a2dp.txt android/pixit-a2dp.txt \
 		android/pics-avctp.txt android/pixit-avctp.txt \
-		android/pts-a2dp.txt \
+		android/pts-a2dp.txt android/pts-avrcp.txt \
 
 		android/pts-l2cap.txt
diff --git a/android/pts-avrcp.txt b/android/pts-avrcp.txt
new file mode 100644
index 0000000..f2533b4
--- /dev/null
+++ b/android/pts-avrcp.txt
@@ -0,0 +1,194 @@
+PTS test results for AVRCP
+
+PTS version: 5.0
+Tested: --not yet tested--
+
+Results:
+PASS	test passed
+FAIL	test failed
+INC	test is inconclusive
+N/A	test is disabled due to PICS setup
+
+		Controller (CT)
+-------------------------------------------------------------------------------
+Test Name		Result	Notes
+-------------------------------------------------------------------------------
+TC_CT_BGN_BV_01_I	N/A
+TC_CT_BGN_BV_02_I	N/A
+TC_CT_CEC_BV_01_I	N/A
+TC_CT_CEC_BV_02_I	N/A
+TC_CT_CFG_BV_01_C	N/A
+TC_CT_CON_BV_01_C	N/A
+TC_CT_CON_BV_03_C	N/A
+TC_CT_CRC_BV_01_I	N/A
+TC_CT_CRC_BV_02_I	N/A
+TC_CT_ICC_BV_01_I	N/A
+TC_CT_ICC_BV_02_I	N/A
+TC_CT_MCN_CB_BV_01_C	N/A
+TC_CT_MCN_CB_BV_01_I	N/A
+TC_CT_MCN_CB_BV_02_I	N/A
+TC_CT_MCN_CB_BV_03_I	N/A
+TC_CT_MCN_CB_BV_04_C	N/A
+TC_CT_MCN_CB_BV_04_I	N/A
+TC_CT_MCN_CB_BV_05_I	N/A
+TC_CT_MCN_CB_BV_06_I	N/A
+TC_CT_MCN_CB_BV_07_C	N/A
+TC_CT_MCN_CB_BV_07_I	N/A
+TC_CT_MCN_NP_BV_01_C	N/A
+TC_CT_MCN_NP_BV_01_I	N/A
+TC_CT_MCN_NP_BV_02_I	N/A
+TC_CT_MCN_NP_BV_03_C	N/A
+TC_CT_MCN_NP_BV_03_I	N/A
+TC_CT_MCN_NP_BV_04_I	N/A
+TC_CT_MCN_NP_BV_05_C	N/A
+TC_CT_MCN_NP_BV_05_I	N/A
+TC_CT_MCN_NP_BV_06_I	N/A
+TC_CT_MCN_NP_BV_07_I	N/A
+TC_CT_MCN_NP_BV_08_C	N/A
+TC_CT_MCN_SRC_BV_01_C	N/A
+TC_CT_MCN_SRC_BV_01_I	N/A
+TC_CT_MCN_SRC_BV_02_I	N/A
+TC_CT_MCN_SRC_BV_03_C	N/A
+TC_CT_MCN_SRC_BV_03_I	N/A
+TC_CT_MCN_SRC_BV_04_I	N/A
+TC_CT_MCN_SRC_BV_05_C	N/A
+TC_CT_MDI_BV_01_C	N/A
+TC_CT_MDI_BV_03_C	N/A
+TC_CT_MPS_BV_01_C	N/A
+TC_CT_MPS_BV_01_I	N/A
+TC_CT_MPS_BV_02_I	N/A
+TC_CT_MPS_BV_03_C	N/A
+TC_CT_MPS_BV_03_I	N/A
+TC_CT_MPS_BV_08_C	N/A
+TC_CT_NFY_BV_01_C	N/A
+TC_CT_PAS_BV_01_C	N/A
+TC_CT_PAS_BV_03_C	N/A
+TC_CT_PAS_BV_05_C	N/A
+TC_CT_PAS_BV_07_C	N/A
+TC_CT_PAS_BV_09_C	N/A
+TC_CT_PAS_BV_11_C	N/A
+TC_CT_PTH_BV_01_C	N/A
+TC_CT_PTH_BV_02_C	N/A
+TC_CT_PTT_BV_01_I	N/A
+TC_CT_PTT_BV_02_I	N/A
+TC_CT_PTT_BV_03_I	N/A
+TC_CT_PTT_BV_04_I	N/A
+TC_CT_PTT_BV_05_I	N/A
+TC_CT_RCR_BV_01_C	N/A
+TC_CT_RCR_BV_03_C	N/A
+TC_CT_VLH_BI_03_C	N/A
+TC_CT_VLH_BI_04_C	N/A
+TC_CT_VLH_BV_01_C	N/A
+TC_CT_VLH_BV_01_I	N/A
+TC_CT_VLH_BV_02_I	N/A
+TC_CT_VLH_BV_03_C	N/A
+-------------------------------------------------------------------------------
+
+
+		Target (TG)
+-------------------------------------------------------------------------------
+Test Name		Result	Notes
+-------------------------------------------------------------------------------
+TC_TG_BGN_BV_01_I	N/A
+TC_TG_BGN_BV_02_I	N/A
+TC_TG_CEC_BV_01_I	INC
+TC_TG_CEC_BV_02_I	INC
+TC_TG_CFG_BI_01_C	INC
+TC_TG_CFG_BV_02_C	INC
+TC_TG_CON_BV_02_C	N/A
+TC_TG_CON_BV_04_C	N/A
+TC_TG_CON_BV_05_C	N/A
+TC_TG_CRC_BV_01_I	INC
+TC_TG_CRC_BV_02_I	INC
+TC_TG_ICC_BV_01_I	INC
+TC_TG_ICC_BV_02_I	INC
+TC_TG_INV_BI_01_C	INC
+TC_TG_INV_BI_02_C	N/A
+TC_TG_MCN_CB_BI_01_C	N/A
+TC_TG_MCN_CB_BI_02_C	N/A
+TC_TG_MCN_CB_BI_03_C	N/A
+TC_TG_MCN_CB_BI_04_C	N/A
+TC_TG_MCN_CB_BI_05_C	N/A
+TC_TG_MCN_CB_BV_01_I	N/A
+TC_TG_MCN_CB_BV_02_C	N/A
+TC_TG_MCN_CB_BV_02_I	N/A
+TC_TG_MCN_CB_BV_03_C	N/A
+TC_TG_MCN_CB_BV_03_I	N/A
+TC_TG_MCN_CB_BV_04_I	N/A
+TC_TG_MCN_CB_BV_05_C	N/A
+TC_TG_MCN_CB_BV_05_I	N/A
+TC_TG_MCN_CB_BV_06_C	N/A
+TC_TG_MCN_CB_BV_06_I	N/A
+TC_TG_MCN_CB_BV_07_I	N/A
+TC_TG_MCN_CB_BV_08_C	N/A
+TC_TG_MCN_CB_BV_09_C	N/A
+TC_TG_MCN_CB_BV_10_C	N/A
+TC_TG_MCN_CB_BV_11_C	N/A
+TC_TG_MCN_NP_BI_01_C	N/A
+TC_TG_MCN_NP_BI_02_C	N/A
+TC_TG_MCN_NP_BV_01_I	N/A
+TC_TG_MCN_NP_BV_02_C	N/A
+TC_TG_MCN_NP_BV_02_I	N/A
+TC_TG_MCN_NP_BV_03_I	N/A
+TC_TG_MCN_NP_BV_04_C	N/A
+TC_TG_MCN_NP_BV_04_I	N/A
+TC_TG_MCN_NP_BV_05_I	N/A
+TC_TG_MCN_NP_BV_06_C	N/A
+TC_TG_MCN_NP_BV_06_I	N/A
+TC_TG_MCN_NP_BV_07_C	N/A
+TC_TG_MCN_NP_BV_07_I	N/A
+TC_TG_MCN_NP_BV_09_C	N/A
+TC_TG_MCN_SRC_BV_01_I	N/A
+TC_TG_MCN_SRC_BV_02_C	N/A
+TC_TG_MCN_SRC_BV_02_I	N/A
+TC_TG_MCN_SRC_BV_03_I	N/A
+TC_TG_MCN_SRC_BV_04_C	N/A
+TC_TG_MCN_SRC_BV_04_I	N/A
+TC_TG_MCN_SRC_BV_06_C	N/A
+TC_TG_MDI_BV_02_C	INC
+TC_TG_MDI_BV_04_C	INC
+TC_TG_MDI_BV_05_C	INC
+TC_TG_MPS_BI_01_C	N/A
+TC_TG_MPS_BI_02_C	N/A
+TC_TG_MPS_BV_01_I	N/A
+TC_TG_MPS_BV_02_C	N/A
+TC_TG_MPS_BV_02_I	N/A
+TC_TG_MPS_BV_03_I	N/A
+TC_TG_MPS_BV_04_C	N/A
+TC_TG_MPS_BV_05_C	N/A
+TC_TG_MPS_BV_06_C	N/A
+TC_TG_MPS_BV_07_C	N/A
+TC_TG_MPS_BV_09_C	N/A
+TC_TG_MPS_BV_10_C	N/A
+TC_TG_NFY_BI_01_C	INC
+TC_TG_NFY_BV_02_C	INC
+TC_TG_NFY_BV_03_C	N/A
+TC_TG_NFY_BV_04_C	INC
+TC_TG_NFY_BV_05_C	INC
+TC_TG_NFY_BV_06_C	N/A
+TC_TG_NFY_BV_07_C	N/A
+TC_TG_NFY_BV_08_C	INC
+TC_TG_PAS_BI_01_C	N/A
+TC_TG_PAS_BI_02_C	N/A
+TC_TG_PAS_BI_03_C	N/A
+TC_TG_PAS_BI_04_C	N/A
+TC_TG_PAS_BI_05_C	N/A
+TC_TG_PAS_BV_02_C	N/A
+TC_TG_PAS_BV_04_C	N/A
+TC_TG_PAS_BV_06_C	N/A
+TC_TG_PAS_BV_08_C	N/A
+TC_TG_PAS_BV_10_C	N/A
+TC_TG_PTT_BV_01_I	INC
+TC_TG_PTT_BV_02_I	N/A
+TC_TG_PTT_BV_03_I	N/A
+TC_TG_PTT_BV_04_I	N/A
+TC_TG_PTT_BV_05_I	N/A
+TC_TG_RCR_BV_02_C	INC
+TC_TG_RCR_BV_04_C	INC
+TC_TG_VLH_BI_01_C	N/A
+TC_TG_VLH_BI_02_C	N/A
+TC_TG_VLH_BV_01_I	N/A
+TC_TG_VLH_BV_02_C	N/A
+TC_TG_VLH_BV_02_I	N/A
+TC_TG_VLH_BV_04_C	N/A
+-------------------------------------------------------------------------------
-- 
1.8.5.2


^ permalink raw reply related

* [PATCH 1/3] android/pts: Add PTS test results document for A2DP
From: Jakub Tyszkowski @ 2014-01-16 10:01 UTC (permalink / raw)
  To: linux-bluetooth

This will allow for better tracking of current state of implementation.
---
 android/Makefile.am  |  2 ++
 android/pts-a2dp.txt | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 59 insertions(+)
 create mode 100644 android/pts-a2dp.txt

diff --git a/android/Makefile.am b/android/Makefile.am
index cd4a526..0ce0188 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -148,4 +148,6 @@ EXTRA_DIST += android/Android.mk android/hal-ipc-api.txt android/README \
 		android/pics-avrcp.txt android/pixit-avrcp.txt \
 		android/pics-a2dp.txt android/pixit-a2dp.txt \
 		android/pics-avctp.txt android/pixit-avctp.txt \
+		android/pts-a2dp.txt \
+
 		android/pts-l2cap.txt
diff --git a/android/pts-a2dp.txt b/android/pts-a2dp.txt
new file mode 100644
index 0000000..a269ec1
--- /dev/null
+++ b/android/pts-a2dp.txt
@@ -0,0 +1,57 @@
+PTS test results for A2DP
+
+PTS version: 5.0
+Tested: --not yet tested--
+
+Results:
+PASS	test passed
+FAIL	test failed
+INC	test is inconclusive
+N/A	test is disabled due to PICS setup
+
+		Source (SRC)
+-------------------------------------------------------------------------------
+Test Name		Result	Notes
+-------------------------------------------------------------------------------
+TC_SRC_CC_BV_09_I	INC
+TC_SRC_CC_BV_10_I	N/A
+TC_SRC_REL_BV_01_I	INC
+TC_SRC_REL_BV_02_I	INC
+TC_SRC_SET_BV_01_I	INC
+TC_SRC_SET_BV_02_I	INC
+TC_SRC_SET_BV_03_I	INC
+TC_SRC_SET_BV_04_I	INC
+TC_SRC_SET_BV_05_I	INC
+TC_SRC_SET_BV_06_I	INC
+TC_SRC_SUS_BV_01_I	INC
+TC_SRC_SUS_BV_02_I	INC
+TC_SRC_SDP_BV_01_I	INC
+TC_SRC_AS_BV_01_I	INC
+-------------------------------------------------------------------------------
+
+
+		Sink (SNK)
+-------------------------------------------------------------------------------
+Test Name		Result	Notes
+-------------------------------------------------------------------------------
+TC_SNK_CC_BV_01_I	N/A
+TC_SNK_CC_BV_02_I	N/A
+TC_SNK_CC_BV_03_I	N/A
+TC_SNK_CC_BV_04_I	N/A
+TC_SNK_CC_BV_05_I	N/A
+TC_SNK_CC_BV_06_I	N/A
+TC_SNK_CC_BV_07_I	N/A
+TC_SNK_CC_BV_08_I	N/A
+TC_SNK_REL_BV_01_I	N/A
+TC_SNK_REL_BV_02_I	N/A
+TC_SNK_SET_BV_01_I	N/A
+TC_SNK_SET_BV_02_I	N/A
+TC_SNK_SET_BV_03_I	N/A
+TC_SNK_SET_BV_04_I	N/A
+TC_SNK_SET_BV_05_I	N/A
+TC_SNK_SET_BV_06_I	N/A
+TC_SNK_SUS_BV_01_I	N/A
+TC_SNK_SUS_BV_02_I	N/A
+TC_SNK_SDP_BV_02_I	N/A
+TC_SNK_AS_BV_01_I	N/A
+-------------------------------------------------------------------------------
-- 
1.8.5.2


^ permalink raw reply related

* [PATCHv2 5/5] android/ipc-tester: Add next command test case
From: Marcin Kraglak @ 2014-01-16  9:45 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389865538-28157-1-git-send-email-marcin.kraglak@tieto.com>

This case will register service, next unregister it and send
command. Expected status is raise SIGTERM.
---
 android/test-ipc.c | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/android/test-ipc.c b/android/test-ipc.c
index 930f9f4..1fde61b 100644
--- a/android/test-ipc.c
+++ b/android/test-ipc.c
@@ -306,6 +306,16 @@ static gboolean register_service(gpointer user_data)
 	return FALSE;
 }
 
+static gboolean unregister_service(gpointer user_data)
+{
+	struct context *context = user_data;
+	const struct test_data *test_data = context->data;
+
+	ipc_unregister(test_data->service);
+
+	return FALSE;
+}
+
 static void test_cmd(gconstpointer data)
 {
 	struct context *context = create_context(data);
@@ -336,6 +346,21 @@ static void test_cmd_reg(gconstpointer data)
 	ipc_cleanup();
 }
 
+static void test_cmd_reg_1(gconstpointer data)
+{
+	struct context *context = create_context(data);
+
+	ipc_init();
+
+	g_idle_add(register_service, context);
+	g_idle_add(unregister_service, context);
+	g_idle_add(send_cmd, context);
+
+	execute_context(context);
+
+	ipc_cleanup();
+}
+
 static void test_cmd_handler(const void *buf, uint16_t len)
 {
 	ipc_send_rsp(0, 1, 0);
@@ -367,6 +392,15 @@ static const struct test_data test_cmd_2 = {
 	.handlers_size = 1
 };
 
+static const struct test_data test_cmd_3 = {
+	.cmd = &test_cmd_1_hdr,
+	.cmd_size = sizeof(test_cmd_1_hdr),
+	.service = 0,
+	.handlers = cmd_handlers,
+	.handlers_size = 1,
+	.expected_signal = SIGTERM
+};
+
 int main(int argc, char *argv[])
 {
 	g_test_init(&argc, &argv, NULL);
@@ -378,6 +412,8 @@ int main(int argc, char *argv[])
 	g_test_add_data_func("/android_ipc/send_cmd_1", &test_cmd_1, test_cmd);
 	g_test_add_data_func("/android_ipc/send_cmd_2", &test_cmd_2,
 							test_cmd_reg);
+	g_test_add_data_func("/android_ipc/send_cmd_3", &test_cmd_3,
+							test_cmd_reg_1);
 
 	return g_test_run();
 }
-- 
1.8.3.1


^ permalink raw reply related

* [PATCHv2 4/5] android/ipc-tester: Add test case to send cmd to registered service
From: Marcin Kraglak @ 2014-01-16  9:45 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389865538-28157-1-git-send-email-marcin.kraglak@tieto.com>

This will test sending command to previously registered service.
---
 android/test-ipc.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 62 insertions(+)

diff --git a/android/test-ipc.c b/android/test-ipc.c
index 99f8559..930f9f4 100644
--- a/android/test-ipc.c
+++ b/android/test-ipc.c
@@ -46,6 +46,9 @@ struct test_data {
 	uint32_t expected_signal;
 	const struct hal_hdr *cmd;
 	uint16_t cmd_size;
+	uint8_t service;
+	const struct ipc_handler *handlers;
+	uint8_t handlers_size;
 };
 
 struct context {
@@ -74,11 +77,23 @@ static void context_quit(struct context *context)
 static gboolean cmd_watch(GIOChannel *io, GIOCondition cond,
 						gpointer user_data)
 {
+	struct context *context = user_data;
+	const struct test_data *test_data = context->data;
+	uint8_t buf[128];
+	int sk;
+
 	if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
 		g_assert(FALSE);
 		return FALSE;
 	}
 
+	sk = g_io_channel_unix_get_fd(io);
+
+	g_assert(read(sk, buf, sizeof(buf)) == test_data->cmd_size);
+	g_assert(!memcmp(test_data->cmd, buf, test_data->cmd_size));
+
+	context_quit(context);
+
 	return TRUE;
 }
 
@@ -280,6 +295,17 @@ static gboolean send_cmd(gpointer user_data)
 	return FALSE;
 }
 
+static gboolean register_service(gpointer user_data)
+{
+	struct context *context = user_data;
+	const struct test_data *test_data = context->data;
+
+	ipc_register(test_data->service, test_data->handlers,
+						test_data->handlers_size);
+
+	return FALSE;
+}
+
 static void test_cmd(gconstpointer data)
 {
 	struct context *context = create_context(data);
@@ -293,6 +319,28 @@ static void test_cmd(gconstpointer data)
 	ipc_cleanup();
 }
 
+static void test_cmd_reg(gconstpointer data)
+{
+	struct context *context = create_context(data);
+	const struct test_data *test_data = context->data;
+
+	ipc_init();
+
+	g_idle_add(register_service, context);
+	g_idle_add(send_cmd, context);
+
+	execute_context(context);
+
+	ipc_unregister(test_data->service);
+
+	ipc_cleanup();
+}
+
+static void test_cmd_handler(const void *buf, uint16_t len)
+{
+	ipc_send_rsp(0, 1, 0);
+}
+
 static const struct test_data test_init_1 = {};
 
 static const struct hal_hdr test_cmd_1_hdr = {
@@ -307,6 +355,18 @@ static const struct test_data test_cmd_1 = {
 	.expected_signal = SIGTERM
 };
 
+static const struct ipc_handler cmd_handlers[] = {
+	{ test_cmd_handler, false, 0 }
+};
+
+static const struct test_data test_cmd_2 = {
+	.cmd = &test_cmd_1_hdr,
+	.cmd_size = sizeof(test_cmd_1_hdr),
+	.service = 0,
+	.handlers = cmd_handlers,
+	.handlers_size = 1
+};
+
 int main(int argc, char *argv[])
 {
 	g_test_init(&argc, &argv, NULL);
@@ -316,6 +376,8 @@ int main(int argc, char *argv[])
 
 	g_test_add_data_func("/android_ipc/init", &test_init_1, test_init);
 	g_test_add_data_func("/android_ipc/send_cmd_1", &test_cmd_1, test_cmd);
+	g_test_add_data_func("/android_ipc/send_cmd_2", &test_cmd_2,
+							test_cmd_reg);
 
 	return g_test_run();
 }
-- 
1.8.3.1


^ permalink raw reply related

* [PATCHv2 3/5] android/ipc-tester: Add test case to send cmd
From: Marcin Kraglak @ 2014-01-16  9:45 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389865538-28157-1-git-send-email-marcin.kraglak@tieto.com>

This test case will check if ipc lib will raise SIGTERM
after sending cmd to not registered service.
---
 android/test-ipc.c | 46 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 45 insertions(+), 1 deletion(-)

diff --git a/android/test-ipc.c b/android/test-ipc.c
index 6ac1175..99f8559 100644
--- a/android/test-ipc.c
+++ b/android/test-ipc.c
@@ -44,6 +44,8 @@
 
 struct test_data {
 	uint32_t expected_signal;
+	const struct hal_hdr *cmd;
+	uint16_t cmd_size;
 };
 
 struct context {
@@ -95,6 +97,7 @@ static gboolean connect_handler(GIOChannel *io, GIOCondition cond,
 						gpointer user_data)
 {
 	struct context *context = user_data;
+	const struct test_data *test_data = context->data;
 	GIOChannel *new_io;
 	GIOCondition watch_cond;
 	int sk;
@@ -126,7 +129,7 @@ static gboolean connect_handler(GIOChannel *io, GIOCondition cond,
 		context->cmd_io = new_io;
 	}
 
-	if (context->cmd_source && context->notif_source)
+	if (context->cmd_source && context->notif_source && !test_data->cmd)
 		context_quit(context);
 
 	return TRUE;
@@ -262,8 +265,48 @@ static void test_init(gconstpointer data)
 	ipc_cleanup();
 }
 
+static gboolean send_cmd(gpointer user_data)
+{
+	struct context *context = user_data;
+	const struct test_data *test_data = context->data;
+	int sk;
+
+	sk = g_io_channel_unix_get_fd(context->cmd_io);
+	g_assert(sk >= 0);
+
+	g_assert(write(sk, test_data->cmd, test_data->cmd_size) ==
+						test_data->cmd_size);
+
+	return FALSE;
+}
+
+static void test_cmd(gconstpointer data)
+{
+	struct context *context = create_context(data);
+
+	ipc_init();
+
+	g_idle_add(send_cmd, context);
+
+	execute_context(context);
+
+	ipc_cleanup();
+}
+
 static const struct test_data test_init_1 = {};
 
+static const struct hal_hdr test_cmd_1_hdr = {
+	.service_id = 0,
+	.opcode = 1,
+	.len = 0
+};
+
+static const struct test_data test_cmd_1 = {
+	.cmd = &test_cmd_1_hdr,
+	.cmd_size = sizeof(test_cmd_1_hdr),
+	.expected_signal = SIGTERM
+};
+
 int main(int argc, char *argv[])
 {
 	g_test_init(&argc, &argv, NULL);
@@ -272,6 +315,7 @@ int main(int argc, char *argv[])
 		__btd_log_init("*", 0);
 
 	g_test_add_data_func("/android_ipc/init", &test_init_1, test_init);
+	g_test_add_data_func("/android_ipc/send_cmd_1", &test_cmd_1, test_cmd);
 
 	return g_test_run();
 }
-- 
1.8.3.1


^ permalink raw reply related

* [PATCHv2 2/5] android: Fix ipc cleanup
From: Marcin Kraglak @ 2014-01-16  9:45 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389865538-28157-1-git-send-email-marcin.kraglak@tieto.com>

Remove sources while cleanup. It will avoid receiving
events after cleanup.
---
 android/ipc.c | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/android/ipc.c b/android/ipc.c
index ed3ef3c..d6b96e3 100644
--- a/android/ipc.c
+++ b/android/ipc.c
@@ -45,6 +45,9 @@ static struct service_handler services[HAL_SERVICE_ID_MAX + 1];
 static GIOChannel *cmd_io = NULL;
 static GIOChannel *notif_io = NULL;
 
+static guint cmd_watch = 0;
+static guint notif_watch = 0;
+
 int ipc_handle_msg(struct service_handler *handlers, size_t max_index,
 						const void *buf, ssize_t len)
 {
@@ -192,11 +195,11 @@ static gboolean notif_connect_cb(GIOChannel *io, GIOCondition cond,
 
 	cond = G_IO_ERR | G_IO_HUP | G_IO_NVAL;
 
-	g_io_add_watch(io, cond, notif_watch_cb, NULL);
+	notif_watch = g_io_add_watch(io, cond, notif_watch_cb, NULL);
 
 	cond = G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
 
-	g_io_add_watch(cmd_io, cond, cmd_watch_cb, NULL);
+	cmd_watch = g_io_add_watch(cmd_io, cond, cmd_watch_cb, NULL);
 
 	info("IPC: successfully connected");
 
@@ -232,12 +235,22 @@ void ipc_init(void)
 
 void ipc_cleanup(void)
 {
+	if (cmd_watch) {
+		g_source_remove(cmd_watch);
+		cmd_watch = 0;
+	}
+
 	if (cmd_io) {
 		g_io_channel_shutdown(cmd_io, TRUE, NULL);
 		g_io_channel_unref(cmd_io);
 		cmd_io = NULL;
 	}
 
+	if (notif_watch) {
+		g_source_remove(notif_watch);
+		notif_watch = 0;
+	}
+
 	if (notif_io) {
 		g_io_channel_shutdown(notif_io, TRUE, NULL);
 		g_io_channel_unref(notif_io);
-- 
1.8.3.1


^ permalink raw reply related

* [PATCHv2 1/5] android: Add android ipc tester
From: Marcin Kraglak @ 2014-01-16  9:45 UTC (permalink / raw)
  To: linux-bluetooth

This tool will test ipc library. First test case will check
ipc_init() call.
---
 .gitignore          |   1 +
 android/Makefile.am |   8 ++
 android/test-ipc.c  | 277 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 286 insertions(+)
 create mode 100644 android/test-ipc.c

diff --git a/.gitignore b/.gitignore
index ac76fe2..ddd562a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -114,3 +114,4 @@ android/bluetoothd
 android/haltest
 android/android-tester
 android/bluetoothd-snoop
+android/test-ipc
diff --git a/android/Makefile.am b/android/Makefile.am
index cd4a526..0c61317 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -117,6 +117,14 @@ android_android_tester_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
 
 android_android_tester_LDFLAGS = -pthread -ldl
 
+noinst_PROGRAMS += android/test-ipc
+
+android_test_ipc_SOURCES = android/test-ipc.c \
+				src/shared/util.h src/shared/util.c \
+				src/log.h src/log.c \
+				android/ipc.c android/ipc.h
+android_test_ipc_LDADD = @GLIB_LIBS@
+
 plugin_LTLIBRARIES += android/audio.a2dp.default.la
 
 android_audio_a2dp_default_la_SOURCES = android/audio-msg.h \
diff --git a/android/test-ipc.c b/android/test-ipc.c
new file mode 100644
index 0000000..6ac1175
--- /dev/null
+++ b/android/test-ipc.c
@@ -0,0 +1,277 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2014  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 <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <inttypes.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/signalfd.h>
+
+#include <glib.h>
+#include "src/shared/util.h"
+#include "src/log.h"
+#include "android/hal-msg.h"
+#include "android/ipc.h"
+
+struct test_data {
+	uint32_t expected_signal;
+};
+
+struct context {
+	GMainLoop *main_loop;
+
+	int sk;
+
+	guint source;
+	guint cmd_source;
+	guint notif_source;
+
+	GIOChannel *cmd_io;
+	GIOChannel *notif_io;
+	GIOChannel *signal_io;
+
+	guint signal_source;
+
+	const struct test_data *data;
+};
+
+static void context_quit(struct context *context)
+{
+	g_main_loop_quit(context->main_loop);
+}
+
+static gboolean cmd_watch(GIOChannel *io, GIOCondition cond,
+						gpointer user_data)
+{
+	if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
+		g_assert(FALSE);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static gboolean notif_watch(GIOChannel *io, GIOCondition cond,
+							gpointer user_data)
+{
+	if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
+		g_assert(FALSE);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static gboolean connect_handler(GIOChannel *io, GIOCondition cond,
+						gpointer user_data)
+{
+	struct context *context = user_data;
+	GIOChannel *new_io;
+	GIOCondition watch_cond;
+	int sk;
+
+	if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
+		g_assert(FALSE);
+		return FALSE;
+	}
+
+	g_assert(!context->cmd_source || !context->notif_source);
+
+	sk = accept(context->sk, NULL, NULL);
+	g_assert(sk >= 0);
+
+	new_io = g_io_channel_unix_new(sk);
+
+	watch_cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
+
+	if (context->cmd_source && !context->notif_source) {
+		context->notif_source = g_io_add_watch(new_io, watch_cond,
+							notif_watch, context);
+		g_assert(context->notif_source > 0);
+		context->notif_io = new_io;
+	}
+
+	if (!context->cmd_source) {
+		context->cmd_source = g_io_add_watch(new_io, watch_cond,
+							cmd_watch, context);
+		context->cmd_io = new_io;
+	}
+
+	if (context->cmd_source && context->notif_source)
+		context_quit(context);
+
+	return TRUE;
+}
+
+static gboolean signal_handler(GIOChannel *channel, GIOCondition cond,
+							gpointer user_data)
+{
+	struct context *context = user_data;
+	const struct test_data *test_data = context->data;
+	struct signalfd_siginfo si;
+	ssize_t result;
+	int fd;
+
+	if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP))
+		return FALSE;
+
+	fd = g_io_channel_unix_get_fd(channel);
+
+	result = read(fd, &si, sizeof(si));
+	if (result != sizeof(si))
+		return FALSE;
+
+	g_assert(test_data->expected_signal == si.ssi_signo);
+	context_quit(context);
+	return TRUE;
+}
+
+static guint setup_signalfd(gpointer user_data)
+{
+	GIOChannel *channel;
+	guint source;
+	sigset_t mask;
+	int ret;
+	int fd;
+
+	sigemptyset(&mask);
+	sigaddset(&mask, SIGINT);
+	sigaddset(&mask, SIGTERM);
+
+	ret = sigprocmask(SIG_BLOCK, &mask, NULL);
+	g_assert(ret == 0);
+
+	fd = signalfd(-1, &mask, 0);
+	g_assert(fd >= 0);
+
+	channel = g_io_channel_unix_new(fd);
+
+	g_io_channel_set_close_on_unref(channel, TRUE);
+	g_io_channel_set_encoding(channel, NULL, NULL);
+	g_io_channel_set_buffered(channel, FALSE);
+
+	source = g_io_add_watch(channel,
+				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+				signal_handler, user_data);
+
+	g_io_channel_unref(channel);
+
+	return source;
+}
+
+static struct context *create_context(gconstpointer data)
+{
+	struct context *context = g_new0(struct context, 1);
+	struct sockaddr_un addr;
+	GIOChannel *io;
+	int ret, sk;
+
+	context->main_loop = g_main_loop_new(NULL, FALSE);
+	g_assert(context->main_loop);
+
+	context->signal_source = setup_signalfd(context);
+	g_assert(context->signal_source);
+
+	sk = socket(AF_LOCAL, SOCK_SEQPACKET, 0);
+	g_assert(sk >= 0);
+
+	memset(&addr, 0, sizeof(addr));
+	addr.sun_family = AF_UNIX;
+
+	memcpy(addr.sun_path, BLUEZ_HAL_SK_PATH, sizeof(BLUEZ_HAL_SK_PATH));
+
+	ret = bind(sk, (struct sockaddr *) &addr, sizeof(addr));
+	g_assert(ret == 0);
+
+	ret = listen(sk, 5);
+	g_assert(ret == 0);
+
+	io = g_io_channel_unix_new(sk);
+
+	g_io_channel_set_close_on_unref(io, TRUE);
+
+	context->source = g_io_add_watch(io,
+				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+				connect_handler, context);
+	g_assert(context->source > 0);
+
+	g_io_channel_unref(io);
+
+	context->sk = sk;
+	context->data = data;
+
+	return context;
+}
+
+static void execute_context(struct context *context)
+{
+	g_main_loop_run(context->main_loop);
+
+	g_io_channel_shutdown(context->notif_io, true, NULL);
+	g_io_channel_shutdown(context->cmd_io, true, NULL);
+	g_io_channel_unref(context->cmd_io);
+	g_io_channel_unref(context->notif_io);
+
+	g_source_remove(context->notif_source);
+	g_source_remove(context->signal_source);
+	g_source_remove(context->cmd_source);
+	g_source_remove(context->source);
+
+	g_main_loop_unref(context->main_loop);
+
+	g_free(context);
+}
+
+static void test_init(gconstpointer data)
+{
+	struct context *context = create_context(data);
+
+	ipc_init();
+
+	execute_context(context);
+
+	ipc_cleanup();
+}
+
+static const struct test_data test_init_1 = {};
+
+int main(int argc, char *argv[])
+{
+	g_test_init(&argc, &argv, NULL);
+
+	if (g_test_verbose())
+		__btd_log_init("*", 0);
+
+	g_test_add_data_func("/android_ipc/init", &test_init_1, test_init);
+
+	return g_test_run();
+}
-- 
1.8.3.1


^ permalink raw reply related

* Re: [PATCH] Bluetooth: Queue incoming ACL data until BT_CONNECTED state is reached
From: Johan Hedberg @ 2014-01-16  8:53 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: linux-bluetooth@vger.kernel.org development
In-Reply-To: <BB667CD7-90B1-4D87-8647-F59CB35A258B@holtmann.org>

Hi Marcel,

On Wed, Jan 15, 2014, Marcel Holtmann wrote:
> > --- a/net/bluetooth/l2cap_core.c
> > +++ b/net/bluetooth/l2cap_core.c
> > @@ -63,6 +63,8 @@ static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err);
> > static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
> > 		     struct sk_buff_head *skbs, u8 event);
> > 
> > +static void process_pending_rx(struct work_struct *work);
> > +
> 
> do we really need this forward declaration?

Believe me I hate forward declarations just as much as you do. Either
this function or then l2cap_recv_frame must be forward declared unless
you want to move the following functions further down in l2cap_core.c:

l2cap_conn_add()
l2cap_chan_connect()
l2cap_connect_cfm()

The last two depend on l2cap_conn_add() which in turn depends on
process_pending_rx(). It's a fairly simple patch looking like this (two
more lines removed because the stat includes removing the forward
declatiation - I'd of course order the patches the other way around when
I send them):

 net/bluetooth/l2cap_core.c | 430 ++++++++++++++++++++--------------------
 1 file changed, 214 insertions(+), 216 deletions(-)

Doing this however means e.g. that l2cap_connect_cfm() isn't any more
grouped in the same place as connect_ind() and the other callbacks. So
I'm not sure if you wanna move those also downwards (making the patch
bigger), not worry about it, or just stick to the forward declaration.

Johan

> > +static void process_pending_rx(struct work_struct *work)
> > +{
> > +	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
> > +					       pending_rx_work);
> > +
> > +	BT_DBG("");
> > +
> > +	while (!skb_queue_empty(&conn->pending_rx)) {
> > +		struct sk_buff *skb;
> > +
> > +		skb = skb_dequeue(&conn->pending_rx);
> > +
> > +		l2cap_recv_frame(conn, skb);
> > +	}
> > +}
> > +
> 
> I realize we have done this skb_queue_empty check and then skb_dequeue
> a bit, but that seems a little bit pointless.
> 
> skb_dequeue is taking a spinlock, but even then checking for empty
> first and then dequeuing it seems more complicated that needed here.
> We could just dequeue it check if skb == NULL.
> 
> 	while (1) {
> 		struct sk_buff *skb;
> 
> 		skb = sbk_dequeue(&conn->pending_rx);
> 		if (!skb)
> 			break;
> 
> 		l2cap_recv_frame(conn, skb);
> 	}

I've fixed this in my v2.

> And we have similar things in l2cap_streaming_send, l2cap_chan_send
> and l2cap_le_credits. I get the feeling we should change all of these.

Sure, I'll send patches for those at some point.

Johan

^ permalink raw reply

* Re: [PATCH 2/5] android: Fix ipc cleanup
From: Szymon Janc @ 2014-01-16  8:41 UTC (permalink / raw)
  To: Marcin Kraglak; +Cc: linux-bluetooth
In-Reply-To: <1389813150-16914-2-git-send-email-marcin.kraglak@tieto.com>

Hi Marcin,

On Wednesday 15 of January 2014 20:12:27 Marcin Kraglak wrote:
> Remove sources while cleanup. It will avoid receiving
> events after cleanup.
> ---
>  android/ipc.c | 17 +++++++++++++++--
>  1 file changed, 15 insertions(+), 2 deletions(-)
> 
> diff --git a/android/ipc.c b/android/ipc.c
> index ed3ef3c..4277bfe 100644
> --- a/android/ipc.c
> +++ b/android/ipc.c
> @@ -45,6 +45,9 @@ static struct service_handler services[HAL_SERVICE_ID_MAX + 1];
>  static GIOChannel *cmd_io = NULL;
>  static GIOChannel *notif_io = NULL;
>  
> +static guint cmd_id;
> +static guint notif_id;

Please name it cmd_watch and notif_watch. Also explicitly initialize them to 0 here.

> +
>  int ipc_handle_msg(struct service_handler *handlers, size_t max_index,
>  						const void *buf, ssize_t len)
>  {
> @@ -192,11 +195,11 @@ static gboolean notif_connect_cb(GIOChannel *io, GIOCondition cond,
>  
>  	cond = G_IO_ERR | G_IO_HUP | G_IO_NVAL;
>  
> -	g_io_add_watch(io, cond, notif_watch_cb, NULL);
> +	notif_id = g_io_add_watch(io, cond, notif_watch_cb, NULL);
>  
>  	cond = G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
>  
> -	g_io_add_watch(cmd_io, cond, cmd_watch_cb, NULL);
> +	cmd_id = g_io_add_watch(cmd_io, cond, cmd_watch_cb, NULL);
>  
>  	info("IPC: successfully connected");
>  
> @@ -232,12 +235,22 @@ void ipc_init(void)
>  
>  void ipc_cleanup(void)
>  {
> +	if (cmd_id) {
> +		g_source_remove(cmd_id);
> +		cmd_id = 0;
> +	}
> +
>  	if (cmd_io) {
>  		g_io_channel_shutdown(cmd_io, TRUE, NULL);
>  		g_io_channel_unref(cmd_io);
>  		cmd_io = NULL;
>  	}
>  
> +	if (notif_id) {
> +		g_source_remove(notif_id);
> +		notif_id = 0;
> +	}
> +
>  	if (notif_io) {
>  		g_io_channel_shutdown(notif_io, TRUE, NULL);
>  		g_io_channel_unref(notif_io);
> 

-- 
Best regards, 
Szymon Janc

^ permalink raw reply

* [PATCHv4 8/8] android/ipc-tester: Add more cases for malformed data
From: Jakub Tyszkowski @ 2014-01-16  8:38 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389861512-2326-1-git-send-email-jakub.tyszkowski@tieto.com>

This patch adds tests for more types of possible data malformations.
---
 android/ipc-tester.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/android/ipc-tester.c b/android/ipc-tester.c
index f4321ce..3f4db82 100644
--- a/android/ipc-tester.c
+++ b/android/ipc-tester.c
@@ -577,6 +577,48 @@ static const struct generic_data malformed_data = {
 	.num_services = 1,
 };
 
+static const struct generic_data malformed_data2 = {
+	.ipc_data = {
+		/* use proper msg */
+		.buffer = &register_bt_msg,
+		/* but write incomplete */
+		.len = sizeof(register_bt_msg) - 1,
+	},
+	.init_services = {HAL_SERVICE_ID_BLUETOOTH},
+	.num_services = 1,
+};
+
+struct malformed_data3_struct {
+	struct regmod_msg valid_msg;
+	int redundant_data;
+}  __attribute__((packed));
+
+static struct malformed_data3_struct malformed_data3_msg = {
+	/* valid register service message */
+	.valid_msg = {
+		.header = {
+			.service_id = HAL_SERVICE_ID_CORE,
+			.opcode = HAL_OP_REGISTER_MODULE,
+			.len = sizeof(struct hal_cmd_register_module),
+			},
+		.cmd = {
+			.service_id = HAL_SERVICE_ID_CORE,
+			},
+	},
+	/* plus redundant data */
+	. redundant_data = 666,
+};
+
+static const struct generic_data malformed_data3 = {
+	.ipc_data = {
+		/* use malformed msg */
+		.buffer = &malformed_data3_msg,
+		.len = sizeof(malformed_data3_msg),
+	},
+	.init_services = {HAL_SERVICE_ID_BLUETOOTH},
+	.num_services = 1,
+};
+
 struct hal_hdr enable_unknown_service_hdr = {
 	.service_id = HAL_SERVICE_ID_MAX + 1,
 	.opcode = HAL_OP_REGISTER_MODULE,
@@ -653,6 +695,10 @@ int main(int argc, char *argv[])
 						setup, ipc_send_tc, teardown);
 	test_bredrle("Malformed data (wrong payload declared)", &malformed_data,
 						setup, ipc_send_tc, teardown);
+	test_bredrle("Malformed data2 (undersized msg)", &malformed_data2,
+						setup, ipc_send_tc, teardown);
+	test_bredrle("Malformed data3 (oversized msg)", &malformed_data3,
+						setup, ipc_send_tc, teardown);
 	test_bredrle("Invalid service", &enable_unknown_service_data,
 						setup, ipc_send_tc, teardown);
 	test_bredrle("Enable unregistered service",
-- 
1.8.5.2


^ permalink raw reply related

* [PATCHv4 7/8] android/ipc-tester: Add basic test cases for IPC's daemon site
From: Jakub Tyszkowski @ 2014-01-16  8:38 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389861512-2326-1-git-send-email-jakub.tyszkowski@tieto.com>

This patch add first few test cases checking for proper daemon
termination in case of receiving invalid IPC data.
---
 android/ipc-tester.c | 120 +++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 117 insertions(+), 3 deletions(-)

diff --git a/android/ipc-tester.c b/android/ipc-tester.c
index 12ab85b..f4321ce 100644
--- a/android/ipc-tester.c
+++ b/android/ipc-tester.c
@@ -532,11 +532,113 @@ static void ipc_send_tc(const void *data)
 							3, user, g_free); \
 	} while (0)
 
-static const struct generic_data dummy_data = {
+struct regmod_msg register_bt_msg = {
+	.header = {
+		.service_id = HAL_SERVICE_ID_CORE,
+		.opcode = HAL_OP_REGISTER_MODULE,
+		.len = sizeof(struct hal_cmd_register_module),
+		},
+	.cmd = {
+		.service_id = HAL_SERVICE_ID_CORE,
+		},
+};
+
+static const struct generic_data too_small_data = {
 	.ipc_data = {
-		.buffer = "",
+		/* valid header and payload */
+		.buffer = &register_bt_msg,
+		/* but write only incomplete header */
 		.len = 1,
 	},
+	.init_services = {},
+	.num_services = 0,
+};
+
+struct regmod_msg register_bt_malformed_size_msg = {
+	.header = {
+		.service_id = HAL_SERVICE_ID_CORE,
+		.opcode = HAL_OP_REGISTER_MODULE,
+		/* wrong payload size declared */
+		.len = sizeof(struct hal_cmd_register_module) - 1,
+		},
+	.cmd = {
+		.service_id = HAL_SERVICE_ID_CORE,
+		},
+};
+
+static const struct generic_data malformed_data = {
+	.ipc_data = {
+		/* use malformed msg - wrong size declared */
+		.buffer = &register_bt_malformed_size_msg,
+		/* but write proper size */
+		.len = sizeof(register_bt_malformed_size_msg),
+	},
+	.init_services = {HAL_SERVICE_ID_BLUETOOTH},
+	.num_services = 1,
+};
+
+struct hal_hdr enable_unknown_service_hdr = {
+	.service_id = HAL_SERVICE_ID_MAX + 1,
+	.opcode = HAL_OP_REGISTER_MODULE,
+	.len = 0,
+};
+
+static const struct generic_data enable_unknown_service_data = {
+	.ipc_data = {
+		/* enable invalid service */
+		.buffer = &enable_unknown_service_hdr,
+		.len = sizeof(enable_unknown_service_hdr),
+	},
+	.init_services = {HAL_SERVICE_ID_BLUETOOTH},
+	.num_services = 1,
+};
+
+struct hal_hdr enable_bt_service_hdr = {
+	.service_id = HAL_SERVICE_ID_BLUETOOTH,
+	.opcode = HAL_OP_ENABLE,
+	.len = 0,
+};
+
+static const struct generic_data enable_unregistered_service_data = {
+	.ipc_data = {
+		/* valid msg */
+		.buffer = &enable_bt_service_hdr,
+		/* send the whole thing */
+		.len = sizeof(enable_bt_service_hdr),
+	},
+	/* but don't register it before enabling */
+	.init_services = {},
+	.num_services = 0,
+};
+
+struct hal_hdr invalid_opcode_hdr = {
+	.service_id = HAL_SERVICE_ID_BLUETOOTH,
+	.opcode = 0x16,
+	.len = 0,
+};
+
+static const struct generic_data invalid_opcode_data = {
+	.ipc_data = {
+		/* valid msg */
+		.buffer = &invalid_opcode_hdr,
+		/* send the whole thing */
+		.len = sizeof(invalid_opcode_hdr),
+	},
+	.init_services = {HAL_SERVICE_ID_BLUETOOTH},
+	.num_services = 1,
+};
+
+struct hal_hdr invalid_msg_size_hdr = {
+	.service_id = HAL_SERVICE_ID_BLUETOOTH,
+	.opcode = HAL_OP_CREATE_BOND,
+	.len = 0,
+};
+
+static const struct generic_data invalid_msg_size_data = {
+	.ipc_data = {
+		.buffer = &invalid_msg_size_hdr,
+		.len = sizeof(invalid_msg_size_hdr),
+	},
 	.init_services = {HAL_SERVICE_ID_BLUETOOTH},
 	.num_services = 1,
 };
@@ -547,7 +649,19 @@ int main(int argc, char *argv[])
 
 	tester_init(&argc, &argv);
 
-	test_bredrle("Test Dummy", &dummy_data, setup, ipc_send_tc, teardown);
+	test_bredrle("Too small data", &too_small_data,
+						setup, ipc_send_tc, teardown);
+	test_bredrle("Malformed data (wrong payload declared)", &malformed_data,
+						setup, ipc_send_tc, teardown);
+	test_bredrle("Invalid service", &enable_unknown_service_data,
+						setup, ipc_send_tc, teardown);
+	test_bredrle("Enable unregistered service",
+					&enable_unregistered_service_data,
+					setup, ipc_send_tc, teardown);
+	test_bredrle("Invalid opcode", &invalid_opcode_data,
+						setup, ipc_send_tc, teardown);
+	test_bredrle("Invalid msg size for opcode", &invalid_msg_size_data,
+						setup, ipc_send_tc, teardown);
 
 	return tester_run();
 }
-- 
1.8.5.2


^ permalink raw reply related

* [PATCHv4 6/8] android/ipc-tester: Register services
From: Jakub Tyszkowski @ 2014-01-16  8:38 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389861512-2326-1-git-send-email-jakub.tyszkowski@tieto.com>

This patch adds basic bluetooth service registration during setup procedure.
Without this daemon would reject commands for not registered services.
---
 android/ipc-tester.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 47 insertions(+), 1 deletion(-)

diff --git a/android/ipc-tester.c b/android/ipc-tester.c
index 0a04fb7..12ab85b 100644
--- a/android/ipc-tester.c
+++ b/android/ipc-tester.c
@@ -396,13 +396,53 @@ static gboolean check_for_daemon(gpointer user_data)
 	return false;
 }
 
+struct regmod_msg {
+	struct hal_hdr header;
+	struct hal_cmd_register_module cmd;
+} __attribute__((packed));
+
+static bool setup_module(int service_id)
+{
+	struct hal_hdr response;
+	struct hal_hdr expected_response;
+
+	struct regmod_msg btmodule_msg = {
+		.header = {
+			.service_id = HAL_SERVICE_ID_CORE,
+			.opcode = HAL_OP_REGISTER_MODULE,
+			.len = sizeof(struct hal_cmd_register_module),
+			},
+		.cmd = {
+			.service_id = service_id,
+			},
+	};
+
+	if (write(cmd_sk, &btmodule_msg, sizeof(btmodule_msg)) < 0)
+		goto fail;
+
+	if (read(cmd_sk, &response, sizeof(response)) < 0)
+		goto fail;
+
+	expected_response = btmodule_msg.header;
+	expected_response.len = 0;
+
+	if (memcmp(&response, &expected_response, sizeof(response)) == 0)
+		return true;
+
+fail:
+	tester_warn("Module registration failed.");
+	return false;
+}
+
 static void setup(const void *data)
 {
+	const struct generic_data *generic_data = data;
 	struct test_data *test_data = tester_get_data();
 	int signal_fd[2];
 	char buf[1024];
 	pid_t pid;
 	int len;
+	unsigned int i;
 
 	if (pipe(signal_fd)) {
 		tester_setup_failed();
@@ -446,9 +486,15 @@ static void setup(const void *data)
 		return;
 	}
 
-	/* TODO: register modules */
+	tester_print("Will init %d services.", generic_data->num_services);
+
+	for (i = 0; i < generic_data->num_services; i++)
+		if (!setup_module(generic_data->init_services[i]))
+			tester_setup_failed();
 
 	test_data->setup_done = true;
+
+	tester_setup_complete();
 }
 
 static void teardown(const void *data)
-- 
1.8.5.2


^ permalink raw reply related

* [PATCHv4 5/8] android/ipc-tester: Add sending test data with ipc
From: Jakub Tyszkowski @ 2014-01-16  8:38 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389861512-2326-1-git-send-email-jakub.tyszkowski@tieto.com>

This patch adds some data structures used to send data with ipc during test setup
and run stage.
---
 android/ipc-tester.c | 30 +++++++++++++++++++++++++++++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/android/ipc-tester.c b/android/ipc-tester.c
index 6ba6e1f..0a04fb7 100644
--- a/android/ipc-tester.c
+++ b/android/ipc-tester.c
@@ -55,6 +55,18 @@ struct test_data {
 	bool setup_done;
 };
 
+struct ipc_data {
+	void *buffer;
+	size_t len;
+};
+
+struct generic_data {
+	struct ipc_data ipc_data;
+
+	unsigned int num_services;
+	int init_services[];
+};
+
 #define CONNECT_TIMEOUT (5 * 1000)
 #define SERVICE_NAME "bluetoothd"
 
@@ -453,6 +465,13 @@ static void teardown(const void *data)
 
 static void ipc_send_tc(const void *data)
 {
+	const struct generic_data *generic_data = data;
+	const struct ipc_data *ipc_data = &generic_data->ipc_data;
+
+	if (ipc_data->len) {
+		if (write(cmd_sk, ipc_data->buffer, ipc_data->len) < 0)
+			tester_test_failed();
+	}
 }
 
 #define test_bredrle(name, data, test_setup, test, test_teardown) \
@@ -467,13 +486,22 @@ static void ipc_send_tc(const void *data)
 							3, user, g_free); \
 	} while (0)
 
+static const struct generic_data dummy_data = {
+	.ipc_data = {
+		.buffer = "",
+		.len = 1,
+	},
+	.init_services = {HAL_SERVICE_ID_BLUETOOTH},
+	.num_services = 1,
+};
+
 int main(int argc, char *argv[])
 {
 	snprintf(exec_dir, sizeof(exec_dir), "%s", dirname(argv[0]));
 
 	tester_init(&argc, &argv);
 
-	test_bredrle("Test Dummy", NULL, setup, ipc_send_tc, teardown);
+	test_bredrle("Test Dummy", &dummy_data, setup, ipc_send_tc, teardown);
 
 	return tester_run();
 }
-- 
1.8.5.2


^ permalink raw reply related

* [PATCHv4 4/8] android/ipc-tester: Add daemon shutdown handler
From: Jakub Tyszkowski @ 2014-01-16  8:38 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389861512-2326-1-git-send-email-jakub.tyszkowski@tieto.com>

Handle daemon shutdown asynchronously.
---
 android/ipc-tester.c | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/android/ipc-tester.c b/android/ipc-tester.c
index b76be32..6ba6e1f 100644
--- a/android/ipc-tester.c
+++ b/android/ipc-tester.c
@@ -52,6 +52,7 @@ struct test_data {
 	struct hciemu *hciemu;
 	enum hciemu_type hciemu_type;
 	pid_t bluetoothd_pid;
+	bool setup_done;
 };
 
 #define CONNECT_TIMEOUT (5 * 1000)
@@ -359,6 +360,30 @@ static void cleanup_ipc(void)
 	cmd_sk = -1;
 }
 
+static gboolean check_for_daemon(gpointer user_data)
+{
+	int status;
+	struct test_data *data = user_data;
+
+	if ((waitpid(data->bluetoothd_pid, &status, WNOHANG))
+							!= data->bluetoothd_pid)
+		return true;
+
+	if (data->setup_done) {
+		if (WIFEXITED(status) &&
+				(WEXITSTATUS(status) == EXIT_SUCCESS)) {
+			tester_test_passed();
+			return false;
+		}
+		tester_test_failed();
+	} else {
+		tester_setup_failed();
+	}
+
+	tester_warn("Unexpected Daemon shutdown with status %d", status);
+	return false;
+}
+
 static void setup(const void *data)
 {
 	struct test_data *test_data = tester_get_data();
@@ -399,6 +424,10 @@ static void setup(const void *data)
 		tester_setup_failed();
 		return;
 	}
+
+	g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, check_for_daemon, test_data,
+									NULL);
+
 	if (!init_ipc()) {
 		tester_warn("Cannot initialize IPC mechanism!");
 		tester_setup_failed();
@@ -406,6 +435,8 @@ static void setup(const void *data)
 	}
 
 	/* TODO: register modules */
+
+	test_data->setup_done = true;
 }
 
 static void teardown(const void *data)
-- 
1.8.5.2


^ permalink raw reply related


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