Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCHv2 2/8] android/ipc-tester: Run daemon in separate process
From: Jakub Tyszkowski @ 2014-01-14 12:14 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389701685-1861-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.2


^ permalink raw reply related

* [PATCHv2 1/8] android/ipc-tester: Skeleton for ipc negative tester
From: Jakub Tyszkowski @ 2014-01-14 12:14 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389701685-1861-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 ac76fe2..d790fd2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -113,4 +113,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.2


^ permalink raw reply related

* [PATCHv2 0/8] IPC negative tester
From: Jakub Tyszkowski @ 2014-01-14 12:14 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.

V2 changes:
	* fixed few indentation issues
	* fixed missing __attribute__((packed))
	* fixed amount of data written for 'malformed data' test case
	* fixed opcode for 'invalid service' test case
	* added patch(8) with more 'malformed data' cases

Jakub Tyszkowski (8):
  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
  androi/ipc-tester: Add more cases for malformed data

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

--
1.8.5.2


^ permalink raw reply

* [PATCH BlueZ 2/2] android/A2DP: Connect transport channel when initiator
From: Luiz Augusto von Dentz @ 2014-01-14 11:48 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389700090-3642-1-git-send-email-luiz.dentz@gmail.com>

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

This connects transport channel when initiator of open request.
---
 android/a2dp.c | 51 +++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 39 insertions(+), 12 deletions(-)

diff --git a/android/a2dp.c b/android/a2dp.c
index aab0940..7b76cf3 100644
--- a/android/a2dp.c
+++ b/android/a2dp.c
@@ -141,6 +141,25 @@ static struct a2dp_device *a2dp_device_new(const bdaddr_t *dst)
 	return dev;
 }
 
+static bool a2dp_device_connect(struct a2dp_device *dev, BtIOConnect cb)
+{
+	GError *err = NULL;
+
+	dev->io = bt_io_connect(cb, dev, NULL, &err,
+					BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
+					BT_IO_OPT_DEST_BDADDR, &dev->dst,
+					BT_IO_OPT_PSM, L2CAP_PSM_AVDTP,
+					BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
+					BT_IO_OPT_INVALID);
+	if (err) {
+		error("%s", err->message);
+		g_error_free(err);
+		return false;
+	}
+
+	return true;
+}
+
 static void bt_a2dp_notify_state(struct a2dp_device *dev, uint8_t state)
 {
 	struct hal_ev_a2dp_conn_state ev;
@@ -398,7 +417,6 @@ static void bt_a2dp_connect(const void *buf, uint16_t len)
 	char addr[18];
 	bdaddr_t dst;
 	GSList *l;
-	GError *err = NULL;
 
 	DBG("");
 
@@ -411,15 +429,7 @@ static void bt_a2dp_connect(const void *buf, uint16_t len)
 	}
 
 	dev = a2dp_device_new(&dst);
-	dev->io = bt_io_connect(signaling_connect_cb, dev, NULL, &err,
-					BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
-					BT_IO_OPT_DEST_BDADDR, &dev->dst,
-					BT_IO_OPT_PSM, L2CAP_PSM_AVDTP,
-					BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
-					BT_IO_OPT_INVALID);
-	if (err) {
-		error("%s", err->message);
-		g_error_free(err);
+	if (!a2dp_device_connect(dev, signaling_connect_cb)) {
 		a2dp_device_free(dev);
 		status = HAL_STATUS_FAILED;
 		goto failed;
@@ -529,6 +539,11 @@ static void transport_connect_cb(GIOChannel *chan, GError *err,
 	}
 
 	g_io_channel_set_close_on_unref(chan, FALSE);
+
+	if (dev->io) {
+		g_io_channel_unref(dev->io);
+		dev->io = NULL;
+	}
 }
 
 static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
@@ -928,12 +943,24 @@ static void sep_open_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
 			void *user_data)
 {
 	struct a2dp_endpoint *endpoint = user_data;
+	struct a2dp_device *dev;
 
 	DBG("");
 
-	if (!err)
-		return;
+	if (err)
+		goto failed;
 
+	dev = find_device_by_session(session);
+	if (!dev) {
+		error("Unable to find device for session");
+		goto failed;
+	}
+
+	a2dp_device_connect(dev, transport_connect_cb);
+
+	return;
+
+failed:
 	setup_remove_by_id(endpoint->id);
 }
 
-- 
1.8.4.2


^ permalink raw reply related

* [PATCH BlueZ 1/2] android/A2DP: Add handling of incoming transport connection
From: Luiz Augusto von Dentz @ 2014-01-14 11:48 UTC (permalink / raw)
  To: linux-bluetooth

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

This adds handling of incoming transport connection attempt.
---
 android/a2dp.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 60 insertions(+), 4 deletions(-)

diff --git a/android/a2dp.c b/android/a2dp.c
index 9f3164a..aab0940 100644
--- a/android/a2dp.c
+++ b/android/a2dp.c
@@ -477,6 +477,60 @@ static const struct ipc_handler cmd_handlers[] = {
 	{ bt_a2dp_disconnect, false, sizeof(struct hal_cmd_a2dp_disconnect) },
 };
 
+static struct a2dp_setup *find_setup_by_device(struct a2dp_device *dev)
+{
+	GSList *l;
+
+	for (l = setups; l; l = g_slist_next(l)) {
+		struct a2dp_setup *setup = l->data;
+
+		if (setup->dev == dev)
+			return setup;
+	}
+
+	return NULL;
+}
+
+static void transport_connect_cb(GIOChannel *chan, GError *err,
+							gpointer user_data)
+{
+	struct a2dp_device *dev = user_data;
+	struct a2dp_setup *setup;
+	uint16_t imtu, omtu;
+	GError *gerr = NULL;
+	int fd;
+
+	if (err) {
+		error("%s", err->message);
+		return;
+	}
+
+	setup = find_setup_by_device(dev);
+	if (!setup) {
+		error("Unable to find stream setup");
+		return;
+	}
+
+	bt_io_get(chan, &gerr,
+			BT_IO_OPT_IMTU, &imtu,
+			BT_IO_OPT_OMTU, &omtu,
+			BT_IO_OPT_INVALID);
+	if (gerr) {
+		error("%s", gerr->message);
+		g_error_free(gerr);
+		return;
+	}
+
+	fd = g_io_channel_unix_get_fd(chan);
+
+	if (!avdtp_stream_set_transport(setup->stream, fd, imtu, omtu)) {
+		error("avdtp_stream_set_transport: failed");
+		return;
+	}
+
+	g_io_channel_set_close_on_unref(chan, FALSE);
+}
+
 static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
 {
 	struct a2dp_device *dev;
@@ -501,13 +555,15 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
 		return;
 	}
 
-	l = g_slist_find_custom(devices, &dst, device_cmp);
-	if (l)
-		return;
-
 	ba2str(&dst, address);
 	DBG("Incoming connection from %s", address);
 
+	l = g_slist_find_custom(devices, &dst, device_cmp);
+	if (l) {
+		transport_connect_cb(chan, err, l->data);
+		return;
+	}
+
 	dev = a2dp_device_new(&dst);
 	signaling_connect_cb(chan, err, dev);
 }
-- 
1.8.4.2


^ permalink raw reply related

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

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.

Johan

^ permalink raw reply

* Re: [PATCH] android/README: Update documentation with AOSP 4.4
From: Johan Hedberg @ 2014-01-14 11:26 UTC (permalink / raw)
  To: Szymon Janc; +Cc: linux-bluetooth
In-Reply-To: <1389653228-5285-1-git-send-email-szymon.janc@gmail.com>

Hi Szymon,

On Mon, Jan 13, 2014, Szymon Janc wrote:
> This includes:
>  - sample repository to AOSP 4.4 based repository with support for
>    Nexus 4 and Nexus 7 2013 devices.
>  - adds info about snoop service
>  - other random additions
> ---
>  android/README | 71 +++++++++++++++++++++++++++++++++++++++++-----------------
>  1 file changed, 50 insertions(+), 21 deletions(-)

Applied. Thanks.

Johan

^ permalink raw reply

* Re: [PATCH] l2test: Use correct buffer size
From: Johan Hedberg @ 2014-01-14 11:26 UTC (permalink / raw)
  To: Andrei Emeltchenko; +Cc: linux-bluetooth
In-Reply-To: <1389631184-32758-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

Hi Andrei,

On Mon, Jan 13, 2014, Andrei Emeltchenko wrote:
> ---
>  tools/l2test.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)

Applied. Thanks.

Johan

^ permalink raw reply

* Re: [PATCH] scotest: Use correct buffer size
From: Johan Hedberg @ 2014-01-14 11:25 UTC (permalink / raw)
  To: Andrei Emeltchenko; +Cc: linux-bluetooth
In-Reply-To: <1389630885-32676-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

Hi Andrei,

On Mon, Jan 13, 2014, Andrei Emeltchenko wrote:
> ---
>  tools/scotest.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)

Applied. Thanks.

Johan

^ permalink raw reply

* [RFC 5/5] android/bluetooth: Add support for loading caches devices from storage
From: Szymon Janc @ 2014-01-14 11:11 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1389697905-18532-1-git-send-email-szymon.janc@tieto.com>

Info is now stored for all devices and bond state depends on linkkey
being stored. Based on that devices loaded from storage are put either
to cache or to bonded_devices list.
---
 android/bluetooth.c | 27 +++++++++++++++++++++++----
 1 file changed, 23 insertions(+), 4 deletions(-)

diff --git a/android/bluetooth.c b/android/bluetooth.c
index df442a3..dfbbe1a 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -1695,7 +1695,8 @@ static void clear_uuids(void)
 					sizeof(cp), &cp, NULL, NULL, NULL);
 }
 
-static void create_device_from_info(GKeyFile *key_file, const char *peer)
+static struct device *create_device_from_info(GKeyFile *key_file,
+							const char *peer)
 {
 	struct device *dev;
 	uint8_t type;
@@ -1710,7 +1711,7 @@ static void create_device_from_info(GKeyFile *key_file, const char *peer)
 	str2ba(peer, &bdaddr);
 	dev = create_device(&bdaddr, type);
 
-	dev->bond_state = HAL_BOND_STATE_BONDED;
+	dev->bond_state = HAL_BOND_STATE_NONE;
 
 	str = g_key_file_get_string(key_file, peer, "Name", NULL);
 	if (str) {
@@ -1746,6 +1747,8 @@ static void create_device_from_info(GKeyFile *key_file, const char *peer)
 
 		g_strfreev(uuids);
 	}
+
+	return dev;
 }
 
 static struct mgmt_link_key_info *get_key_info(GKeyFile *key_file, const char *peer)
@@ -1778,6 +1781,14 @@ failed:
 	return info;
 }
 
+static int device_timestamp_cmp(gconstpointer  a, gconstpointer  b)
+{
+	const struct device *deva = a;
+	const struct device *devb = b;
+
+	return deva->timestamp < devb->timestamp;
+}
+
 static void load_devices_info(bt_bluetooth_ready cb)
 {
 	GKeyFile *key_file;
@@ -1794,16 +1805,24 @@ static void load_devices_info(bt_bluetooth_ready cb)
 
 	for (i = 0; i < len; i++) {
 		struct mgmt_link_key_info *key_info;
+		struct device *dev;
 
-		create_device_from_info(key_file, devs[i]);
+		dev = create_device_from_info(key_file, devs[i]);
 
 		key_info = get_key_info(key_file, devs[i]);
-		if (key_info)
+		if (key_info) {
 			keys = g_slist_prepend(keys, key_info);
+			bonded_devices = g_slist_prepend(bonded_devices, dev);
+			dev->bond_state = HAL_BOND_STATE_BONDED;
+		} else {
+			devices = g_slist_prepend(devices, dev);
+		}
 
 		/* TODO ltk */
 	}
 
+	devices = g_slist_sort(devices, device_timestamp_cmp);
+
 	load_link_keys(keys, cb);
 	g_strfreev(devs);
 	g_slist_free_full(keys, g_free);
-- 
1.8.3.2


^ permalink raw reply related

* [RFC 4/5] android/bluetooth: Add support for caching remote device info
From: Szymon Janc @ 2014-01-14 11:11 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1389697905-18532-1-git-send-email-szymon.janc@tieto.com>

Cache is limited to DEVICES_CACHE_MAX. Devices are sorted with
timestamp so if cache is full olderst device is removed.
---
 android/bluetooth.c | 69 ++++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 55 insertions(+), 14 deletions(-)

diff --git a/android/bluetooth.c b/android/bluetooth.c
index 8c91d87..df442a3 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -70,6 +70,8 @@
 /* Default discoverable timeout 120sec as in Android */
 #define DEFAULT_DISCOVERABLE_TIMEOUT 120
 
+#define DEVICES_CACHE_MAX 100
+
 #define BASELEN_PROP_CHANGED (sizeof(struct hal_ev_adapter_props_changed) \
 					+ (sizeof(struct hal_property)))
 
@@ -261,6 +263,27 @@ static void store_device_info(struct device *dev)
 	g_strfreev(uuids);
 }
 
+static void remove_device_info(struct device *dev)
+{
+	GKeyFile *key_file;
+	gsize length = 0;
+	char addr[18];
+	char *str;
+
+	ba2str(&dev->bdaddr, addr);
+
+	key_file = g_key_file_new();
+	g_key_file_load_from_file(key_file, DEVICES_FILE, 0, NULL);
+
+	g_key_file_remove_group(key_file, addr, NULL);
+
+	str = g_key_file_to_data(key_file, &length, NULL);
+	g_file_set_contents(DEVICES_FILE, str, length, NULL);
+	g_free(str);
+
+	g_key_file_free(key_file);
+}
+
 static int device_match(gconstpointer a, gconstpointer b)
 {
 	const struct device *dev = a;
@@ -284,6 +307,34 @@ static struct device *find_device(const bdaddr_t *bdaddr)
 	return NULL;
 }
 
+static void free_device(struct device *dev)
+{
+	g_free(dev->name);
+	g_free(dev->friendly_name);
+	g_slist_free_full(dev->uuids, g_free);
+	g_free(dev);
+}
+
+static void cache_device(struct device *new_dev)
+{
+	struct device *dev;
+	GSList *l;
+
+	if (g_slist_length(devices) < DEVICES_CACHE_MAX)
+		goto done;
+
+	l = g_slist_last(devices);
+	dev = l->data;
+
+	devices = g_slist_remove(bonded_devices, dev);
+	remove_device_info(dev);
+	free_device(dev);
+
+done:
+	devices = g_slist_prepend(devices, new_dev);
+	store_device_info(new_dev);
+}
+
 static struct device *create_device(const bdaddr_t *bdaddr, uint8_t type)
 {
 	struct device *dev;
@@ -302,19 +353,10 @@ static struct device *create_device(const bdaddr_t *bdaddr, uint8_t type)
 	/* use address for name, will be change if one is present
 	 * eg. in EIR or set by set_property. */
 	dev->name = g_strdup(addr);
-	devices = g_slist_prepend(devices, dev);
 
 	return dev;
 }
 
-static void free_device(struct device *dev)
-{
-	g_free(dev->name);
-	g_free(dev->friendly_name);
-	g_slist_free_full(dev->uuids, g_free);
-	g_free(dev);
-}
-
 static struct device *get_device(const bdaddr_t *bdaddr, uint8_t type)
 {
 	struct device *dev;
@@ -586,7 +628,8 @@ static void set_device_bond_state(const bdaddr_t *addr, uint8_t status,
 	case HAL_BOND_STATE_NONE:
 		if (dev->bond_state == HAL_BOND_STATE_BONDED) {
 			bonded_devices = g_slist_remove(bonded_devices, dev);
-			devices = g_slist_prepend(devices, dev);
+			remove_stored_link_key(&dev->bdaddr);
+			cache_device(dev);
 		}
 		break;
 	case HAL_BOND_STATE_BONDED:
@@ -600,8 +643,6 @@ static void set_device_bond_state(const bdaddr_t *addr, uint8_t status,
 
 	dev->bond_state = state;
 
-	store_device_info(dev);
-
 	send_bond_state_change(&dev->bdaddr, status, state);
 }
 
@@ -1107,6 +1148,8 @@ static void update_found_device(const bdaddr_t *bdaddr, uint8_t bdaddr_type,
 		(*num_prop)++;
 	}
 
+	cache_device(dev);
+
 	ipc_send_notif(HAL_SERVICE_ID_BLUETOOTH, opcode, size, buf);
 
 	if (confirm) {
@@ -2463,8 +2506,6 @@ static void unpair_device_complete(uint8_t status, uint16_t length,
 	if (status != MGMT_STATUS_SUCCESS)
 		return;
 
-	remove_stored_link_key(&rp->addr.bdaddr);
-
 	set_device_bond_state(&rp->addr.bdaddr, HAL_STATUS_SUCCESS,
 							HAL_BOND_STATE_NONE);
 }
-- 
1.8.3.2


^ permalink raw reply related

* [RFC 3/5] android/bluetooth: Always store device info
From: Szymon Janc @ 2014-01-14 11:11 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1389697905-18532-1-git-send-email-szymon.janc@tieto.com>

This allows to cache remote device informations.
---
 android/bluetooth.c | 42 +++++++++++++++++++++++++++++-------------
 1 file changed, 29 insertions(+), 13 deletions(-)

diff --git a/android/bluetooth.c b/android/bluetooth.c
index 23a528a..8c91d87 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -208,23 +208,11 @@ static void store_device_info(struct device *dev)
 	char **uuids = NULL;
 	char *str;
 
-	/* We only store bonded devices and need to modify the storage
-	 * if the state is either NONE or BONDED.
-	 */
-	if (dev->bond_state != HAL_BOND_STATE_BONDED &&
-					dev->bond_state != HAL_BOND_STATE_NONE)
-		return;
-
 	ba2str(&dev->bdaddr, addr);
 
 	key_file = g_key_file_new();
 	g_key_file_load_from_file(key_file, DEVICES_FILE, 0, NULL);
 
-	if (dev->bond_state == HAL_BOND_STATE_NONE) {
-		g_key_file_remove_group(key_file, addr, NULL);
-		goto done;
-	}
-
 	g_key_file_set_integer(key_file, addr, "Type", dev->bdaddr_type);
 
 	g_key_file_set_string(key_file, addr, "Name", dev->name);
@@ -265,7 +253,6 @@ static void store_device_info(struct device *dev)
 		g_key_file_remove_key(key_file, addr, "Services", NULL);
 	}
 
-done:
 	str = g_key_file_to_data(key_file, &length, NULL);
 	g_file_set_contents(DEVICES_FILE, str, length, NULL);
 	g_free(str);
@@ -543,6 +530,33 @@ static void store_link_key(const bdaddr_t *dst, const uint8_t *key,
 	g_key_file_free(key_file);
 }
 
+static void remove_stored_link_key(const bdaddr_t *dst)
+{
+	GKeyFile *key_file;
+	gsize length = 0;
+	char addr[18];
+	char *data;
+
+	key_file = g_key_file_new();
+
+	if (!g_key_file_load_from_file(key_file, DEVICES_FILE, 0, NULL))
+		return;
+
+	ba2str(dst, addr);
+
+	DBG("%s", addr);
+
+	g_key_file_remove_key(key_file, addr, "LinkKey", NULL);
+	g_key_file_remove_key(key_file, addr, "LinkKeyType", NULL);
+	g_key_file_remove_key(key_file, addr, "LinkKeyPinLength", NULL);
+
+	data = g_key_file_to_data(key_file, &length, NULL);
+	g_file_set_contents(DEVICES_FILE, data, length, NULL);
+	g_free(data);
+
+	g_key_file_free(key_file);
+}
+
 static void send_bond_state_change(const bdaddr_t *addr, uint8_t status,
 								uint8_t state)
 {
@@ -2449,6 +2463,8 @@ static void unpair_device_complete(uint8_t status, uint16_t length,
 	if (status != MGMT_STATUS_SUCCESS)
 		return;
 
+	remove_stored_link_key(&rp->addr.bdaddr);
+
 	set_device_bond_state(&rp->addr.bdaddr, HAL_STATUS_SUCCESS,
 							HAL_BOND_STATE_NONE);
 }
-- 
1.8.3.2


^ permalink raw reply related

* [RFC 2/5] android/bluetooth: Use defines for settings and devices files paths
From: Szymon Janc @ 2014-01-14 11:11 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1389697905-18532-1-git-send-email-szymon.janc@tieto.com>

From: Szymon Janc <szymon.janc@gmail.com>

---
 android/bluetooth.c | 24 +++++++++++-------------
 1 file changed, 11 insertions(+), 13 deletions(-)

diff --git a/android/bluetooth.c b/android/bluetooth.c
index 78e98c1..23a528a 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -54,6 +54,9 @@
 
 #define DUT_MODE_FILE "/sys/kernel/debug/bluetooth/hci%u/dut_mode"
 
+#define SETTINGS_FILE ANDROID_STORAGEDIR"/settings"
+#define DEVICES_FILE ANDROID_STORAGEDIR"/devices"
+
 #define DEVICE_ID_SOURCE	0x0002	/* USB */
 #define DEVICE_ID_VENDOR	0x1d6b	/* Linux Foundation */
 #define DEVICE_ID_PRODUCT	0x0247	/* BlueZ for Android */
@@ -149,8 +152,7 @@ static void store_adapter_config(void)
 
 	key_file = g_key_file_new();
 
-	g_key_file_load_from_file(key_file, ANDROID_STORAGEDIR"/settings", 0,
-									NULL);
+	g_key_file_load_from_file(key_file, SETTINGS_FILE, 0, NULL);
 
 	ba2str(&adapter.bdaddr, addr);
 
@@ -161,7 +163,7 @@ static void store_adapter_config(void)
 
 	data = g_key_file_to_data(key_file, &length, NULL);
 
-	g_file_set_contents(ANDROID_STORAGEDIR"/settings", data, length, NULL);
+	g_file_set_contents(SETTINGS_FILE, data, length, NULL);
 
 	g_free(data);
 	g_key_file_free(key_file);
@@ -174,8 +176,7 @@ static void load_adapter_config(void)
 	char *str;
 
 	key_file = g_key_file_new();
-	g_key_file_load_from_file(key_file, ANDROID_STORAGEDIR"/settings", 0,
-									NULL);
+	g_key_file_load_from_file(key_file, SETTINGS_FILE, 0, NULL);
 
 	str = g_key_file_get_string(key_file, "General", "Address", NULL);
 	if (!str) {
@@ -217,8 +218,7 @@ static void store_device_info(struct device *dev)
 	ba2str(&dev->bdaddr, addr);
 
 	key_file = g_key_file_new();
-	g_key_file_load_from_file(key_file, ANDROID_STORAGEDIR"/devices", 0,
-									NULL);
+	g_key_file_load_from_file(key_file, DEVICES_FILE, 0, NULL);
 
 	if (dev->bond_state == HAL_BOND_STATE_NONE) {
 		g_key_file_remove_group(key_file, addr, NULL);
@@ -267,7 +267,7 @@ static void store_device_info(struct device *dev)
 
 done:
 	str = g_key_file_to_data(key_file, &length, NULL);
-	g_file_set_contents(ANDROID_STORAGEDIR"/devices", str, length, NULL);
+	g_file_set_contents(DEVICES_FILE, str, length, NULL);
 	g_free(str);
 
 	g_key_file_free(key_file);
@@ -522,8 +522,7 @@ static void store_link_key(const bdaddr_t *dst, const uint8_t *key,
 
 	key_file = g_key_file_new();
 
-	if (!g_key_file_load_from_file(key_file, ANDROID_STORAGEDIR"/devices",
-								0, NULL))
+	if (!g_key_file_load_from_file(key_file, DEVICES_FILE, 0, NULL))
 		return;
 
 	ba2str(dst, addr);
@@ -538,7 +537,7 @@ static void store_link_key(const bdaddr_t *dst, const uint8_t *key,
 	g_key_file_set_integer(key_file, addr, "LinkKeyPinLength", pin_length);
 
 	data = g_key_file_to_data(key_file, &length, NULL);
-	g_file_set_contents(ANDROID_STORAGEDIR"/devices", data, length, NULL);
+	g_file_set_contents(DEVICES_FILE, data, length, NULL);
 	g_free(data);
 
 	g_key_file_free(key_file);
@@ -1732,8 +1731,7 @@ static void load_devices_info(bt_bluetooth_ready cb)
 
 	key_file = g_key_file_new();
 
-	g_key_file_load_from_file(key_file, ANDROID_STORAGEDIR"/devices", 0,
-									NULL);
+	g_key_file_load_from_file(key_file, DEVICES_FILE, 0, NULL);
 
 	devs = g_key_file_get_groups(key_file, &len);
 
-- 
1.8.3.2


^ permalink raw reply related

* [RFC 1/5] android/bluetooth: Split devices list to devices and bonded_devices
From: Szymon Janc @ 2014-01-14 11:11 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1389697905-18532-1-git-send-email-szymon.janc@tieto.com>

From: Szymon Janc <szymon.janc@gmail.com>

Bonded devices are permament until unbondedn. Non-bonded devices will
be held in (size limited) cache based on timestamp property so split
list to ease separation.
---
 android/bluetooth.c | 47 +++++++++++++++++++++++++++++++++++------------
 1 file changed, 35 insertions(+), 12 deletions(-)

diff --git a/android/bluetooth.c b/android/bluetooth.c
index 735b03e..78e98c1 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -133,6 +133,8 @@ static const uint16_t uuid_list[] = {
 };
 
 static struct mgmt *mgmt_if = NULL;
+
+static GSList *bonded_devices = NULL;
 static GSList *devices = NULL;
 
 /* This list contains addresses which are asked for records */
@@ -284,6 +286,10 @@ static struct device *find_device(const bdaddr_t *bdaddr)
 {
 	GSList *l;
 
+	l = g_slist_find_custom(bonded_devices, bdaddr, device_match);
+	if (l)
+		return l->data;
+
 	l = g_slist_find_custom(devices, bdaddr, device_match);
 	if (l)
 		return l->data;
@@ -560,12 +566,30 @@ static void set_device_bond_state(const bdaddr_t *addr, uint8_t status,
 	if (!dev)
 		return;
 
-	if (dev->bond_state != state) {
-		dev->bond_state = state;
-		send_bond_state_change(&dev->bdaddr, status, state);
+	if (dev->bond_state == state)
+		return;
 
-		store_device_info(dev);
+	switch (state) {
+	case HAL_BOND_STATE_NONE:
+		if (dev->bond_state == HAL_BOND_STATE_BONDED) {
+			bonded_devices = g_slist_remove(bonded_devices, dev);
+			devices = g_slist_prepend(devices, dev);
+		}
+		break;
+	case HAL_BOND_STATE_BONDED:
+		devices = g_slist_remove(devices, dev);
+		bonded_devices = g_slist_prepend(bonded_devices, dev);
+		break;
+	case HAL_BOND_STATE_BONDING:
+	default:
+		break;
 	}
+
+	dev->bond_state = state;
+
+	store_device_info(dev);
+
+	send_bond_state_change(&dev->bdaddr, status, state);
 }
 
 static  void send_device_property(const bdaddr_t *bdaddr, uint8_t type,
@@ -2134,18 +2158,15 @@ static uint8_t get_adapter_scan_mode(void)
 
 static uint8_t get_adapter_bonded_devices(void)
 {
-	uint8_t buf[sizeof(bdaddr_t) * g_slist_length(devices)];
+	uint8_t buf[sizeof(bdaddr_t) * g_slist_length(bonded_devices)];
 	int i = 0;
 	GSList *l;
 
 	DBG("");
 
-	for (l = devices; l; l = g_slist_next(l)) {
+	for (l = bonded_devices; l; l = g_slist_next(l)) {
 		struct device *dev = l->data;
 
-		if (dev->bond_state != HAL_BOND_STATE_BONDED)
-			continue;
-
 		bdaddr2android(&dev->bdaddr, buf + (i * sizeof(bdaddr_t)));
 		i++;
 	}
@@ -2697,11 +2718,10 @@ static void send_bonded_devices_props(void)
 {
 	GSList *l;
 
-	for (l = devices; l; l = g_slist_next(l)) {
+	for (l = bonded_devices; l; l = g_slist_next(l)) {
 		struct device *dev = l->data;
 
-		if (dev->bond_state == HAL_BOND_STATE_BONDED)
-			get_remote_device_props(dev);
+		get_remote_device_props(dev);
 	}
 }
 
@@ -3099,6 +3119,9 @@ void bt_bluetooth_unregister(void)
 {
 	DBG("");
 
+	g_slist_free_full(bonded_devices, (GDestroyNotify) free_device);
+	bonded_devices = NULL;
+
 	g_slist_free_full(devices, (GDestroyNotify) free_device);
 	devices = NULL;
 
-- 
1.8.3.2


^ permalink raw reply related

* [RFC 0/5] Remote device cache support
From: Szymon Janc @ 2014-01-14 11:11 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

Hi All,

This adds support for permanent cache of remote devices info. Cache size is
limited to DEVICES_CACHE_MAX (currently 100) and oldest devices (based on
timestamp) is removed if cache gets full.

notes:
 - there is still place for improvements in number of reads/writes done.
   Will work on that when current cache approach is accepted.
 - there is no need to cache SDP (we cache UUIDs)

Comments are welcome.

-- 
BR
Szymon Janc

Szymon Janc (5):
  android/bluetooth: Split devices list to devices and bonded_devices
  android/bluetooth: Use defines for settings and devices files paths
  android/bluetooth: Always store device info
  android/bluetooth: Add support for caching remote device info
  android/bluetooth: Add support for loading caches devices from storage

 android/bluetooth.c | 199 ++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 148 insertions(+), 51 deletions(-)

-- 
1.8.3.2


^ permalink raw reply

* Re: [BlueZ v2 01/12] audio/A2DP: Add implemention of SEP open indication
From: Szymon Janc @ 2014-01-14 10:54 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
In-Reply-To: <1389696168-26947-1-git-send-email-luiz.dentz@gmail.com>

Hi Luiz,

On Tuesday 14 of January 2014 12:42:37 Luiz Augusto von Dentz wrote:
> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
> 
> ---
>  android/a2dp.c | 49 +++++++++++++++++++++++++++++++++++--------------
>  1 file changed, 35 insertions(+), 14 deletions(-)
> 
> diff --git a/android/a2dp.c b/android/a2dp.c
> index 1f7678a..1a9adb8 100644
> --- a/android/a2dp.c
> +++ b/android/a2dp.c
> @@ -581,9 +581,44 @@ static gboolean sep_setconf_ind(struct avdtp *session,
>  	return TRUE;
>  }
>  
> +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 gboolean sep_open_ind(struct avdtp *session, struct avdtp_local_sep *sep,
> +				struct avdtp_stream *stream, uint8_t *err,
> +				void *user_data)
> +{
> +	struct a2dp_endpoint *endpoint = user_data;
> +	struct a2dp_setup *setup;
> +
> +	DBG("");
> +
> +	setup = find_setup(endpoint->id);
> +	if (!setup) {
> +		error("Unable to find stream setup for endpoint %u",
> +								endpoint->id);
> +		*err = AVDTP_SEP_NOT_IN_USE;
> +		return FALSE;
> +	}
> +
> +	return TRUE;
> +}
> +
>  static struct avdtp_sep_ind sep_ind = {
>  	.get_capability		= sep_getcap_ind,
>  	.set_configuration	= sep_setconf_ind,
> +	.open			= sep_open_ind,
>  };
>  
>  static uint8_t register_endpoint(const uint8_t *uuid, uint8_t codec,
> @@ -713,20 +748,6 @@ 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)
>  {
>  	const struct audio_cmd_open_stream *cmd = buf;
> 

All patches in this set have been applied, thanks.

-- 
Best regards, 
Szymon Janc

^ permalink raw reply

* [BlueZ v2 12/12] android/AVDTP: Fix invalid free of struct discover
From: Luiz Augusto von Dentz @ 2014-01-14 10:42 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389696168-26947-1-git-send-email-luiz.dentz@gmail.com>

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

If callback releases the last reference it can cause the following:
Invalid free() / delete / delete[] / realloc()
   at 0x4A07577: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
   by 0x386244EF7E: g_free (in /usr/lib64/libglib-2.0.so.0.3800.2)
   by 0x410356: finalize_discovery (avdtp.c:933)
   by 0x414462: session_cb (avdtp.c:2555)
   by 0x38624492A5: g_main_context_dispatch (in /usr/lib64/libglib-2.0.so.0.3800.2)
   by 0x3862449627: ??? (in /usr/lib64/libglib-2.0.so.0.3800.2)
   by 0x3862449A39: g_main_loop_run (in /usr/lib64/libglib-2.0.so.0.3800.2)
   by 0x403A95: main (main.c:439)
 Address 0x4cf7af0 is 0 bytes inside a block of size 24 free'd
   at 0x4A07577: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
   by 0x386244EF7E: g_free (in /usr/lib64/libglib-2.0.so.0.3800.2)
   by 0x410356: finalize_discovery (avdtp.c:933)
   by 0x4110BC: avdtp_unref (avdtp.c:1026)
   by 0x416491: a2dp_device_free (a2dp.c:122)
   by 0x4165DF: bt_a2dp_notify_state (a2dp.c:166)
   by 0x417170: discover_cb (a2dp.c:333)
   by 0x41034E: finalize_discovery (avdtp.c:931)
   by 0x414462: session_cb (avdtp.c:2555)
   by 0x38624492A5: g_main_context_dispatch (in /usr/lib64/libglib-2.0.so.0.3800.2)
   by 0x3862449627: ??? (in /usr/lib64/libglib-2.0.so.0.3800.2)
   by 0x3862449A39: g_main_loop_run (in /usr/lib64/libglib-2.0.so.0.3800.2)
---
 android/avdtp.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/android/avdtp.c b/android/avdtp.c
index 473e02b..5da1206 100644
--- a/android/avdtp.c
+++ b/android/avdtp.c
@@ -923,6 +923,8 @@ static void finalize_discovery(struct avdtp *session, int err)
 	if (!discover)
 		return;
 
+	session->discover = NULL;
+
 	avdtp_error_init(&avdtp_err, AVDTP_ERRNO, err);
 
 	if (discover->id > 0)
@@ -931,7 +933,6 @@ static void finalize_discovery(struct avdtp *session, int err)
 	discover->cb(session, session->seps, err ? &avdtp_err : NULL,
 							discover->user_data);
 	g_free(discover);
-	session->discover = NULL;
 }
 
 static void release_stream(struct avdtp_stream *stream, struct avdtp *session)
-- 
1.8.4.2


^ permalink raw reply related

* [BlueZ v2 11/12] audio/A2DP: Add implemention of SEP abort confirmation
From: Luiz Augusto von Dentz @ 2014-01-14 10:42 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389696168-26947-1-git-send-email-luiz.dentz@gmail.com>

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

---
 android/a2dp.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/android/a2dp.c b/android/a2dp.c
index 146abd3..9f3164a 100644
--- a/android/a2dp.c
+++ b/android/a2dp.c
@@ -923,12 +923,27 @@ static void sep_close_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
 	setup_remove_by_id(endpoint->id);
 }
 
+static void sep_abort_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
+			struct avdtp_stream *stream, struct avdtp_error *err,
+			void *user_data)
+{
+	struct a2dp_endpoint *endpoint = user_data;
+
+	DBG("");
+
+	if (err)
+		return;
+
+	setup_remove_by_id(endpoint->id);
+}
+
 static struct avdtp_sep_cfm sep_cfm = {
 	.set_configuration	= sep_setconf_cfm,
 	.open			= sep_open_cfm,
 	.start			= sep_start_cfm,
 	.suspend		= sep_suspend_cfm,
 	.close			= sep_close_cfm,
+	.abort			= sep_abort_cfm,
 };
 
 static uint8_t register_endpoint(const uint8_t *uuid, uint8_t codec,
-- 
1.8.4.2


^ permalink raw reply related

* [BlueZ v2 10/12] audio/A2DP: Add implemention of SEP close confirmation
From: Luiz Augusto von Dentz @ 2014-01-14 10:42 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389696168-26947-1-git-send-email-luiz.dentz@gmail.com>

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

---
 android/a2dp.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/android/a2dp.c b/android/a2dp.c
index 17f7a9f..146abd3 100644
--- a/android/a2dp.c
+++ b/android/a2dp.c
@@ -909,11 +909,26 @@ static void sep_suspend_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
 	setup_remove_by_id(endpoint->id);
 }
 
+static void sep_close_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
+			struct avdtp_stream *stream, struct avdtp_error *err,
+			void *user_data)
+{
+	struct a2dp_endpoint *endpoint = user_data;
+
+	DBG("");
+
+	if (err)
+		return;
+
+	setup_remove_by_id(endpoint->id);
+}
+
 static struct avdtp_sep_cfm sep_cfm = {
 	.set_configuration	= sep_setconf_cfm,
 	.open			= sep_open_cfm,
 	.start			= sep_start_cfm,
 	.suspend		= sep_suspend_cfm,
+	.close			= sep_close_cfm,
 };
 
 static uint8_t register_endpoint(const uint8_t *uuid, uint8_t codec,
-- 
1.8.4.2


^ permalink raw reply related

* [BlueZ v2 09/12] audio/A2DP: Add implemention of SEP suspend confirmation
From: Luiz Augusto von Dentz @ 2014-01-14 10:42 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389696168-26947-1-git-send-email-luiz.dentz@gmail.com>

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

---
 android/a2dp.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/android/a2dp.c b/android/a2dp.c
index 940cb9c..17f7a9f 100644
--- a/android/a2dp.c
+++ b/android/a2dp.c
@@ -895,10 +895,25 @@ static void sep_start_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
 	setup_remove_by_id(endpoint->id);
 }
 
+static void sep_suspend_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
+			struct avdtp_stream *stream, struct avdtp_error *err,
+			void *user_data)
+{
+	struct a2dp_endpoint *endpoint = user_data;
+
+	DBG("");
+
+	if (!err)
+		return;
+
+	setup_remove_by_id(endpoint->id);
+}
+
 static struct avdtp_sep_cfm sep_cfm = {
 	.set_configuration	= sep_setconf_cfm,
 	.open			= sep_open_cfm,
 	.start			= sep_start_cfm,
+	.suspend		= sep_suspend_cfm,
 };
 
 static uint8_t register_endpoint(const uint8_t *uuid, uint8_t codec,
-- 
1.8.4.2


^ permalink raw reply related

* [BlueZ v2 08/12] audio/A2DP: Add implemention of SEP start confirmation
From: Luiz Augusto von Dentz @ 2014-01-14 10:42 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389696168-26947-1-git-send-email-luiz.dentz@gmail.com>

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

---
 android/a2dp.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/android/a2dp.c b/android/a2dp.c
index 59f8bf5..940cb9c 100644
--- a/android/a2dp.c
+++ b/android/a2dp.c
@@ -881,9 +881,24 @@ static void sep_open_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
 	setup_remove_by_id(endpoint->id);
 }
 
+static void sep_start_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
+			struct avdtp_stream *stream, struct avdtp_error *err,
+			void *user_data)
+{
+	struct a2dp_endpoint *endpoint = user_data;
+
+	DBG("");
+
+	if (!err)
+		return;
+
+	setup_remove_by_id(endpoint->id);
+}
+
 static struct avdtp_sep_cfm sep_cfm = {
 	.set_configuration	= sep_setconf_cfm,
 	.open			= sep_open_cfm,
+	.start			= sep_start_cfm,
 };
 
 static uint8_t register_endpoint(const uint8_t *uuid, uint8_t codec,
-- 
1.8.4.2


^ permalink raw reply related

* [BlueZ v2 07/12] audio/A2DP: Add implemention of SEP open confirmation
From: Luiz Augusto von Dentz @ 2014-01-14 10:42 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389696168-26947-1-git-send-email-luiz.dentz@gmail.com>

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

---
 android/a2dp.c | 56 ++++++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 42 insertions(+), 14 deletions(-)

diff --git a/android/a2dp.c b/android/a2dp.c
index afc6331..59f8bf5 100644
--- a/android/a2dp.c
+++ b/android/a2dp.c
@@ -657,6 +657,33 @@ static void setup_remove(struct a2dp_setup *setup)
 	setup_free(setup);
 }
 
+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 setup_remove_by_id(uint8_t id)
+{
+	struct a2dp_setup *setup;
+
+	setup = find_setup(id);
+	if (!setup) {
+		error("Unable to find stream setup for endpoint %u", id);
+		return;
+	}
+
+	setup_remove(setup);
+}
+
 static gboolean sep_setconf_ind(struct avdtp *session,
 						struct avdtp_local_sep *sep,
 						struct avdtp_stream *stream,
@@ -711,20 +738,6 @@ static gboolean sep_setconf_ind(struct avdtp *session,
 	return TRUE;
 }
 
-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 gboolean sep_open_ind(struct avdtp *session, struct avdtp_local_sep *sep,
 				struct avdtp_stream *stream, uint8_t *err,
 				void *user_data)
@@ -854,8 +867,23 @@ failed:
 	setup_remove(setup);
 }
 
+static void sep_open_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
+			struct avdtp_stream *stream, struct avdtp_error *err,
+			void *user_data)
+{
+	struct a2dp_endpoint *endpoint = user_data;
+
+	DBG("");
+
+	if (!err)
+		return;
+
+	setup_remove_by_id(endpoint->id);
+}
+
 static struct avdtp_sep_cfm sep_cfm = {
 	.set_configuration	= sep_setconf_cfm,
+	.open			= sep_open_cfm,
 };
 
 static uint8_t register_endpoint(const uint8_t *uuid, uint8_t codec,
-- 
1.8.4.2


^ permalink raw reply related

* [BlueZ v2 06/12] audio/A2DP: Add implemention of SEP set_configuration confirmation
From: Luiz Augusto von Dentz @ 2014-01-14 10:42 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389696168-26947-1-git-send-email-luiz.dentz@gmail.com>

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

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

diff --git a/android/a2dp.c b/android/a2dp.c
index 8d0884c..afc6331 100644
--- a/android/a2dp.c
+++ b/android/a2dp.c
@@ -822,6 +822,42 @@ static struct avdtp_sep_ind sep_ind = {
 	.suspend		= sep_suspend_ind,
 };
 
+static void sep_setconf_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
+				struct avdtp_stream *stream,
+				struct avdtp_error *err, void *user_data)
+{
+	struct a2dp_endpoint *endpoint = user_data;
+	struct a2dp_setup *setup;
+	int ret;
+
+	DBG("");
+
+	setup = find_setup(endpoint->id);
+	if (!setup) {
+		error("Unable to find stream setup for endpoint %u",
+								endpoint->id);
+		return;
+	}
+
+	if (err)
+		goto failed;
+
+	ret = avdtp_open(session, stream);
+	if (ret < 0) {
+		error("avdtp_open: %s", strerror(-ret));
+		goto failed;
+	}
+
+	return;
+
+failed:
+	setup_remove(setup);
+}
+
+static struct avdtp_sep_cfm sep_cfm = {
+	.set_configuration	= sep_setconf_cfm,
+};
+
 static uint8_t register_endpoint(const uint8_t *uuid, uint8_t codec,
 							GSList *presets)
 {
@@ -834,8 +870,8 @@ static uint8_t register_endpoint(const uint8_t *uuid, uint8_t codec,
 	endpoint->codec = codec;
 	endpoint->sep = avdtp_register_sep(AVDTP_SEP_TYPE_SOURCE,
 						AVDTP_MEDIA_TYPE_AUDIO,
-						codec, FALSE, &sep_ind, NULL,
-						endpoint);
+						codec, FALSE, &sep_ind,
+						&sep_cfm, endpoint);
 	endpoint->caps = presets->data;
 	endpoint->presets = g_slist_copy(g_slist_nth(presets, 1));
 
-- 
1.8.4.2


^ permalink raw reply related

* [BlueZ v2 05/12] android/A2DP: Discover endpoints when initiator
From: Luiz Augusto von Dentz @ 2014-01-14 10:42 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389696168-26947-1-git-send-email-luiz.dentz@gmail.com>

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

---
 android/a2dp.c | 244 +++++++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 184 insertions(+), 60 deletions(-)

diff --git a/android/a2dp.c b/android/a2dp.c
index a483514..8d0884c 100644
--- a/android/a2dp.c
+++ b/android/a2dp.c
@@ -173,6 +173,166 @@ static void disconnect_cb(void *user_data)
 	bt_a2dp_notify_state(dev, HAL_A2DP_STATE_DISCONNECTED);
 }
 
+static int sbc_check_config(void *caps, uint8_t caps_len, void *conf,
+							uint8_t conf_len)
+{
+	a2dp_sbc_t *cap, *config;
+
+	if (conf_len != caps_len || conf_len != sizeof(a2dp_sbc_t)) {
+		error("SBC: Invalid configuration size (%u)", conf_len);
+		return -EINVAL;
+	}
+
+	cap = caps;
+	config = conf;
+
+	if (!(cap->frequency & config->frequency)) {
+		error("SBC: Unsupported frequency (%u) by endpoint",
+							config->frequency);
+		return -EINVAL;
+	}
+
+	if (!(cap->channel_mode & config->channel_mode)) {
+		error("SBC: Unsupported channel mode (%u) by endpoint",
+							config->channel_mode);
+		return -EINVAL;
+	}
+
+	if (!(cap->block_length & config->block_length)) {
+		error("SBC: Unsupported block length (%u) by endpoint",
+							config->block_length);
+		return -EINVAL;
+	}
+
+	if (!(cap->allocation_method & config->allocation_method)) {
+		error("SBC: Unsupported allocation method (%u) by endpoint",
+							config->block_length);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int check_capabilities(struct a2dp_preset *preset,
+				struct avdtp_media_codec_capability *codec,
+				uint8_t codec_len)
+{
+	/* Codec specific */
+	switch (codec->media_codec_type) {
+	case A2DP_CODEC_SBC:
+		return sbc_check_config(codec->data, codec_len, preset->data,
+								preset->len);
+	default:
+		return -EINVAL;
+	}
+}
+
+static struct a2dp_preset *select_preset(struct a2dp_endpoint *endpoint,
+						struct avdtp_remote_sep *rsep)
+{
+	struct avdtp_service_capability *service;
+	struct avdtp_media_codec_capability *codec;
+	GSList *l;
+
+	service = avdtp_get_codec(rsep);
+	codec = (struct avdtp_media_codec_capability *) service->data;
+
+	for (l = endpoint->presets; l; l = g_slist_next(l)) {
+		struct a2dp_preset *preset = l->data;
+
+		if (check_capabilities(preset, codec,
+					service->length - sizeof(*codec)) == 0)
+			return preset;
+	}
+
+	return NULL;
+}
+
+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 int select_configuration(struct a2dp_device *dev,
+				struct a2dp_endpoint *endpoint,
+				struct avdtp_remote_sep *rsep)
+{
+	struct a2dp_preset *preset;
+	struct avdtp_stream *stream;
+	struct avdtp_service_capability *service;
+	struct avdtp_media_codec_capability *codec;
+	GSList *caps;
+	int err;
+
+	preset = select_preset(endpoint, rsep);
+	if (!preset) {
+		error("Unable to select codec preset");
+		return -EINVAL;
+	}
+
+	service = avdtp_service_cap_new(AVDTP_MEDIA_TRANSPORT, NULL, 0);
+	caps = g_slist_append(NULL, service);
+
+	codec = g_malloc0(sizeof(*codec) + preset->len);
+	codec->media_type = AVDTP_MEDIA_TYPE_AUDIO;
+	codec->media_codec_type = endpoint->codec;
+	memcpy(codec->data, preset->data, preset->len);
+
+	service = avdtp_service_cap_new(AVDTP_MEDIA_CODEC, codec,
+						sizeof(*codec) + preset->len);
+	caps = g_slist_append(caps, service);
+
+	err = avdtp_set_configuration(dev->session, rsep, endpoint->sep, caps,
+								&stream);
+	g_slist_free_full(caps, g_free);
+	if (err < 0) {
+		error("avdtp_set_configuration: %s", strerror(-err));
+		return err;
+	}
+
+	setup_add(dev, endpoint, preset, stream);
+
+	return 0;
+}
+
+static void discover_cb(struct avdtp *session, GSList *seps,
+				struct avdtp_error *err, void *user_data)
+{
+	struct a2dp_device *dev = user_data;
+	struct a2dp_endpoint *endpoint = NULL;
+	struct avdtp_remote_sep *rsep = NULL;
+	GSList *l;
+
+	for (l = endpoints; l; l = g_slist_next(l)) {
+		endpoint = l->data;
+
+		rsep = avdtp_find_remote_sep(session, endpoint->sep);
+		if (rsep)
+			break;
+	}
+
+	if (!rsep) {
+		error("Unable to find matching endpoint");
+		goto failed;
+	}
+
+	if (select_configuration(dev, endpoint, rsep) < 0)
+		goto failed;
+
+	return;
+
+failed:
+	avdtp_shutdown(session);
+}
+
 static void signaling_connect_cb(GIOChannel *chan, GError *err,
 							gpointer user_data)
 {
@@ -192,20 +352,17 @@ static void signaling_connect_cb(GIOChannel *chan, GError *err,
 			BT_IO_OPT_OMTU, &omtu,
 			BT_IO_OPT_INVALID);
 	if (gerr) {
-		bt_a2dp_notify_state(dev, HAL_A2DP_STATE_DISCONNECTED);
 		error("%s", gerr->message);
 		g_error_free(gerr);
-		return;
+		goto failed;
 	}
 
 	fd = g_io_channel_unix_get_fd(chan);
 
 	/* FIXME: Add proper version */
 	dev->session = avdtp_new(fd, imtu, omtu, 0x0100);
-	if (!dev->session) {
-		bt_a2dp_notify_state(dev, HAL_A2DP_STATE_DISCONNECTED);
-		return;
-	}
+	if (!dev->session)
+		goto failed;
 
 	avdtp_add_disconnect_cb(dev->session, disconnect_cb, dev);
 
@@ -214,7 +371,23 @@ static void signaling_connect_cb(GIOChannel *chan, GError *err,
 		dev->io = NULL;
 	}
 
+	/* Proceed to stream setup if initiator */
+	if (dev->state == HAL_A2DP_STATE_CONNECTING) {
+		int perr;
+
+		perr = avdtp_discover(dev->session, discover_cb, dev);
+		if (perr < 0) {
+			error("avdtp_discover: %s", strerror(-perr));
+			goto failed;
+		}
+	}
+
 	bt_a2dp_notify_state(dev, HAL_A2DP_STATE_CONNECTED);
+
+	return;
+
+failed:
+	bt_a2dp_notify_state(dev, HAL_A2DP_STATE_DISCONNECTED);
 }
 
 static void bt_a2dp_connect(const void *buf, uint16_t len)
@@ -428,50 +601,11 @@ 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;
+	struct a2dp_preset *caps;
 
 	for (l = endpoint->presets; l; l = g_slist_next(l)) {
 		struct a2dp_preset *preset = l->data;
@@ -483,10 +617,13 @@ static int check_config(struct a2dp_endpoint *endpoint,
 			return 0;
 	}
 
+	caps = endpoint->caps;
+
 	/* Codec specific */
 	switch (endpoint->codec) {
 	case A2DP_CODEC_SBC:
-		return sbc_check_config(endpoint, config);
+		return sbc_check_config(caps->data, caps->len, config->data,
+								config->len);
 	default:
 		return -EINVAL;
 	}
@@ -520,19 +657,6 @@ static void setup_remove(struct a2dp_setup *setup)
 	setup_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,
-- 
1.8.4.2


^ permalink raw reply related

* [BlueZ v2 04/12] audio/A2DP: Add implemention of SEP suspend indication
From: Luiz Augusto von Dentz @ 2014-01-14 10:42 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389696168-26947-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, 23 insertions(+)

diff --git a/android/a2dp.c b/android/a2dp.c
index 1b12767..a483514 100644
--- a/android/a2dp.c
+++ b/android/a2dp.c
@@ -667,12 +667,35 @@ static gboolean sep_start_ind(struct avdtp *session,
 	return TRUE;
 }
 
+static gboolean sep_suspend_ind(struct avdtp *session,
+						struct avdtp_local_sep *sep,
+						struct avdtp_stream *stream,
+						uint8_t *err,
+						void *user_data)
+{
+	struct a2dp_endpoint *endpoint = user_data;
+	struct a2dp_setup *setup;
+
+	DBG("");
+
+	setup = find_setup(endpoint->id);
+	if (!setup) {
+		error("Unable to find stream setup for endpoint %u",
+								endpoint->id);
+		*err = AVDTP_SEP_NOT_IN_USE;
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
 static struct avdtp_sep_ind sep_ind = {
 	.get_capability		= sep_getcap_ind,
 	.set_configuration	= sep_setconf_ind,
 	.open			= sep_open_ind,
 	.close			= sep_close_ind,
 	.start			= sep_start_ind,
+	.suspend		= sep_suspend_ind,
 };
 
 static uint8_t register_endpoint(const uint8_t *uuid, uint8_t codec,
-- 
1.8.4.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