Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH 7/7] android/ipc-tester: Add basic negative test cases for IPC's daemon site
From: Jakub Tyszkowski @ 2014-01-13 10:37 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389609422-21200-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-negative-tester.c | 120 ++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 117 insertions(+), 3 deletions(-)

diff --git a/android/ipc-negative-tester.c b/android/ipc-negative-tester.c
index 7b2bbf8..15701e8 100644
--- a/android/ipc-negative-tester.c
+++ b/android/ipc-negative-tester.c
@@ -540,22 +540,136 @@ 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 to_small_data = {
 	.ipc_data = {
-		.buffer = "",
+		/* valid header and payload */
+		.buffer = &register_bt_msg,
+		/* but write only incomplete header */
 		.len = 1,
 	},
 	.init_services = {HAL_SERVICE_ID_BLUETOOTH},
 	.num_services = 1,
 };
 
+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(struct hal_cmd_register_module),
+	},
+	.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_ENABLE,
+	.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,
+};
+
 int main(int argc, char *argv[])
 {
 	snprintf(exec_dir, sizeof(exec_dir), "%s", dirname(argv[0]));
 
 	tester_init(&argc, &argv);
 
-	test_bredrle("Test Dummy", &dummy_data, setup, ipc_send_tc, teardown);
+	test_bredrle("To small data", &to_small_data,
+						setup, ipc_send_tc, teardown);
+	test_bredrle("Malformed data", &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


^ permalink raw reply related

* [PATCH 6/7] android/ipc-tester: Register services
From: Jakub Tyszkowski @ 2014-01-13 10:37 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389609422-21200-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-negative-tester.c | 48 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 47 insertions(+), 1 deletion(-)

diff --git a/android/ipc-negative-tester.c b/android/ipc-negative-tester.c
index 46a8754..7b2bbf8 100644
--- a/android/ipc-negative-tester.c
+++ b/android/ipc-negative-tester.c
@@ -404,13 +404,53 @@ failed:
 	return false;
 }
 
+struct regmod_msg {
+	struct hal_hdr header;
+	struct hal_cmd_register_module cmd;
+};
+
+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();
@@ -454,9 +494,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


^ permalink raw reply related

* [PATCH 5/7] android/ipc-tester: Add sending test data with ipc
From: Jakub Tyszkowski @ 2014-01-13 10:37 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389609422-21200-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-negative-tester.c | 30 +++++++++++++++++++++++++++++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/android/ipc-negative-tester.c b/android/ipc-negative-tester.c
index bbe4ce6..46a8754 100644
--- a/android/ipc-negative-tester.c
+++ b/android/ipc-negative-tester.c
@@ -49,6 +49,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"
 
@@ -461,6 +473,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) \
@@ -475,13 +494,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


^ permalink raw reply related

* [PATCH 4/7] android/ipc-tester: Add daemon shutdown handler
From: Jakub Tyszkowski @ 2014-01-13 10:36 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389609422-21200-1-git-send-email-jakub.tyszkowski@tieto.com>

Handle daemon shutdown asynchronously.

---
 android/ipc-negative-tester.c | 45 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/android/ipc-negative-tester.c b/android/ipc-negative-tester.c
index 1736794..bbe4ce6 100644
--- a/android/ipc-negative-tester.c
+++ b/android/ipc-negative-tester.c
@@ -46,6 +46,7 @@ struct test_data {
 	struct hciemu *hciemu;
 	enum hciemu_type hciemu_type;
 	pid_t bluetoothd_pid;
+	bool setup_done;
 };
 
 #define CONNECT_TIMEOUT (5 * 1000)
@@ -353,6 +354,44 @@ 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 (WIFEXITED(status)) {
+		tester_test_passed();
+	} else if (WIFSIGNALED(status)) {
+		switch (WTERMSIG(status)) {
+		case SIGTERM:
+			if (data->setup_done)
+				tester_test_passed();
+			else
+				tester_setup_failed();
+			break;
+		case SIGSEGV:
+			tester_warn("Daemon died with segmentation fault");
+			goto failed;
+		default:
+			tester_warn("Bad signal received %d", status);
+			goto failed;
+		}
+	}
+
+	return true;
+
+failed:
+	if (data->setup_done)
+		tester_test_failed();
+	else
+		tester_setup_failed();
+	return false;
+}
+
 static void setup(const void *data)
 {
 	struct test_data *test_data = tester_get_data();
@@ -393,6 +432,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();
@@ -400,6 +443,8 @@ static void setup(const void *data)
 	}
 
 	/* TODO: register modules */
+
+	test_data->setup_done = true;
 }
 
 static void teardown(const void *data)
-- 
1.8.5


^ permalink raw reply related

* [PATCH 3/7] android/ipc-tester: Add IPC initialization
From: Jakub Tyszkowski @ 2014-01-13 10:36 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389609422-21200-1-git-send-email-jakub.tyszkowski@tieto.com>

This patch adds IPC mechanism initialization.
The deamon is being started and IPC socket connection is established.

---
 android/ipc-negative-tester.c | 122 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 122 insertions(+)

diff --git a/android/ipc-negative-tester.c b/android/ipc-negative-tester.c
index 78ca104..1736794 100644
--- a/android/ipc-negative-tester.c
+++ b/android/ipc-negative-tester.c
@@ -17,6 +17,8 @@
 
 #include <stdlib.h>
 #include <unistd.h>
+#include <errno.h>
+#include <poll.h>
 
 #include <sys/socket.h>
 #include <sys/types.h>
@@ -32,6 +34,8 @@
 #include "src/shared/mgmt.h"
 #include "src/shared/hciemu.h"
 
+#include "hal-msg.h"
+#include <cutils/properties.h>
 
 #define WAIT_FOR_SIGNAL_TIME 2 /* in seconds */
 #define EMULATOR_SIGNAL "emulator_started"
@@ -44,8 +48,14 @@ struct test_data {
 	pid_t bluetoothd_pid;
 };
 
+#define CONNECT_TIMEOUT (5 * 1000)
+#define SERVICE_NAME "bluetoothd"
+
 static char exec_dir[PATH_MAX + 1];
 
+static int cmd_sk = -1;
+static int notif_sk = -1;
+
 static void read_info_callback(uint8_t status, uint16_t length,
 					const void *param, void *user_data)
 {
@@ -240,6 +250,109 @@ failed:
 	close(fd);
 }
 
+static int accept_connection(int sk)
+{
+	int err;
+	struct pollfd pfd;
+	int new_sk;
+
+	memset(&pfd, 0 , sizeof(pfd));
+	pfd.fd = sk;
+	pfd.events = POLLIN;
+
+	err = poll(&pfd, 1, CONNECT_TIMEOUT);
+	if (err < 0) {
+		err = errno;
+		tester_warn("Failed to poll: %d (%s)", err, strerror(err));
+		return -errno;
+	}
+
+	if (err == 0) {
+		tester_warn("bluetoothd connect timeout");
+		return -errno;
+	}
+
+	new_sk = accept(sk, NULL, NULL);
+	if (new_sk < 0) {
+		err = errno;
+		tester_warn("Failed to accept socket: %d (%s)",
+							err, strerror(err));
+		return -errno;
+	}
+
+	return new_sk;
+}
+
+static bool init_ipc(void)
+{
+	struct sockaddr_un addr;
+
+	int sk;
+	int err;
+
+	sk = socket(AF_LOCAL, SOCK_SEQPACKET, 0);
+	if (sk < 0) {
+		err = errno;
+		tester_warn("Failed to create socket: %d (%s)", err,
+							strerror(err));
+		return false;
+	}
+
+	memset(&addr, 0, sizeof(addr));
+	addr.sun_family = AF_UNIX;
+
+	memcpy(addr.sun_path, BLUEZ_HAL_SK_PATH, sizeof(BLUEZ_HAL_SK_PATH));
+
+	if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+		err = errno;
+		tester_warn("Failed to bind socket: %d (%s)", err,
+								strerror(err));
+		close(sk);
+		return false;
+	}
+
+	if (listen(sk, 2) < 0) {
+		err = errno;
+		tester_warn("Failed to listen on socket: %d (%s)", err,
+								strerror(err));
+		close(sk);
+		return false;
+	}
+
+	/* Start Android Bluetooth daemon service */
+	if (property_set("ctl.start", SERVICE_NAME) < 0) {
+		tester_warn("Failed to start service %s", SERVICE_NAME);
+		close(sk);
+		return false;
+	}
+
+	cmd_sk = accept_connection(sk);
+	if (cmd_sk < 0) {
+		close(sk);
+		return false;
+	}
+
+	notif_sk = accept_connection(sk);
+	if (notif_sk < 0) {
+		close(sk);
+		close(cmd_sk);
+		cmd_sk = -1;
+		return false;
+	}
+
+	tester_print("bluetoothd connected");
+
+	close(sk);
+
+	return true;
+}
+
+static void cleanup_ipc(void)
+{
+	close(cmd_sk);
+	cmd_sk = -1;
+}
+
 static void setup(const void *data)
 {
 	struct test_data *test_data = tester_get_data();
@@ -280,12 +393,21 @@ static void setup(const void *data)
 		tester_setup_failed();
 		return;
 	}
+	if (!init_ipc()) {
+		tester_warn("Cannot initialize IPC mechanism!");
+		tester_setup_failed();
+		return;
+	}
+
+	/* TODO: register modules */
 }
 
 static void teardown(const void *data)
 {
 	struct test_data *test_data = tester_get_data();
 
+	cleanup_ipc();
+
 	if (test_data->bluetoothd_pid)
 		waitpid(test_data->bluetoothd_pid, NULL, 0);
 
-- 
1.8.5


^ permalink raw reply related

* [PATCH 2/7] android/ipc-tester: Run daemon in separate process
From: Jakub Tyszkowski @ 2014-01-13 10:36 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389609422-21200-1-git-send-email-jakub.tyszkowski@tieto.com>

This patch adds new process waiting to run daemon when needed.

---
 android/ipc-negative-tester.c | 124 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 123 insertions(+), 1 deletion(-)

diff --git a/android/ipc-negative-tester.c b/android/ipc-negative-tester.c
index 0c2edda..78ca104 100644
--- a/android/ipc-negative-tester.c
+++ b/android/ipc-negative-tester.c
@@ -15,8 +15,14 @@
  *
  */
 
+#include <stdlib.h>
 #include <unistd.h>
 
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/un.h>
+#include <libgen.h>
 #include <glib.h>
 
 #include "lib/bluetooth.h"
@@ -27,13 +33,19 @@
 #include "src/shared/hciemu.h"
 
 
+#define WAIT_FOR_SIGNAL_TIME 2 /* in seconds */
+#define EMULATOR_SIGNAL "emulator_started"
+
 struct test_data {
 	struct mgmt *mgmt;
 	uint16_t mgmt_index;
 	struct hciemu *hciemu;
 	enum hciemu_type hciemu_type;
+	pid_t bluetoothd_pid;
 };
 
+static char exec_dir[PATH_MAX + 1];
+
 static void read_info_callback(uint8_t status, uint16_t length,
 					const void *param, void *user_data)
 {
@@ -162,13 +174,121 @@ static void test_post_teardown(const void *data)
 	test_data->hciemu = NULL;
 }
 
+static void bluetoothd_start(int hci_index)
+{
+	char prg_name[PATH_MAX + 1];
+	char index[8];
+	char *prg_argv[4];
+
+	snprintf(prg_name, sizeof(prg_name), "%s/%s", exec_dir, "bluetoothd");
+	snprintf(index, sizeof(index), "%d", hci_index);
+
+	prg_argv[0] = prg_name;
+	prg_argv[1] = "-i";
+	prg_argv[2] = index;
+	prg_argv[3] = NULL;
+
+	if (!tester_use_debug())
+		fclose(stderr);
+
+	execve(prg_argv[0], prg_argv, NULL);
+}
+
+static void emulator(int pipe, int hci_index)
+{
+	static const char SYSTEM_SOCKET_PATH[] = "\0android_system";
+	char buf[1024];
+	struct sockaddr_un addr;
+	struct timeval tv;
+	int fd;
+	ssize_t len;
+
+	fd = socket(PF_LOCAL, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+	if (fd < 0)
+		goto failed;
+
+	tv.tv_sec = WAIT_FOR_SIGNAL_TIME;
+	tv.tv_usec = 0;
+	setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv));
+
+	memset(&addr, 0, sizeof(addr));
+	addr.sun_family = AF_UNIX;
+	memcpy(addr.sun_path, SYSTEM_SOCKET_PATH, sizeof(SYSTEM_SOCKET_PATH));
+
+	if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+		perror("Failed to bind system socket");
+		goto failed;
+	}
+
+	len = write(pipe, EMULATOR_SIGNAL, sizeof(EMULATOR_SIGNAL));
+
+	if (len != sizeof(EMULATOR_SIGNAL))
+		goto failed;
+
+	memset(buf, 0, sizeof(buf));
+
+	len = read(fd, buf, sizeof(buf));
+	if (len <= 0 || (strcmp(buf, "ctl.start=bluetoothd")))
+		goto failed;
+
+	close(pipe);
+	close(fd);
+	bluetoothd_start(hci_index);
+
+failed:
+	close(pipe);
+	close(fd);
+}
+
 static void setup(const void *data)
 {
-	tester_setup_failed();
+	struct test_data *test_data = tester_get_data();
+	int signal_fd[2];
+	char buf[1024];
+	pid_t pid;
+	int len;
+
+	if (pipe(signal_fd)) {
+		tester_setup_failed();
+		return;
+	}
+
+	pid = fork();
+
+	if (pid < 0) {
+		close(signal_fd[0]);
+		close(signal_fd[1]);
+		tester_setup_failed();
+		return;
+	}
+
+	if (pid == 0) {
+		if (!tester_use_debug())
+			fclose(stderr);
+
+		close(signal_fd[0]);
+		emulator(signal_fd[1], test_data->mgmt_index);
+		exit(0);
+	}
+
+	close(signal_fd[1]);
+	test_data->bluetoothd_pid = pid;
+
+	len = read(signal_fd[0], buf, sizeof(buf));
+	if (len <= 0 || (strcmp(buf, EMULATOR_SIGNAL))) {
+		close(signal_fd[0]);
+		tester_setup_failed();
+		return;
+	}
 }
 
 static void teardown(const void *data)
 {
+	struct test_data *test_data = tester_get_data();
+
+	if (test_data->bluetoothd_pid)
+		waitpid(test_data->bluetoothd_pid, NULL, 0);
+
 	tester_teardown_complete();
 }
 
@@ -190,6 +310,8 @@ static void ipc_send_tc(const void *data)
 
 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);
-- 
1.8.5


^ permalink raw reply related

* [PATCH 1/7] android/ipc-tester: Skeleton for ipc negative tester
From: Jakub Tyszkowski @ 2014-01-13 10:36 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389609422-21200-1-git-send-email-jakub.tyszkowski@tieto.com>

Add skeleton for ipc negative testing.

---
 .gitignore                    |   1 +
 android/Makefile.am           |  17 ++++
 android/ipc-negative-tester.c | 198 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 216 insertions(+)
 create mode 100644 android/ipc-negative-tester.c

diff --git a/.gitignore b/.gitignore
index 077b1c9..89406f9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -112,4 +112,5 @@ android/system-emulator
 android/bluetoothd
 android/haltest
 android/android-tester
+android/ipc-negative-tester
 android/bluetoothd-snoop
diff --git a/android/Makefile.am b/android/Makefile.am
index 356f932..c89c7e3 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -121,6 +121,23 @@ android_android_tester_LDFLAGS = -pthread -ldl
 
 plugin_LTLIBRARIES += android/audio.a2dp.default.la
 
+noinst_PROGRAMS += android/ipc-negative-tester
+
+android_ipc_negative_tester_SOURCES = emulator/btdev.h emulator/btdev.c \
+				emulator/bthost.h emulator/bthost.c \
+				src/shared/io.h src/shared/io-glib.c \
+				src/shared/queue.h src/shared/queue.c \
+				src/shared/util.h src/shared/util.c \
+				src/shared/mgmt.h src/shared/mgmt.c \
+				src/shared/hciemu.h src/shared/hciemu.c \
+				src/shared/tester.h src/shared/tester.c \
+				android/hal-utils.h android/hal-utils.c \
+				android/ipc-negative-tester.c
+
+android_ipc_negative_tester_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/android
+
+android_ipc_negative_tester_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
+
 android_audio_a2dp_default_la_SOURCES = android/audio-msg.h \
 					android/hal-audio.c \
 					android/hardware/audio.h \
diff --git a/android/ipc-negative-tester.c b/android/ipc-negative-tester.c
new file mode 100644
index 0000000..0c2edda
--- /dev/null
+++ b/android/ipc-negative-tester.c
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2014 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <unistd.h>
+
+#include <glib.h>
+
+#include "lib/bluetooth.h"
+#include "lib/mgmt.h"
+
+#include "src/shared/tester.h"
+#include "src/shared/mgmt.h"
+#include "src/shared/hciemu.h"
+
+
+struct test_data {
+	struct mgmt *mgmt;
+	uint16_t mgmt_index;
+	struct hciemu *hciemu;
+	enum hciemu_type hciemu_type;
+};
+
+static void read_info_callback(uint8_t status, uint16_t length,
+					const void *param, void *user_data)
+{
+	struct test_data *data = tester_get_data();
+	const struct mgmt_rp_read_info *rp = param;
+	char addr[18];
+	uint16_t manufacturer;
+	uint32_t supported_settings, current_settings;
+
+	tester_print("Read Info callback");
+	tester_print("  Status: 0x%02x", status);
+
+	if (status || !param) {
+		tester_pre_setup_failed();
+		return;
+	}
+
+	ba2str(&rp->bdaddr, addr);
+	manufacturer = btohs(rp->manufacturer);
+	supported_settings = btohl(rp->supported_settings);
+	current_settings = btohl(rp->current_settings);
+
+	tester_print("  Address: %s", addr);
+	tester_print("  Version: 0x%02x", rp->version);
+	tester_print("  Manufacturer: 0x%04x", manufacturer);
+	tester_print("  Supported settings: 0x%08x", supported_settings);
+	tester_print("  Current settings: 0x%08x", current_settings);
+	tester_print("  Class: 0x%02x%02x%02x",
+			rp->dev_class[2], rp->dev_class[1], rp->dev_class[0]);
+	tester_print("  Name: %s", rp->name);
+	tester_print("  Short name: %s", rp->short_name);
+
+	if (strcmp(hciemu_get_address(data->hciemu), addr)) {
+		tester_pre_setup_failed();
+		return;
+	}
+
+	tester_pre_setup_complete();
+}
+
+static void index_added_callback(uint16_t index, uint16_t length,
+					const void *param, void *user_data)
+{
+	struct test_data *data = tester_get_data();
+
+	tester_print("Index Added callback");
+	tester_print("  Index: 0x%04x", index);
+
+	data->mgmt_index = index;
+
+	mgmt_send(data->mgmt, MGMT_OP_READ_INFO, data->mgmt_index, 0, NULL,
+					read_info_callback, NULL, NULL);
+}
+
+static void index_removed_callback(uint16_t index, uint16_t length,
+					const void *param, void *user_data)
+{
+	struct test_data *data = tester_get_data();
+
+	tester_print("Index Removed callback");
+	tester_print("  Index: 0x%04x", index);
+
+	if (index != data->mgmt_index)
+		return;
+
+	mgmt_unregister_index(data->mgmt, data->mgmt_index);
+
+	mgmt_unref(data->mgmt);
+	data->mgmt = NULL;
+
+	tester_post_teardown_complete();
+}
+
+static void read_index_list_callback(uint8_t status, uint16_t length,
+					const void *param, void *user_data)
+{
+	struct test_data *data = tester_get_data();
+
+	tester_print("Read Index List callback");
+	tester_print("  Status: 0x%02x", status);
+
+	if (status || !param) {
+		tester_pre_setup_failed();
+		return;
+	}
+
+	mgmt_register(data->mgmt, MGMT_EV_INDEX_ADDED, MGMT_INDEX_NONE,
+					index_added_callback, NULL, NULL);
+
+	mgmt_register(data->mgmt, MGMT_EV_INDEX_REMOVED, MGMT_INDEX_NONE,
+					index_removed_callback, NULL, NULL);
+
+	data->hciemu = hciemu_new(data->hciemu_type);
+	if (!data->hciemu) {
+		tester_warn("Failed to setup HCI emulation");
+		tester_pre_setup_failed();
+		return;
+	}
+
+	tester_print("New hciemu instance created");
+}
+
+static void test_pre_setup(const void *data)
+{
+	struct test_data *test_data = tester_get_data();
+
+	if (!tester_use_debug())
+		fclose(stderr);
+
+	test_data->mgmt = mgmt_new_default();
+	if (!test_data->mgmt) {
+		tester_warn("Failed to setup management interface");
+		tester_pre_setup_failed();
+		return;
+	}
+
+	mgmt_send(test_data->mgmt, MGMT_OP_READ_INDEX_LIST, MGMT_INDEX_NONE, 0,
+				NULL, read_index_list_callback, NULL, NULL);
+}
+
+static void test_post_teardown(const void *data)
+{
+	struct test_data *test_data = tester_get_data();
+
+	hciemu_unref(test_data->hciemu);
+	test_data->hciemu = NULL;
+}
+
+static void setup(const void *data)
+{
+	tester_setup_failed();
+}
+
+static void teardown(const void *data)
+{
+	tester_teardown_complete();
+}
+
+static void ipc_send_tc(const void *data)
+{
+}
+
+#define test_bredrle(name, data, test_setup, test, test_teardown) \
+	do { \
+		struct test_data *user; \
+		user = g_malloc0(sizeof(struct test_data)); \
+		if (!user) \
+			break; \
+		user->hciemu_type = HCIEMU_TYPE_BREDRLE; \
+		tester_add_full(name, data, test_pre_setup, test_setup, \
+				test, test_teardown, test_post_teardown, \
+							3, user, g_free); \
+	} while (0)
+
+int main(int argc, char *argv[])
+{
+	tester_init(&argc, &argv);
+
+	test_bredrle("Test Dummy", NULL, setup, ipc_send_tc, teardown);
+
+	return tester_run();
+}
-- 
1.8.5


^ permalink raw reply related

* [PATCH 0/7] IPC negative tester
From: Jakub Tyszkowski @ 2014-01-13 10:36 UTC (permalink / raw)
  To: linux-bluetooth

Following patchset adds IPC negative tester framework with few test cases
checking IPC's behaviour on daemon side. Expected daemon's behaviour is to
shut down gracefully in case of receiving invalid IPC data.

Jakub Tyszkowski (7):
  android/ipc-tester: Skeleton for ipc negative tester
  android/ipc-tester: Run daemon in separate process
  android/ipc-tester: Add IPC initialization
  android/ipc-tester: Add daemon shutdown handler
  android/ipc-tester: Add sending test data with ipc
  android/ipc-tester: Register services
  android/ipc-tester: Add basic negative test cases for IPC's daemon
    site

 .gitignore                    |   1 +
 android/Makefile.am           |  17 ++
 android/ipc-negative-tester.c | 675 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 693 insertions(+)
 create mode 100644 android/ipc-negative-tester.c

--
1.8.5


^ permalink raw reply

* [PATCH] emulator/bthost: Fix sending L2CAP config req
From: Marcin Kraglak @ 2014-01-13 10:36 UTC (permalink / raw)
  To: linux-bluetooth

Send L2CAP config request with correct dcid field. It worked
well only if scid and dcid of L2CAP connection were the same.
---
 emulator/bthost.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/emulator/bthost.c b/emulator/bthost.c
index 96d375f..f3bd4c6 100644
--- a/emulator/bthost.c
+++ b/emulator/bthost.c
@@ -968,7 +968,7 @@ static bool l2cap_conn_req(struct bthost *bthost, struct btconn *conn,
 							le16_to_cpu(psm));
 
 		memset(&conf_req, 0, sizeof(conf_req));
-		conf_req.dcid = rsp.dcid;
+		conf_req.dcid = rsp.scid;
 
 		l2cap_sig_send(bthost, conn, BT_L2CAP_PDU_CONFIG_REQ, 0,
 						&conf_req, sizeof(conf_req));
-- 
1.8.3.1


^ permalink raw reply related

* [BlueZ v3 6/6] audio/A2DP: Add implemention of audio Suspend Stream command
From: Luiz Augusto von Dentz @ 2014-01-13 10:36 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389609361-27883-1-git-send-email-luiz.dentz@gmail.com>

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

---
 android/a2dp.c | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/android/a2dp.c b/android/a2dp.c
index 385c214..59761b9 100644
--- a/android/a2dp.c
+++ b/android/a2dp.c
@@ -809,8 +809,29 @@ failed:
 
 static void bt_stream_suspend(const void *buf, uint16_t len)
 {
-	DBG("Not Implemented");
+	const struct audio_cmd_suspend_stream *cmd = buf;
+	struct a2dp_setup *setup;
+	int err;
+
+	DBG("");
+
+	setup = find_setup(cmd->id);
+	if (!setup) {
+		error("Unable to find stream for endpoint %u", cmd->id);
+		goto failed;
+	}
+
+	err = avdtp_suspend(setup->dev->session, setup->stream);
+	if (err < 0) {
+		error("avdtp_suspend: %s", strerror(-err));
+		goto failed;
+	}
 
+	audio_ipc_send_rsp(AUDIO_OP_SUSPEND_STREAM, AUDIO_STATUS_SUCCESS);
+
+	return;
+
+failed:
 	audio_ipc_send_rsp(AUDIO_OP_SUSPEND_STREAM, AUDIO_STATUS_FAILED);
 }
 
-- 
1.8.4.2


^ permalink raw reply related

* [BlueZ v3 5/6] audio/A2DP: Add implemention of audio Resume Stream command
From: Luiz Augusto von Dentz @ 2014-01-13 10:36 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389609361-27883-1-git-send-email-luiz.dentz@gmail.com>

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

---
 android/a2dp.c | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/android/a2dp.c b/android/a2dp.c
index ca9260c..385c214 100644
--- a/android/a2dp.c
+++ b/android/a2dp.c
@@ -781,8 +781,29 @@ failed:
 
 static void bt_stream_resume(const void *buf, uint16_t len)
 {
-	DBG("Not Implemented");
+	const struct audio_cmd_resume_stream *cmd = buf;
+	struct a2dp_setup *setup;
+	int err;
+
+	DBG("");
 
+	setup = find_setup(cmd->id);
+	if (!setup) {
+		error("Unable to find stream for endpoint %u", cmd->id);
+		goto failed;
+	}
+
+	err = avdtp_start(setup->dev->session, setup->stream);
+	if (err < 0) {
+		error("avdtp_start: %s", strerror(-err));
+		goto failed;
+	}
+
+	audio_ipc_send_rsp(AUDIO_OP_RESUME_STREAM, AUDIO_STATUS_SUCCESS);
+
+	return;
+
+failed:
 	audio_ipc_send_rsp(AUDIO_OP_RESUME_STREAM, AUDIO_STATUS_FAILED);
 }
 
-- 
1.8.4.2


^ permalink raw reply related

* [BlueZ v3 4/6] audio/A2DP: Add implemention of audio Close Stream command
From: Luiz Augusto von Dentz @ 2014-01-13 10:35 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389609361-27883-1-git-send-email-luiz.dentz@gmail.com>

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

---
 android/a2dp.c | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/android/a2dp.c b/android/a2dp.c
index e0aab36..ca9260c 100644
--- a/android/a2dp.c
+++ b/android/a2dp.c
@@ -753,8 +753,29 @@ static void bt_stream_open(const void *buf, uint16_t len)
 
 static void bt_stream_close(const void *buf, uint16_t len)
 {
-	DBG("Not Implemented");
+	const struct audio_cmd_close_stream *cmd = buf;
+	struct a2dp_setup *setup;
+	int err;
 
+	DBG("");
+
+	setup = find_setup(cmd->id);
+	if (!setup) {
+		error("Unable to find stream for endpoint %u", cmd->id);
+		goto failed;
+	}
+
+	err = avdtp_close(setup->dev->session, setup->stream, FALSE);
+	if (err < 0) {
+		error("avdtp_close: %s", strerror(-err));
+		goto failed;
+	}
+
+	audio_ipc_send_rsp(AUDIO_OP_CLOSE_STREAM, AUDIO_STATUS_SUCCESS);
+
+	return;
+
+failed:
 	audio_ipc_send_rsp(AUDIO_OP_CLOSE_STREAM, AUDIO_STATUS_FAILED);
 }
 
-- 
1.8.4.2


^ permalink raw reply related

* [BlueZ v3 3/6] audio/A2DP: Add implemention of audio Open Stream command
From: Luiz Augusto von Dentz @ 2014-01-13 10:35 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389609361-27883-1-git-send-email-luiz.dentz@gmail.com>

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

---
 android/a2dp.c | 203 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 200 insertions(+), 3 deletions(-)

diff --git a/android/a2dp.c b/android/a2dp.c
index 88e43d6..e0aab36 100644
--- a/android/a2dp.c
+++ b/android/a2dp.c
@@ -37,6 +37,7 @@
 #include "lib/bluetooth.h"
 #include "lib/sdp.h"
 #include "lib/sdp_lib.h"
+#include "profiles/audio/a2dp-codecs.h"
 #include "log.h"
 #include "a2dp.h"
 #include "hal-msg.h"
@@ -53,6 +54,7 @@
 static GIOChannel *server = NULL;
 static GSList *devices = NULL;
 static GSList *endpoints = NULL;
+static GSList *setups = NULL;
 static bdaddr_t adapter_addr;
 static uint32_t record_id = 0;
 
@@ -67,6 +69,7 @@ struct a2dp_endpoint {
 	struct avdtp_local_sep *sep;
 	struct a2dp_preset *caps;
 	GSList *presets;
+	struct a2dp_config *config;
 };
 
 struct a2dp_device {
@@ -76,6 +79,13 @@ struct a2dp_device {
 	struct avdtp	*session;
 };
 
+struct a2dp_setup {
+	struct a2dp_device *dev;
+	struct a2dp_endpoint *endpoint;
+	struct a2dp_preset *preset;
+	struct avdtp_stream *stream;
+};
+
 static int device_cmp(gconstpointer s, gconstpointer user_data)
 {
 	const struct a2dp_device *dev = s;
@@ -397,7 +407,7 @@ static gboolean sep_getcap_ind(struct avdtp *session,
 					void *user_data)
 {
 	struct a2dp_endpoint *endpoint = user_data;
-	struct a2dp_preset *cap = endpoint->presets->data;
+	struct a2dp_preset *cap = endpoint->caps;
 	struct avdtp_service_capability *service;
 	struct avdtp_media_codec_capability *codec;
 
@@ -419,8 +429,162 @@ static gboolean sep_getcap_ind(struct avdtp *session,
 	return TRUE;
 }
 
+static int sbc_check_config(struct a2dp_endpoint *endpoint,
+						struct a2dp_preset *conf)
+{
+	a2dp_sbc_t *caps, *config;
+
+	if (conf->len != sizeof(a2dp_sbc_t)) {
+		error("SBC: Invalid configuration size (%u)", conf->len);
+		return -EINVAL;
+	}
+
+	caps = endpoint->caps->data;
+	config = conf->data;
+
+	if (!(caps->frequency & config->frequency)) {
+		error("SBC: Unsupported frequency (%u) by endpoint",
+							config->frequency);
+		return -EINVAL;
+	}
+
+	if (!(caps->channel_mode & config->channel_mode)) {
+		error("SBC: Unsupported channel mode (%u) by endpoint",
+							config->channel_mode);
+		return -EINVAL;
+	}
+
+	if (!(caps->block_length & config->block_length)) {
+		error("SBC: Unsupported block length (%u) by endpoint",
+							config->block_length);
+		return -EINVAL;
+	}
+
+	if (!(caps->allocation_method & config->allocation_method)) {
+		error("SBC: Unsupported allocation method (%u) by endpoint",
+							config->block_length);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int check_config(struct a2dp_endpoint *endpoint,
+						struct a2dp_preset *config)
+{
+	GSList *l;
+
+	for (l = endpoint->presets; l; l = g_slist_next(l)) {
+		struct a2dp_preset *preset = l->data;
+
+		if (preset->len != config->len)
+			continue;
+
+		if (memcmp(preset->data, config->data, preset->len) == 0)
+			return 0;
+	}
+
+	/* Codec specific */
+	switch (endpoint->codec) {
+	case A2DP_CODEC_SBC:
+		return sbc_check_config(endpoint, config);
+	default:
+		return -EINVAL;
+	}
+}
+
+static struct a2dp_device *find_device_by_session(struct avdtp *session)
+{
+	GSList *l;
+
+	for (l = devices; l; l = g_slist_next(l)) {
+		struct a2dp_device *dev = l->data;
+
+		if (dev->session == session)
+			return dev;
+	}
+
+	return NULL;
+}
+
+static void setup_free(void *data)
+{
+	struct a2dp_setup *setup = data;
+
+	preset_free(setup->preset);
+	g_free(setup);
+}
+
+static void setup_add(struct a2dp_device *dev, struct a2dp_endpoint *endpoint,
+			struct a2dp_preset *preset, struct avdtp_stream *stream)
+{
+	struct a2dp_setup *setup;
+
+	setup = g_new0(struct a2dp_setup, 1);
+	setup->dev = dev;
+	setup->endpoint = endpoint;
+	setup->preset = preset;
+	setup->stream = stream;
+	setups = g_slist_append(setups, setup);
+}
+
+static gboolean sep_setconf_ind(struct avdtp *session,
+						struct avdtp_local_sep *sep,
+						struct avdtp_stream *stream,
+						GSList *caps,
+						avdtp_set_configuration_cb cb,
+						void *user_data)
+{
+	struct a2dp_endpoint *endpoint = user_data;
+	struct a2dp_device *dev;
+	struct a2dp_preset *preset = NULL;
+
+	DBG("");
+
+	dev = find_device_by_session(session);
+	if (!dev) {
+		error("Unable to find device for session %p", session);
+		return FALSE;
+	}
+
+	for (; caps != NULL; caps = g_slist_next(caps)) {
+		struct avdtp_service_capability *cap = caps->data;
+		struct avdtp_media_codec_capability *codec;
+
+		if (cap->category == AVDTP_DELAY_REPORTING)
+			return FALSE;
+
+		if (cap->category != AVDTP_MEDIA_CODEC)
+			continue;
+
+		codec = (struct avdtp_media_codec_capability *) cap->data;
+
+		if (codec->media_codec_type != endpoint->codec)
+			return FALSE;
+
+		preset = g_new0(struct a2dp_preset, 1);
+		preset->len = cap->length - sizeof(*codec);
+		preset->data = g_memdup(codec->data, preset->len);
+
+		if (check_config(endpoint, preset) < 0) {
+			preset_free(preset);
+			return FALSE;
+		}
+	}
+
+	if (!preset)
+		return FALSE;
+
+	setup_add(dev, endpoint, preset, stream);
+
+	cb(session, stream, NULL);
+
+	return TRUE;
+}
+
 static struct avdtp_sep_ind sep_ind = {
 	.get_capability		= sep_getcap_ind,
+	.set_configuration	= sep_setconf_ind,
 };
 
 static uint8_t register_endpoint(const uint8_t *uuid, uint8_t codec,
@@ -550,11 +714,41 @@ static void bt_audio_close(const void *buf, uint16_t len)
 	audio_ipc_send_rsp(AUDIO_OP_CLOSE, AUDIO_STATUS_SUCCESS);
 }
 
+static struct a2dp_setup *find_setup(uint8_t id)
+{
+	GSList *l;
+
+	for (l = setups; l; l = g_slist_next(l)) {
+		struct a2dp_setup *setup = l->data;
+
+		if (setup->endpoint->id == id)
+			return setup;
+	}
+
+	return NULL;
+}
+
 static void bt_stream_open(const void *buf, uint16_t len)
 {
-	DBG("Not Implemented");
+	const struct audio_cmd_open_stream *cmd = buf;
+	struct audio_rsp_open_stream *rsp;
+	struct a2dp_setup *setup;
+
+	DBG("");
 
-	audio_ipc_send_rsp(AUDIO_OP_OPEN_STREAM, AUDIO_STATUS_FAILED);
+	setup = find_setup(cmd->id);
+	if (!setup) {
+		error("Unable to find stream for endpoint %u", cmd->id);
+		audio_ipc_send_rsp(AUDIO_OP_OPEN_STREAM, AUDIO_STATUS_FAILED);
+		return;
+	}
+
+	len = sizeof(*rsp) + setup->preset->len;
+	rsp = g_malloc0(sizeof(*rsp) + setup->preset->len);
+	rsp->preset->len = setup->preset->len;
+	memcpy(rsp->preset->data, setup->preset->data, setup->preset->len);
+
+	audio_ipc_send_rsp_full(AUDIO_OP_OPEN_STREAM, len, rsp, -1);
 }
 
 static void bt_stream_close(const void *buf, uint16_t len)
@@ -653,6 +847,9 @@ void bt_a2dp_unregister(void)
 {
 	DBG("");
 
+	g_slist_free_full(setups, setup_free);
+	setups = NULL;
+
 	g_slist_free_full(endpoints, unregister_endpoint);
 	endpoints = NULL;
 
-- 
1.8.4.2


^ permalink raw reply related

* [BlueZ v3 2/6] audio/A2DP: Add implemention of audio Close command
From: Luiz Augusto von Dentz @ 2014-01-13 10:35 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389609361-27883-1-git-send-email-luiz.dentz@gmail.com>

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

---
 android/a2dp.c | 30 ++++++++++++++++++++++++++++--
 1 file changed, 28 insertions(+), 2 deletions(-)

diff --git a/android/a2dp.c b/android/a2dp.c
index c7e3d8d..88e43d6 100644
--- a/android/a2dp.c
+++ b/android/a2dp.c
@@ -517,11 +517,37 @@ failed:
 	audio_ipc_send_rsp(AUDIO_OP_OPEN, AUDIO_STATUS_FAILED);
 }
 
+static struct a2dp_endpoint *find_endpoint(uint8_t id)
+{
+	GSList *l;
+
+	for (l = endpoints; l; l = g_slist_next(l)) {
+		struct a2dp_endpoint *endpoint = l->data;
+
+		if (endpoint->id == id)
+			return endpoint;
+	}
+
+	return NULL;
+}
+
 static void bt_audio_close(const void *buf, uint16_t len)
 {
-	DBG("Not Implemented");
+	const struct audio_cmd_close *cmd = buf;
+	struct a2dp_endpoint *endpoint;
+
+	DBG("");
+
+	endpoint = find_endpoint(cmd->id);
+	if (!endpoint) {
+		error("Unable to find endpoint %u", cmd->id);
+		audio_ipc_send_rsp(AUDIO_OP_CLOSE, AUDIO_STATUS_FAILED);
+		return;
+	}
+
+	unregister_endpoint(endpoint);
 
-	audio_ipc_send_rsp(AUDIO_OP_CLOSE, HAL_STATUS_FAILED);
+	audio_ipc_send_rsp(AUDIO_OP_CLOSE, AUDIO_STATUS_SUCCESS);
 }
 
 static void bt_stream_open(const void *buf, uint16_t len)
-- 
1.8.4.2


^ permalink raw reply related

* [BlueZ v3 1/6] audio/A2DP: Add implemention of audio Open command
From: Luiz Augusto von Dentz @ 2014-01-13 10:35 UTC (permalink / raw)
  To: linux-bluetooth

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

---
 android/a2dp.c | 161 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 160 insertions(+), 1 deletion(-)

diff --git a/android/a2dp.c b/android/a2dp.c
index b59c53d..c7e3d8d 100644
--- a/android/a2dp.c
+++ b/android/a2dp.c
@@ -52,9 +52,23 @@
 
 static GIOChannel *server = NULL;
 static GSList *devices = NULL;
+static GSList *endpoints = NULL;
 static bdaddr_t adapter_addr;
 static uint32_t record_id = 0;
 
+struct a2dp_preset {
+	void *data;
+	int8_t len;
+};
+
+struct a2dp_endpoint {
+	uint8_t id;
+	uint8_t codec;
+	struct avdtp_local_sep *sep;
+	struct a2dp_preset *caps;
+	GSList *presets;
+};
+
 struct a2dp_device {
 	bdaddr_t	dst;
 	uint8_t		state;
@@ -70,6 +84,29 @@ static int device_cmp(gconstpointer s, gconstpointer user_data)
 	return bacmp(&dev->dst, dst);
 }
 
+static void preset_free(void *data)
+{
+	struct a2dp_preset *preset = data;
+
+	g_free(preset->data);
+	g_free(preset);
+}
+
+static void unregister_endpoint(void *data)
+{
+	struct a2dp_endpoint *endpoint = data;
+
+	if (endpoint->sep)
+		avdtp_unregister_sep(endpoint->sep);
+
+	if (endpoint->caps)
+		preset_free(endpoint->caps);
+
+	g_slist_free_full(endpoint->presets, preset_free);
+
+	g_free(endpoint);
+}
+
 static void a2dp_device_free(struct a2dp_device *dev)
 {
 	if (dev->session)
@@ -354,10 +391,129 @@ static sdp_record_t *a2dp_record(void)
 	return record;
 }
 
+static gboolean sep_getcap_ind(struct avdtp *session,
+					struct avdtp_local_sep *sep,
+					GSList **caps, uint8_t *err,
+					void *user_data)
+{
+	struct a2dp_endpoint *endpoint = user_data;
+	struct a2dp_preset *cap = endpoint->presets->data;
+	struct avdtp_service_capability *service;
+	struct avdtp_media_codec_capability *codec;
+
+	*caps = NULL;
+
+	service = avdtp_service_cap_new(AVDTP_MEDIA_TRANSPORT, NULL, 0);
+	*caps = g_slist_append(*caps, service);
+
+	codec = g_malloc0(sizeof(*codec) + sizeof(cap->len));
+	codec->media_type = AVDTP_MEDIA_TYPE_AUDIO;
+	codec->media_codec_type = endpoint->codec;
+	memcpy(codec->data, cap->data, cap->len);
+
+	service = avdtp_service_cap_new(AVDTP_MEDIA_CODEC, codec,
+						sizeof(*codec) + cap->len);
+	*caps = g_slist_append(*caps, service);
+	g_free(codec);
+
+	return TRUE;
+}
+
+static struct avdtp_sep_ind sep_ind = {
+	.get_capability		= sep_getcap_ind,
+};
+
+static uint8_t register_endpoint(const uint8_t *uuid, uint8_t codec,
+							GSList *presets)
+{
+	struct a2dp_endpoint *endpoint;
+
+	/* FIXME: Add proper check for uuid */
+
+	endpoint = g_new0(struct a2dp_endpoint, 1);
+	endpoint->id = g_slist_length(endpoints) + 1;
+	endpoint->codec = codec;
+	endpoint->sep = avdtp_register_sep(AVDTP_SEP_TYPE_SOURCE,
+						AVDTP_MEDIA_TYPE_AUDIO,
+						codec, FALSE, &sep_ind, NULL,
+						endpoint);
+	endpoint->caps = g_slist_nth_data(presets->data, 0);
+	endpoint->presets = g_slist_copy(g_slist_nth(presets, 1));
+
+	endpoints = g_slist_append(endpoints, endpoint);
+
+	return endpoint->id;
+}
+
+static GSList *parse_presets(const struct audio_preset *p, uint8_t count,
+								uint16_t len)
+{
+	GSList *l = NULL;
+	uint8_t i;
+
+	for (i = 0; count > i; i++) {
+		const uint8_t *ptr = (const uint8_t *) p;
+		struct a2dp_preset *preset;
+
+		if (len < sizeof(struct audio_preset)) {
+			DBG("Invalid preset index %u", i);
+			g_slist_free_full(l, preset_free);
+			return NULL;
+		}
+
+		len -= sizeof(struct audio_preset);
+		if (len == 0 || len < p->len) {
+			DBG("Invalid preset size of %u for index %u", len, i);
+			g_slist_free_full(l, preset_free);
+			return NULL;
+		}
+
+		preset = g_new0(struct a2dp_preset, 1);
+		preset->len = p->len;
+		preset->data = g_memdup(p->data, preset->len);
+		l = g_slist_append(l, preset);
+
+		len -= preset->len;
+		ptr += sizeof(*p) + preset->len;
+		p = (const struct audio_preset *) ptr;
+	}
+
+	return l;
+}
+
 static void bt_audio_open(const void *buf, uint16_t len)
 {
-	DBG("Not Implemented");
+	const struct audio_cmd_open *cmd = buf;
+	struct audio_rsp_open rsp;
+	GSList *presets;
 
+	DBG("");
+
+	if (cmd->presets == 0) {
+		error("No audio presets found");
+		goto failed;
+	}
+
+	presets = parse_presets(cmd->preset, cmd->presets, len - sizeof(*cmd));
+	if (!presets) {
+		error("No audio presets found");
+		goto failed;
+	}
+
+	rsp.id = register_endpoint(cmd->uuid, cmd->codec, presets);
+	if (rsp.id == 0) {
+		g_slist_free_full(presets, preset_free);
+		error("Unable to register endpoint");
+		goto failed;
+	}
+
+	g_slist_free(presets);
+
+	audio_ipc_send_rsp_full(AUDIO_OP_OPEN, sizeof(rsp), &rsp, -1);
+
+	return;
+
+failed:
 	audio_ipc_send_rsp(AUDIO_OP_OPEN, AUDIO_STATUS_FAILED);
 }
 
@@ -471,6 +627,9 @@ void bt_a2dp_unregister(void)
 {
 	DBG("");
 
+	g_slist_free_full(endpoints, unregister_endpoint);
+	endpoints = NULL;
+
 	g_slist_foreach(devices, a2dp_device_disconnected, NULL);
 	devices = NULL;
 
-- 
1.8.4.2


^ permalink raw reply related

* Re: [PATCH] tools/bluetooth-player: check path validity
From: Luiz Augusto von Dentz @ 2014-01-13 10:15 UTC (permalink / raw)
  To: Sebastian Chlad; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <1389371461-11578-1-git-send-email-sebastianx.chlad@intel.com>

Hi Sebastian,

On Fri, Jan 10, 2014 at 6:31 PM, Sebastian Chlad
<sebastianx.chlad@intel.com> wrote:
> Bluetooth-player change-folder cmd approves any argument however it
> can be and then should a valid path only. Failing in providing
> a valid path crashes bluetooth-player thus argument should be
> checked if it's a valid path.
> ---
>  tools/bluetooth-player.c | 5 +++++
>  1 file changed, 5 insertions(+)
>
> diff --git a/tools/bluetooth-player.c b/tools/bluetooth-player.c
> index 2afdd17..f10d9be 100644
> --- a/tools/bluetooth-player.c
> +++ b/tools/bluetooth-player.c
> @@ -738,6 +738,11 @@ static void cmd_change_folder(int argc, char *argv[])
>                 return;
>         }
>
> +       if (dbus_validate_path(argv[1], NULL) == FALSE) {
> +               rl_printf("Not a valid path\n");
> +               return;
> +       }
> +
>         if (check_default_player() == FALSE)
>                 return;
>
> --
> 1.8.3.2

Pushed, thanks.


-- 
Luiz Augusto von Dentz

^ permalink raw reply

* Re: [PATCH 1/2] android/pics: Add PICS and PIXIT for AVRCP
From: Szymon Janc @ 2014-01-13 10:05 UTC (permalink / raw)
  To: Jakub Tyszkowski; +Cc: linux-bluetooth
In-Reply-To: <1389600696-32598-1-git-send-email-jakub.tyszkowski@tieto.com>

Hi Jakub,

On Monday 13 of January 2014 09:11:35 Jakub Tyszkowski wrote:
> Add PICS/PIXIT for AVRCP targeting Android 4.4.
> ---
>  android/Makefile.am     |   1 +
>  android/pics-avrcp.txt  | 626 ++++++++++++++++++++++++++++++++++++++++++++++++
>  android/pixit-avrcp.txt |  36 +++
>  3 files changed, 663 insertions(+)
>  create mode 100644 android/pics-avrcp.txt
>  create mode 100644 android/pixit-avrcp.txt

Both patches applied, thanks.

-- 
Best regards, 
Szymon Janc

^ permalink raw reply

* Re: [PATCH] android/pan: Generate file path in compile time
From: Szymon Janc @ 2014-01-13 10:00 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389604100-26189-1-git-send-email-szymon.janc@tieto.com>

Hi,

On Monday 13 of January 2014 10:08:20 Szymon Janc wrote:
> This reduce need of using snprintf function and removes need of manual
> buffer size calculation.
> ---
>  android/pan.c | 11 ++++-------
>  1 file changed, 4 insertions(+), 7 deletions(-)
> 
> diff --git a/android/pan.c b/android/pan.c
> index 205da71..dfd7762 100644
> --- a/android/pan.c
> +++ b/android/pan.c
> @@ -50,9 +50,9 @@
>  #include "bluetooth.h"
>  
>  #define SVC_HINT_NETWORKING 0x02
> -#define BNEP_BRIDGE	"bnep"
> -#define FORWARD_DELAY_PATH	"/sys/class/net/%s/bridge/forward_delay"
> -#define DELAY_PATH_MAX	41
> +
> +#define BNEP_BRIDGE "bnep"
> +#define FORWARD_DELAY_PATH "/sys/class/net/"BNEP_BRIDGE"/bridge/forward_delay"
>  
>  static bdaddr_t adapter_addr;
>  GSList *devices = NULL;
> @@ -470,11 +470,8 @@ failed:
>  static int set_forward_delay(void)
>  {
>  	int fd, ret;
> -	char path[DELAY_PATH_MAX];
> -
> -	snprintf(path, sizeof(path), FORWARD_DELAY_PATH, BNEP_BRIDGE);
>  
> -	fd = open(path, O_RDWR);
> +	fd = open(FORWARD_DELAY_PATH, O_RDWR);
>  	if (fd < 0)
>  		return -errno;
>

This is now upstream.

-- 
Best regards, 
Szymon Janc

^ permalink raw reply

* Re: [PATCH BlueZ 3/6] audio/A2DP: Add implemention of audio Open Stream command
From: Lukasz Rymanowski @ 2014-01-13  9:38 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <CABBYNZ+pfaxs8=0eO6w7e3DRmCGyA2wLJpANscCMpLgXOAo_7A@mail.gmail.com>

Hi Luiz,

On Mon, Jan 13, 2014 at 8:55 AM, Luiz Augusto von Dentz
<luiz.dentz@gmail.com> wrote:
> Hi Lukasz,
>
> On Mon, Jan 13, 2014 at 2:10 AM, Lukasz Rymanowski
> <lukasz.rymanowski@gmail.com> wrote:
>> Hi Luiz,
>>
>> On Sat, Jan 11, 2014 at 11:13 AM, Luiz Augusto von Dentz
>> <luiz.dentz@gmail.com> wrote:
>>> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
>>>
>>> ---
>>>  android/a2dp.c | 199 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>>>  1 file changed, 197 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/android/a2dp.c b/android/a2dp.c
>>> index 8649cf3..479cb71 100644
>>> --- a/android/a2dp.c
>>> +++ b/android/a2dp.c
>>> @@ -37,6 +37,7 @@
>>>  #include "lib/bluetooth.h"
>>>  #include "lib/sdp.h"
>>>  #include "lib/sdp_lib.h"
>>> +#include "profiles/audio/a2dp-codecs.h"
>>
>> We need to discuss how we gonna use structs from this file in
>> hal-audio (eg. a2dp_sbc_t). Maybe we should have some special file
>> with audio structs/defines for IPC only? Then you could copy data to
>> structs you need.
>
> Not sure what you mean about this header, its LGPL already so I see no
> problem of including it in hal-audio.

You are right, it is LGPL so no problem.

\Lukasz

^ permalink raw reply

* Re: [PATCH] avrcp: Remove dead code
From: Luiz Augusto von Dentz @ 2014-01-13  9:08 UTC (permalink / raw)
  To: Andrei Emeltchenko; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <1389365780-20136-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

Hi Andrei,

On Fri, Jan 10, 2014 at 4:56 PM, Andrei Emeltchenko
<Andrei.Emeltchenko.news@gmail.com> wrote:
> From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
>
> session->target cannot be NULL since it is already checked 11 lines
> above:
> ...
>         if (session == NULL || session->target == NULL)
>                 return -ENOTCONN;
> ...
> ---
>  profiles/audio/avrcp.c | 24 ++++--------------------
>  1 file changed, 4 insertions(+), 20 deletions(-)
>
> diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c
> index 8d4309a..197959f 100644
> --- a/profiles/audio/avrcp.c
> +++ b/profiles/audio/avrcp.c
> @@ -3722,30 +3722,14 @@ int avrcp_set_volume(struct btd_device *dev, uint8_t volume)
>
>         DBG("volume=%u", volume);
>
> -       if (session->target) {
> -               pdu->pdu_id = AVRCP_SET_ABSOLUTE_VOLUME;
> -               pdu->params[0] = volume;
> -               pdu->params_len = htons(1);
> +       pdu->pdu_id = AVRCP_SET_ABSOLUTE_VOLUME;
> +       pdu->params[0] = volume;
> +       pdu->params_len = htons(1);
>
> -               return avctp_send_vendordep_req(session->conn,
> +       return avctp_send_vendordep_req(session->conn,
>                                         AVC_CTYPE_CONTROL, AVC_SUBUNIT_PANEL,
>                                         buf, sizeof(buf),
>                                         avrcp_handle_set_volume, session);
> -       } else if (session->registered_events &
> -                                       (1 << AVRCP_EVENT_VOLUME_CHANGED)) {
> -               uint8_t id = AVRCP_EVENT_VOLUME_CHANGED;
> -               pdu->pdu_id = AVRCP_REGISTER_NOTIFICATION;
> -               pdu->params[0] = AVRCP_EVENT_VOLUME_CHANGED;
> -               pdu->params[1] = volume;
> -               pdu->params_len = htons(2);
> -
> -               return avctp_send_vendordep(session->conn,
> -                                       session->transaction_events[id],
> -                                       AVC_CTYPE_CHANGED, AVC_SUBUNIT_PANEL,
> -                                       buf, sizeof(buf));
> -       }

The above code is necessary to notify volume changes when acting as
controller (session->control is set), so your fix is not good either
and we should depend on session->target on the first place because
both session->control and session->target can be set.

^ permalink raw reply

* [PATCH] android/pan: Generate file path in compile time
From: Szymon Janc @ 2014-01-13  9:08 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

This reduce need of using snprintf function and removes need of manual
buffer size calculation.
---
 android/pan.c | 11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/android/pan.c b/android/pan.c
index 205da71..dfd7762 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -50,9 +50,9 @@
 #include "bluetooth.h"
 
 #define SVC_HINT_NETWORKING 0x02
-#define BNEP_BRIDGE	"bnep"
-#define FORWARD_DELAY_PATH	"/sys/class/net/%s/bridge/forward_delay"
-#define DELAY_PATH_MAX	41
+
+#define BNEP_BRIDGE "bnep"
+#define FORWARD_DELAY_PATH "/sys/class/net/"BNEP_BRIDGE"/bridge/forward_delay"
 
 static bdaddr_t adapter_addr;
 GSList *devices = NULL;
@@ -470,11 +470,8 @@ failed:
 static int set_forward_delay(void)
 {
 	int fd, ret;
-	char path[DELAY_PATH_MAX];
-
-	snprintf(path, sizeof(path), FORWARD_DELAY_PATH, BNEP_BRIDGE);
 
-	fd = open(path, O_RDWR);
+	fd = open(FORWARD_DELAY_PATH, O_RDWR);
 	if (fd < 0)
 		return -errno;
 
-- 
1.8.3.2


^ permalink raw reply related

* Re: [PATCH 1/2] tools: Fix build error in seq2bseq
From: Johan Hedberg @ 2014-01-13  8:48 UTC (permalink / raw)
  To: Szymon Janc; +Cc: linux-bluetooth
In-Reply-To: <1389600554-20669-1-git-send-email-szymon.janc@tieto.com>

Hi Szymon,

On Mon, Jan 13, 2014, Szymon Janc wrote:
> Don't ignore return value of write. This fix following build error on
> Ubuntu:
> 
> tools/seq2bseq.c: In function ‘convert_line’:
> tools/seq2bseq.c:52:8: error: ignoring return value of ‘write’,
>      declared with attribute warn_unused_result [-Werror=unused-result]
>    write(fd, &val, 1);
> ---
>  tools/seq2bseq.c | 10 +++++++---
>  1 file changed, 7 insertions(+), 3 deletions(-)

Both patches have been applied. Thanks.

Johan

^ permalink raw reply

* Re: [PATCH] android-tester: Add possibility to debug mgmt
From: Johan Hedberg @ 2014-01-13  8:45 UTC (permalink / raw)
  To: Marcin Kraglak; +Cc: linux-bluetooth
In-Reply-To: <1389360214-31932-1-git-send-email-marcin.kraglak@tieto.com>

Hi Marcin,

On Fri, Jan 10, 2014, Marcin Kraglak wrote:
> Print mgmt debug info if debug flag is set in android-tester.
> ---
>  android/android-tester.c | 15 ++++++++++++---
>  1 file changed, 12 insertions(+), 3 deletions(-)

Applied. Thanks.

Johan

^ permalink raw reply

* Re: [PATCH] btproxy: Fix double close
From: Johan Hedberg @ 2014-01-13  8:42 UTC (permalink / raw)
  To: Andrei Emeltchenko; +Cc: linux-bluetooth
In-Reply-To: <1389258082-10847-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

Hi Andrei,

On Thu, Jan 09, 2014, Andrei Emeltchenko wrote:
> setup_streams() already makes close()
> ---
>  tools/btproxy.c | 5 +----
>  1 file changed, 1 insertion(+), 4 deletions(-)

Applied. Thanks.

Johan

^ permalink raw reply

* Re: [PATCH] android/pts: Update PTS results for MAP
From: Johan Hedberg @ 2014-01-13  8:40 UTC (permalink / raw)
  To: Jakub Tyszkowski; +Cc: linux-bluetooth
In-Reply-To: <1389171173-30512-1-git-send-email-jakub.tyszkowski@tieto.com>

Hi Jakub,

On Wed, Jan 08, 2014, Jakub Tyszkowski wrote:
> Update MAP PTS results for BlueZ stack on Nexus4 (Android 4.4.2).
> ---
>  android/pts-map.txt | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)

Applied. Thanks.

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