Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH 04/17] shared: Add timeout handling with Glib support
From: Lukasz Rymanowski @ 2014-02-26  1:57 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Lukasz Rymanowski
In-Reply-To: <1393379848-4031-1-git-send-email-lukasz.rymanowski@tieto.com>

---
 src/shared/timeout-glib.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 73 insertions(+)
 create mode 100644 src/shared/timeout-glib.c

diff --git a/src/shared/timeout-glib.c b/src/shared/timeout-glib.c
new file mode 100644
index 0000000..c045efc
--- /dev/null
+++ b/src/shared/timeout-glib.c
@@ -0,0 +1,73 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2014  Intel Corporation. All rights reserved.
+ *
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ */
+
+#include "timeout.h"
+
+#include <glib.h>
+
+struct timeout_data {
+	timeout_func_t func;
+	timeout_destroy_func_t destroy;
+	void *user_data;
+};
+
+static gboolean timeout_callback(gpointer user_data)
+{
+	struct timeout_data *data  = user_data;
+
+	if (data->func(data->user_data))
+		return TRUE;
+
+	return FALSE;
+}
+
+static void timeout_destroy(gpointer user_data)
+{
+	struct timeout_data *data = user_data;
+
+	if (data->destroy)
+		data->destroy(data->user_data);
+
+	g_free(data);
+}
+
+int timeout_add(unsigned int ms, timeout_func_t func, void *user_data,
+						timeout_destroy_func_t destroy)
+{
+	guint id;
+	struct timeout_data *data = g_malloc0(sizeof(*data));
+
+	data->func = func;
+	data->destroy = destroy;
+	data->user_data = user_data;
+
+	id = g_timeout_add_full(G_PRIORITY_DEFAULT, ms, timeout_callback, data,
+							timeout_destroy);
+	if (!id)
+		g_free(data);
+
+	return id;
+}
+
+void timeout_remove(unsigned int id)
+{
+	GSource *source = g_main_context_find_source_by_id(NULL, id);
+	if (source)
+		g_source_destroy(source);
+}
-- 
1.8.4


^ permalink raw reply related

* [PATCH 05/17] shared: Add timeout handling with mainloop support
From: Lukasz Rymanowski @ 2014-02-26  1:57 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Lukasz Rymanowski
In-Reply-To: <1393379848-4031-1-git-send-email-lukasz.rymanowski@tieto.com>

---
 src/shared/timeout-mainloop.c | 78 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 78 insertions(+)
 create mode 100644 src/shared/timeout-mainloop.c

diff --git a/src/shared/timeout-mainloop.c b/src/shared/timeout-mainloop.c
new file mode 100644
index 0000000..bdc527a
--- /dev/null
+++ b/src/shared/timeout-mainloop.c
@@ -0,0 +1,78 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2014  Intel Corporation. All rights reserved.
+ *
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ */
+
+#include <stdlib.h>
+
+#include "timeout.h"
+
+#include "monitor/mainloop.h"
+
+struct timeout_data {
+	int id;
+	timeout_func_t func;
+	timeout_destroy_func_t destroy;
+	unsigned int timeout;
+	void *user_data;
+};
+
+static void timeout_callback(int id, void *user_data)
+{
+	struct timeout_data *data = user_data;
+
+	if (data->func(data->user_data) &&
+		!mainloop_modify_timeout(data->id, data->timeout))
+		return;
+
+	mainloop_remove_timeout(data->id);
+}
+
+static void timeout_destroy(void *user_data)
+{
+	struct timeout_data *data = user_data;
+
+	if (data->destroy)
+		data->destroy(data->user_data);
+
+	free(data);
+}
+
+int timeout_add(unsigned int t, timeout_func_t func, void *user_data,
+						timeout_destroy_func_t destroy)
+{
+	struct timeout_data *data = malloc(sizeof(*data));
+
+	data->func = func;
+	data->user_data = user_data;
+	data->timeout = t;
+
+	data->id = mainloop_add_timeout(t, timeout_callback, data,
+							timeout_destroy);
+	if (!data->id) {
+		free(data);
+		return 0;
+	}
+
+	return data->id;
+}
+
+void timeout_remove(unsigned int id)
+{
+	if (id)
+		mainloop_remove_timeout(id);
+}
-- 
1.8.4


^ permalink raw reply related

* [PATCH 06/17] emulator: Minor style fix
From: Lukasz Rymanowski @ 2014-02-26  1:57 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Lukasz Rymanowski
In-Reply-To: <1393379848-4031-1-git-send-email-lukasz.rymanowski@tieto.com>

---
 emulator/btdev.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/emulator/btdev.c b/emulator/btdev.c
index c7231dd..c6bf96c 100644
--- a/emulator/btdev.c
+++ b/emulator/btdev.c
@@ -708,8 +708,8 @@ static void inquiry_complete(struct btdev *btdev, uint8_t status)
 			ir.rssi = -60;
 			memcpy(ir.data, btdev_list[i]->ext_inquiry_rsp, 240);
 
-			send_event(btdev, BT_HCI_EVT_EXT_INQUIRY_RESULT,
-							&ir, sizeof(ir));
+			send_event(btdev, BT_HCI_EVT_EXT_INQUIRY_RESULT, &ir,
+								sizeof(ir));
 			continue;
 		}
 
@@ -737,8 +737,8 @@ static void inquiry_complete(struct btdev *btdev, uint8_t status)
 			memcpy(ir.dev_class, btdev_list[i]->dev_class, 3);
 			ir.clock_offset = 0x0000;
 
-			send_event(btdev, BT_HCI_EVT_INQUIRY_RESULT,
-							&ir, sizeof(ir));
+			send_event(btdev, BT_HCI_EVT_INQUIRY_RESULT, &ir,
+								sizeof(ir));
 		}
         }
 
-- 
1.8.4


^ permalink raw reply related

* [PATCH 07/17] emulator: Use timeout for sending inquiry results
From: Lukasz Rymanowski @ 2014-02-26  1:57 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Lukasz Rymanowski
In-Reply-To: <1393379848-4031-1-git-send-email-lukasz.rymanowski@tieto.com>

With this patch btdev uses timeout to schedule inquiry results
It also allows btdev to receive hci commands during inquiry.
Previously btdev was blocked since all the inquiry result were sent in
single loop
---
 Makefile.tools      | 19 ++++++++----
 android/Makefile.am |  2 ++
 emulator/btdev.c    | 87 +++++++++++++++++++++++++++++++++++++++++++++++++----
 3 files changed, 96 insertions(+), 12 deletions(-)

diff --git a/Makefile.tools b/Makefile.tools
index 15d810f..0a41ec3 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -48,6 +48,7 @@ emulator_btvirt_SOURCES = emulator/main.c monitor/bt.h \
 				monitor/mainloop.h monitor/mainloop.c \
 				src/shared/util.h src/shared/util.c \
 				src/shared/crypto.h src/shared/crypto.c \
+				src/sharead/timeout.h src/shared/timeout-mainloop.c \
 				emulator/server.h emulator/server.c \
 				emulator/vhci.h emulator/vhci.c \
 				emulator/btdev.h emulator/btdev.c \
@@ -82,7 +83,8 @@ tools_mgmt_tester_SOURCES = tools/mgmt-tester.c monitor/bt.h \
 				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
+				src/shared/tester.h src/shared/tester.c \
+				src/shared/timeout.h src/shared/timeout-glib.c
 tools_mgmt_tester_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
 
 tools_l2cap_tester_SOURCES = tools/l2cap-tester.c monitor/bt.h \
@@ -94,7 +96,8 @@ tools_l2cap_tester_SOURCES = tools/l2cap-tester.c monitor/bt.h \
 				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
+				src/shared/tester.h src/shared/tester.c \
+				src/shared/timeout.h src/shared/timeout-glib.c
 tools_l2cap_tester_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
 
 tools_rfcomm_tester_SOURCES = tools/rfcomm-tester.c monitor/bt.h \
@@ -106,7 +109,8 @@ tools_rfcomm_tester_SOURCES = tools/rfcomm-tester.c monitor/bt.h \
 				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
+				src/shared/tester.h src/shared/tester.c \
+				src/shared/timeout.h src/shared/timeout-glib.c
 tools_rfcomm_tester_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
 
 tools_smp_tester_SOURCES = tools/smp-tester.c monitor/bt.h \
@@ -118,7 +122,8 @@ tools_smp_tester_SOURCES = tools/smp-tester.c monitor/bt.h \
 				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
+				src/shared/tester.h src/shared/tester.c \
+				src/shared/timeout.h src/shared/timeout-glib.c
 tools_smp_tester_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
 
 tools_gap_tester_SOURCES = tools/gap-tester.c monitor/bt.h \
@@ -128,7 +133,8 @@ tools_gap_tester_SOURCES = tools/gap-tester.c monitor/bt.h \
 				src/shared/util.h src/shared/util.c \
 				src/shared/queue.h src/shared/queue.c \
 				src/shared/hciemu.h src/shared/hciemu.c \
-				src/shared/tester.h src/shared/tester.c
+				src/shared/tester.h src/shared/tester.c \
+				src/shared/timeout.h src/shared/timeout-glib.c
 tools_gap_tester_LDADD =  lib/libbluetooth-internal.la \
 				gdbus/libgdbus-internal.la \
 				@GLIB_LIBS@ @DBUS_LIBS@
@@ -142,7 +148,8 @@ tools_sco_tester_SOURCES = tools/sco-tester.c monitor/bt.h \
 				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
+				src/shared/tester.h src/shared/tester.c \
+				src/shared/timeout.h src/shared/timeout-glib.c
 tools_sco_tester_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
 
 tools_hci_tester_SOURCES = tools/hci-tester.c monitor/bt.h \
diff --git a/android/Makefile.am b/android/Makefile.am
index b93b840..036a08b 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -117,6 +117,7 @@ android_android_tester_SOURCES = emulator/btdev.h emulator/btdev.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 \
+				src/shared/timeout.h src/shared/timeout-glib.c \
 				monitor/rfcomm.h \
 				android/hardware/hardware.c \
 				android/android-tester.c
@@ -139,6 +140,7 @@ android_ipc_tester_SOURCES = emulator/btdev.h emulator/btdev.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 \
+				src/shared/timeout.h src/shared/timeout-glib.c \
 				android/hal-utils.h android/hal-utils.c \
 				android/ipc-tester.c
 
diff --git a/emulator/btdev.c b/emulator/btdev.c
index c6bf96c..18f7410 100644
--- a/emulator/btdev.c
+++ b/emulator/btdev.c
@@ -33,6 +33,7 @@
 #include <alloca.h>
 
 #include "src/shared/util.h"
+#include "src/shared/timeout.h"
 #include "monitor/bt.h"
 #include "btdev.h"
 
@@ -68,6 +69,8 @@ struct btdev {
 	btdev_send_func send_handler;
 	void *send_data;
 
+	int inquiry_id;
+
 	struct hook *hook_list[MAX_HOOK_ENTRIES];
 
         uint16_t manufacturer;
@@ -122,8 +125,16 @@ struct btdev {
 	uint8_t  sync_train_service_data;
 };
 
+struct inquiry_data {
+	struct btdev *btdev;
+	int sent_count;
+};
+
+#define DEFAULT_INQUIRY_INTERVAL 2 /* 2 miliseconds */
+
 #define MAX_BTDEV_ENTRIES 16
 
+
 static const uint8_t LINK_KEY_NONE[16] = { 0 };
 static const uint8_t LINK_KEY_DUMMY[16] = {	0, 1, 2, 3, 4, 5, 6, 7,
 						8, 9, 0, 1, 2, 3, 4, 5 };
@@ -527,9 +538,13 @@ void btdev_destroy(struct btdev *btdev)
 	if (!btdev)
 		return;
 
+	if (btdev->inquiry_id)
+		timeout_remove(btdev->inquiry_id);
+
 	del_btdev(btdev);
 
 	free(btdev);
+	btdev = NULL;
 }
 
 const uint8_t *btdev_get_bdaddr(struct btdev *btdev)
@@ -683,12 +698,22 @@ static void num_completed_packets(struct btdev *btdev)
 	}
 }
 
-static void inquiry_complete(struct btdev *btdev, uint8_t status)
+static bool inquiry_callback(void *user_data)
 {
-	struct bt_hci_evt_inquiry_complete ic;
+	struct inquiry_data *data = user_data;
+	struct btdev *btdev = data->btdev;
+	static int j;
+	int sent = data->sent_count;
 	int i;
 
-	for (i = 0; i < MAX_BTDEV_ENTRIES; i++) {
+	if (!btdev)
+		return false;
+
+	for (i = j; i < MAX_BTDEV_ENTRIES; i++, j++) {
+		/*Lets sent 10 inquiry results at once */
+		if (sent + 10 == data->sent_count)
+			break;
+
 		if (!btdev_list[i] || btdev_list[i] == btdev)
 			continue;
 
@@ -710,6 +735,7 @@ static void inquiry_complete(struct btdev *btdev, uint8_t status)
 
 			send_event(btdev, BT_HCI_EVT_EXT_INQUIRY_RESULT, &ir,
 								sizeof(ir));
+			data->sent_count++;
 			continue;
 		}
 
@@ -726,6 +752,7 @@ static void inquiry_complete(struct btdev *btdev, uint8_t status)
 
 			send_event(btdev, BT_HCI_EVT_INQUIRY_RESULT_WITH_RSSI,
 							&ir, sizeof(ir));
+			data->sent_count++;
 		} else {
 			struct bt_hci_evt_inquiry_result ir;
 
@@ -739,11 +766,59 @@ static void inquiry_complete(struct btdev *btdev, uint8_t status)
 
 			send_event(btdev, BT_HCI_EVT_INQUIRY_RESULT, &ir,
 								sizeof(ir));
+			data->sent_count++;
 		}
-        }
+	}
+
+	if (i == MAX_BTDEV_ENTRIES) {
+		struct bt_hci_evt_inquiry_complete ic;
+
+		ic.status = BT_HCI_ERR_SUCCESS;
+		send_event(btdev, BT_HCI_EVT_INQUIRY_COMPLETE, &ic, sizeof(ic));
+
+		/* reset */
+		btdev->inquiry_id = 0;
+		j = 0;
 
-	ic.status = status;
+		return false;
+	}
+
+	return true;
+}
+
+static void inquiry_destroy(void *user_data)
+{
+	struct inquiry_data *data = user_data;
+
+	if (data->btdev)
+		data->btdev->inquiry_id = 0;
+
+	free(data);
+}
+
+static void inquiry_cmd(struct btdev *btdev, const void *cmd)
+{
+	struct inquiry_data *data;
+	struct bt_hci_evt_inquiry_complete ic;
+
+	if (btdev->inquiry_id)
+		return;
+
+	data = malloc(sizeof(*data));
+	if (!data)
+		goto error;
+
+	memset(data, 0, sizeof(*data));
+	data->btdev = btdev;
+
+	btdev->inquiry_id = timeout_add(DEFAULT_INQUIRY_INTERVAL,
+				inquiry_callback, data, inquiry_destroy);
+	/* Return if success */
+	if (btdev->inquiry_id)
+		return;
 
+error:
+	ic.status = BT_HCI_ERR_HARDWARE_FAILURE;
 	send_event(btdev, BT_HCI_EVT_INQUIRY_COMPLETE, &ic, sizeof(ic));
 }
 
@@ -2480,7 +2555,7 @@ static void default_cmd_completion(struct btdev *btdev, uint16_t opcode,
 	case BT_HCI_CMD_INQUIRY:
 		if (btdev->type == BTDEV_TYPE_LE)
 			return;
-		inquiry_complete(btdev, BT_HCI_ERR_SUCCESS);
+		inquiry_cmd(btdev, data);
 		break;
 
 	case BT_HCI_CMD_CREATE_CONN:
-- 
1.8.4


^ permalink raw reply related

* [PATCH 08/17] emulator: Add inquiry cancel
From: Lukasz Rymanowski @ 2014-02-26  1:57 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Lukasz Rymanowski
In-Reply-To: <1393379848-4031-1-git-send-email-lukasz.rymanowski@tieto.com>

---
 emulator/btdev.c | 31 +++++++++++++++++++++++++++----
 1 file changed, 27 insertions(+), 4 deletions(-)

diff --git a/emulator/btdev.c b/emulator/btdev.c
index 18f7410..722c312 100644
--- a/emulator/btdev.c
+++ b/emulator/btdev.c
@@ -70,6 +70,7 @@ struct btdev {
 	void *send_data;
 
 	int inquiry_id;
+	bool inquiry_cancel;
 
 	struct hook *hook_list[MAX_HOOK_ENTRIES];
 
@@ -789,10 +790,20 @@ static bool inquiry_callback(void *user_data)
 static void inquiry_destroy(void *user_data)
 {
 	struct inquiry_data *data = user_data;
+	struct btdev *btdev = data->btdev;
+	uint8_t status = BT_HCI_ERR_SUCCESS;
+
+	if (!btdev)
+		goto finish;
+
+	if (btdev->inquiry_cancel)
+		cmd_complete(btdev, BT_HCI_CMD_INQUIRY_CANCEL, &status,
+							sizeof(status));
 
-	if (data->btdev)
-		data->btdev->inquiry_id = 0;
+	btdev->inquiry_cancel = false;
+	btdev->inquiry_id = 0;
 
+finish:
 	free(data);
 }
 
@@ -822,6 +833,19 @@ error:
 	send_event(btdev, BT_HCI_EVT_INQUIRY_COMPLETE, &ic, sizeof(ic));
 }
 
+static void inquiry_cancel(struct btdev *btdev)
+{
+	uint8_t status = BT_HCI_ERR_COMMAND_DISALLOWED;
+
+	if (btdev->inquiry_id) {
+		btdev->inquiry_cancel = true;
+		timeout_remove(btdev->inquiry_id);
+		btdev->inquiry_id = 0;
+		return;
+	}
+
+	cmd_complete(btdev, BT_HCI_CMD_INQUIRY_CANCEL, &status, sizeof(status));
+}
 static void conn_complete(struct btdev *btdev,
 					const uint8_t *bdaddr, uint8_t status)
 {
@@ -1638,8 +1662,7 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
 	case BT_HCI_CMD_INQUIRY_CANCEL:
 		if (btdev->type == BTDEV_TYPE_LE)
 			goto unsupported;
-		status = BT_HCI_ERR_SUCCESS;
-		cmd_complete(btdev, opcode, &status, sizeof(status));
+		inquiry_cancel(btdev);
 		break;
 
 	case BT_HCI_CMD_CREATE_CONN:
-- 
1.8.4


^ permalink raw reply related

* [PATCH 09/17] emulator: Add handling inquiry number of responses
From: Lukasz Rymanowski @ 2014-02-26  1:57 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Lukasz Rymanowski
In-Reply-To: <1393379848-4031-1-git-send-email-lukasz.rymanowski@tieto.com>

Conflicts:
	emulator/btdev.c

Conflicts:
	emulator/btdev.c
---
 emulator/btdev.c | 32 ++++++++++++++++++++++++--------
 1 file changed, 24 insertions(+), 8 deletions(-)

diff --git a/emulator/btdev.c b/emulator/btdev.c
index 722c312..c74258b 100644
--- a/emulator/btdev.c
+++ b/emulator/btdev.c
@@ -128,6 +128,8 @@ struct btdev {
 
 struct inquiry_data {
 	struct btdev *btdev;
+	int num_resp;
+
 	int sent_count;
 };
 
@@ -703,6 +705,7 @@ static bool inquiry_callback(void *user_data)
 {
 	struct inquiry_data *data = user_data;
 	struct btdev *btdev = data->btdev;
+	struct bt_hci_evt_inquiry_complete ic;
 	static int j;
 	int sent = data->sent_count;
 	int i;
@@ -771,20 +774,31 @@ static bool inquiry_callback(void *user_data)
 		}
 	}
 
-	if (i == MAX_BTDEV_ENTRIES) {
-		struct bt_hci_evt_inquiry_complete ic;
+	/* Check if we sent already required amount of responses*/
+	if (data->num_resp && data->sent_count == data->num_resp)
+		goto finish;
 
-		ic.status = BT_HCI_ERR_SUCCESS;
-		send_event(btdev, BT_HCI_EVT_INQUIRY_COMPLETE, &ic, sizeof(ic));
+	if (i == MAX_BTDEV_ENTRIES) {
+		if (!data->num_resp)
+			goto finish;
 
-		/* reset */
-		btdev->inquiry_id = 0;
+		/* Reset main iterator so we can start iterate btdev_list
+		 * from the beggining */
 		j = 0;
-
-		return false;
 	}
 
 	return true;
+
+finish:
+	/* Note that destroy will be called */
+	ic.status = BT_HCI_ERR_SUCCESS;
+	send_event(btdev, BT_HCI_EVT_INQUIRY_COMPLETE, &ic, sizeof(ic));
+
+	/* reset */
+	btdev->inquiry_id = 0;
+	j = 0;
+
+	return false;
 }
 
 static void inquiry_destroy(void *user_data)
@@ -809,6 +823,7 @@ finish:
 
 static void inquiry_cmd(struct btdev *btdev, const void *cmd)
 {
+	const struct bt_hci_cmd_inquiry *inq_cmd = cmd;
 	struct inquiry_data *data;
 	struct bt_hci_evt_inquiry_complete ic;
 
@@ -821,6 +836,7 @@ static void inquiry_cmd(struct btdev *btdev, const void *cmd)
 
 	memset(data, 0, sizeof(*data));
 	data->btdev = btdev;
+	data->num_resp = inq_cmd->num_resp;
 
 	btdev->inquiry_id = timeout_add(DEFAULT_INQUIRY_INTERVAL,
 				inquiry_callback, data, inquiry_destroy);
-- 
1.8.4


^ permalink raw reply related

* [PATCH 10/17] emulator: Add handling inquiry_lenght from inquiry command
From: Lukasz Rymanowski @ 2014-02-26  1:57 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Lukasz Rymanowski
In-Reply-To: <1393379848-4031-1-git-send-email-lukasz.rymanowski@tieto.com>

---
 emulator/btdev.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/emulator/btdev.c b/emulator/btdev.c
index c74258b..bf0c9d2 100644
--- a/emulator/btdev.c
+++ b/emulator/btdev.c
@@ -129,8 +129,10 @@ struct btdev {
 struct inquiry_data {
 	struct btdev *btdev;
 	int num_resp;
+	int max_iter; /* Calculated from inquiry_lenght */
 
 	int sent_count;
+	int iter;
 };
 
 #define DEFAULT_INQUIRY_INTERVAL 2 /* 2 miliseconds */
@@ -778,8 +780,12 @@ static bool inquiry_callback(void *user_data)
 	if (data->num_resp && data->sent_count == data->num_resp)
 		goto finish;
 
+	/* Check if we already spent as much time as required */
+	if (data->max_iter && data->iter++ == data->max_iter)
+		goto finish;
+
 	if (i == MAX_BTDEV_ENTRIES) {
-		if (!data->num_resp)
+		if (!data->max_iter && !data->num_resp)
 			goto finish;
 
 		/* Reset main iterator so we can start iterate btdev_list
@@ -826,6 +832,7 @@ static void inquiry_cmd(struct btdev *btdev, const void *cmd)
 	const struct bt_hci_cmd_inquiry *inq_cmd = cmd;
 	struct inquiry_data *data;
 	struct bt_hci_evt_inquiry_complete ic;
+	unsigned int inquiry_len_ms = 128 * inq_cmd->length;
 
 	if (btdev->inquiry_id)
 		return;
@@ -838,6 +845,9 @@ static void inquiry_cmd(struct btdev *btdev, const void *cmd)
 	data->btdev = btdev;
 	data->num_resp = inq_cmd->num_resp;
 
+	if (inquiry_len_ms)
+		data->max_iter = inquiry_len_ms / DEFAULT_INQUIRY_INTERVAL;
+
 	btdev->inquiry_id = timeout_add(DEFAULT_INQUIRY_INTERVAL,
 				inquiry_callback, data, inquiry_destroy);
 	/* Return if success */
-- 
1.8.4


^ permalink raw reply related

* [PATCH 11/17] emulator: Add support to create many remote devices in hciemu
From: Lukasz Rymanowski @ 2014-02-26  1:57 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Lukasz Rymanowski
In-Reply-To: <1393379848-4031-1-git-send-email-lukasz.rymanowski@tieto.com>

This patch adds possibility to add more remote devices
---
 emulator/btdev.c    |  2 +-
 src/shared/hciemu.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/shared/hciemu.h | 11 ++++++++++
 3 files changed, 75 insertions(+), 1 deletion(-)

diff --git a/emulator/btdev.c b/emulator/btdev.c
index bf0c9d2..1be3ba1 100644
--- a/emulator/btdev.c
+++ b/emulator/btdev.c
@@ -137,7 +137,7 @@ struct inquiry_data {
 
 #define DEFAULT_INQUIRY_INTERVAL 2 /* 2 miliseconds */
 
-#define MAX_BTDEV_ENTRIES 16
+#define MAX_BTDEV_ENTRIES 100
 
 
 static const uint8_t LINK_KEY_NONE[16] = { 0 };
diff --git a/src/shared/hciemu.c b/src/shared/hciemu.c
index 6c93005..c40f71e 100644
--- a/src/shared/hciemu.c
+++ b/src/shared/hciemu.c
@@ -57,6 +57,7 @@ struct hciemu {
 	guint client_source;
 	struct queue *post_command_hooks;
 	char bdaddr_str[18];
+	GList *remote_devs;
 };
 
 struct hciemu_command_hook {
@@ -358,6 +359,18 @@ struct hciemu *hciemu_ref(struct hciemu *hciemu)
 	return hciemu;
 }
 
+static void destroy_remotes(struct remote_dev *r)
+{
+	bthost_stop(r->bthost);
+
+	g_source_remove(r->client_source);
+	g_source_remove(r->host_source);
+
+	bthost_destroy(r->bthost);
+	btdev_destroy(r->btdev);
+	g_free(r);
+}
+
 void hciemu_unref(struct hciemu *hciemu)
 {
 	if (!hciemu)
@@ -378,6 +391,8 @@ void hciemu_unref(struct hciemu *hciemu)
 	btdev_destroy(hciemu->client_dev);
 	btdev_destroy(hciemu->master_dev);
 
+	g_list_free_full(hciemu->remote_devs, (GDestroyNotify)destroy_remotes);
+
 	free(hciemu);
 }
 
@@ -498,3 +513,51 @@ bool hciemu_del_hook(struct hciemu *hciemu, enum hciemu_hook_type type,
 
 	return btdev_del_hook(hciemu->master_dev, hook_type, opcode);
 }
+
+int hciemu_add_remote_devs(struct hciemu *hciemu, int number_of_devices)
+{
+	int i;
+
+	for (i = 0; i < number_of_devices; i++)  {
+		struct remote_dev *r;
+		struct btdev *btdev;
+		struct bthost *bthost;
+		int sv[2];
+
+		btdev = btdev_create(hciemu->btdev_type, 0x00);
+		if (!btdev)
+			break;
+
+		bthost = bthost_create();
+		if (!bthost) {
+			btdev_destroy(btdev);
+			break;
+		}
+
+		btdev_set_command_handler(btdev, client_command_callback,
+								hciemu);
+
+		if (socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK |
+						SOCK_CLOEXEC, 0, sv) < 0) {
+			bthost_destroy(bthost);
+			btdev_destroy(btdev);
+			break;
+		}
+
+		r = g_malloc(sizeof(*r));
+		r->btdev = btdev;
+		r->bthost = bthost;
+
+		r->client_source = create_source_btdev(sv[0], btdev);
+		r->host_source = create_source_bthost(sv[1], bthost);
+
+		hciemu->remote_devs = g_list_prepend(hciemu->remote_devs, r);
+	}
+
+	return i;
+}
+
+GList *hciemu_get_remote_devs(struct hciemu *hciemu)
+{
+	return hciemu->remote_devs;
+}
diff --git a/src/shared/hciemu.h b/src/shared/hciemu.h
index d948867..52dee23 100644
--- a/src/shared/hciemu.h
+++ b/src/shared/hciemu.h
@@ -26,6 +26,13 @@
 
 struct hciemu;
 
+struct remote_dev {
+	struct btdev *btdev;
+	struct bthost *bthost;
+	guint client_source;
+	guint host_source;
+};
+
 enum hciemu_type {
 	HCIEMU_TYPE_BREDRLE,
 	HCIEMU_TYPE_BREDR,
@@ -67,3 +74,7 @@ int hciemu_add_hook(struct hciemu *hciemu, enum hciemu_hook_type type,
 
 bool hciemu_del_hook(struct hciemu *hciemu, enum hciemu_hook_type type,
 							uint16_t opcode);
+
+int hciemu_add_remote_devs(struct hciemu *hciemu, int number_of_devices);
+
+GList *hciemu_get_remote_devs(struct hciemu *hciemu);
-- 
1.8.4


^ permalink raw reply related

* [PATCH 12/17] android/tester: Add discovery cancel test
From: Lukasz Rymanowski @ 2014-02-26  1:57 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Lukasz Rymanowski
In-Reply-To: <1393379848-4031-1-git-send-email-lukasz.rymanowski@tieto.com>

This test a scenario:
1. Start discovery (99 remote devices)
2. Cancel discovery after 11 inquiry results

Test pass if cancel inquiry command hits btdev before all 50 remote
devices is found
---
 android/android-tester.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 111 insertions(+)

diff --git a/android/android-tester.c b/android/android-tester.c
index 6d5638e..c6484bf 100644
--- a/android/android-tester.c
+++ b/android/android-tester.c
@@ -56,6 +56,8 @@ struct generic_data {
 	bt_callbacks_t expected_hal_cb;
 	struct priority_property *expected_properties;
 	uint8_t expected_properties_num;
+	uint8_t set_num_of_remote;
+	int expected_device_found_num;
 };
 
 struct socket_data {
@@ -408,6 +410,13 @@ static void index_removed_callback(uint16_t index, uint16_t length,
 	tester_post_teardown_complete();
 }
 
+static void enable_and_set_discoverable(gpointer data, gpointer user_data)
+{
+	struct bthost *bthost = ((struct remote_dev *)data)->bthost;
+	bthost_start(bthost);
+	bthost_write_scan_enable(bthost, 0x03);
+}
+
 static void read_index_list_callback(uint8_t status, uint16_t length,
 					const void *param, void *user_data)
 {
@@ -643,6 +652,26 @@ static void discovery_stop_success_cb(bt_discovery_state_t state)
 	}
 }
 
+static void discovery_cancel_state_changed_cb(bt_discovery_state_t state)
+{
+	struct test_data *data = tester_get_data();
+
+	if (state == BT_DISCOVERY_STARTED) {
+		data->cb_count--;
+		return;
+	}
+
+	if (state == BT_DISCOVERY_STOPPED)
+		data->cb_count--;
+
+	if (data->cb_count) {
+		tester_test_failed();
+		return;
+	}
+
+	tester_test_passed();
+}
+
 static void discovery_device_found_state_changed_cb(bt_discovery_state_t state)
 {
 	struct test_data *data = tester_get_data();
@@ -695,6 +724,28 @@ static void discovery_state_changed_cb(bt_discovery_state_t state)
 	}
 }
 
+static void device_found_cancel_cb(int num_properties,
+						bt_property_t *properties)
+{
+	struct test_data *data = tester_get_data();
+	const struct generic_data *test = data->test_data;
+	static int num_resp;
+	int triger_cancel = 11;
+
+	if (num_resp > test->expected_device_found_num)
+		return;
+
+	/* Increase cb_count if we reach bad amount of found devices*/
+	if (num_resp++ == test->expected_device_found_num)
+		data->cb_count++;
+
+	/* It is time to issue cancel discovery */
+	if (num_resp == triger_cancel) {
+		data->cb_count--;
+		data->if_bluetooth->cancel_discovery();
+	}
+}
+
 static void discovery_device_found_cb(int num_properties,
 						bt_property_t *properties)
 {
@@ -1362,6 +1413,16 @@ static const struct generic_data bluetooth_discovery_device_found_test = {
 	.expected_adapter_status = BT_STATUS_NOT_EXPECTED,
 };
 
+static const struct generic_data bluetooth_discovery_cancel_test = {
+	.expected_hal_cb.discovery_state_changed_cb =
+					discovery_cancel_state_changed_cb,
+	.expected_hal_cb.device_found_cb = device_found_cancel_cb,
+	.set_num_of_remote = 98,
+	.expected_device_found_num = 50,
+	.expected_cb_count = 4,
+	.expected_adapter_status = BT_STATUS_NOT_EXPECTED,
+};
+
 static char remote_get_properties_bdname_val[] = "00:AA:01:01:00:00";
 static uint32_t remote_get_properties_cod_val = 0;
 static bt_device_type_t remote_get_properties_tod_val = BT_DEVICE_DEVTYPE_BREDR;
@@ -2052,6 +2113,25 @@ static void setup_enabled_adapter(const void *test_data)
 		tester_setup_failed();
 }
 
+static void setup_enable_adapter_add_remote(const void *test_data)
+{
+	struct test_data *data = tester_get_data();
+	const struct generic_data *test = test_data;
+	GList *l;
+	int i;
+
+	/* Setup some more remote devices if needed */
+	i = hciemu_add_remote_devs(data->hciemu, test->set_num_of_remote);
+	if (i != test->set_num_of_remote)
+		tester_setup_failed();
+
+	tester_print("Created %d remote devices", i);
+	l = hciemu_get_remote_devs(data->hciemu);
+	g_list_foreach(l, enable_and_set_discoverable, NULL);
+
+	setup_enabled_adapter(test_data);
+}
+
 static void teardown(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
@@ -2406,6 +2486,18 @@ static bool pre_inq_compl_hook(const void *dummy, uint16_t len, void *user_data)
 	return false;
 }
 
+static bool post_inq_cancel_hook(const void *dummy, uint16_t len,
+							void *user_data)
+{
+	struct test_data *data = tester_get_data();
+
+	hciemu_del_hook(data->hciemu, HCIEMU_HOOK_POST_CMD,
+						BT_HCI_CMD_INQUIRY_CANCEL);
+
+	data->cb_count--;
+	return true;
+}
+
 static void test_discovery_stop_success(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
@@ -2430,6 +2522,20 @@ static void test_discovery_start_done(const void *test_data)
 	data->if_bluetooth->start_discovery();
 }
 
+static void test_discovery_device_cancel(const void *test_data)
+{
+	struct test_data *data = tester_get_data();
+
+	init_test_conditions(data);
+
+	/* Need this hook to check if inquiry cancel reached btdev */
+	hciemu_add_hook(data->hciemu, HCIEMU_HOOK_POST_CMD,
+						BT_HCI_CMD_INQUIRY_CANCEL,
+						post_inq_cancel_hook, data);
+
+	data->if_bluetooth->start_discovery();
+}
+
 static void test_discovery_device_found(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
@@ -3764,6 +3870,11 @@ int main(int argc, char *argv[])
 				setup_enabled_adapter,
 				test_discovery_device_found, teardown);
 
+	test_bredrle("Bluetooth BR/EDR Discovery Cancel",
+				&bluetooth_discovery_cancel_test,
+				setup_enable_adapter_add_remote,
+				test_discovery_device_cancel, teardown);
+
 	test_bredrle("Bluetooth Device Get Props - Success",
 					&bt_dev_getprops_success_test,
 					setup_enabled_adapter,
-- 
1.8.4


^ permalink raw reply related

* [PATCH 13/17] android/tester: Remove not needed hook for inquiry complete
From: Lukasz Rymanowski @ 2014-02-26  1:57 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Lukasz Rymanowski
In-Reply-To: <1393379848-4031-1-git-send-email-lukasz.rymanowski@tieto.com>

Inquiry is scheduled with timeout so there is no need to hook
before inquiry complete. It influence those tests cases:
"Bluetooth BR/EDR Discovery Start - Success".
"Bluetooth BR/EDR Discovery Stop - Success".
---
 android/android-tester.c | 17 -----------------
 1 file changed, 17 deletions(-)

diff --git a/android/android-tester.c b/android/android-tester.c
index c6484bf..65516c1 100644
--- a/android/android-tester.c
+++ b/android/android-tester.c
@@ -2475,17 +2475,6 @@ static void test_discovery_stop_done(const void *test_data)
 	check_expected_status(status);
 }
 
-static bool pre_inq_compl_hook(const void *dummy, uint16_t len, void *user_data)
-{
-	struct test_data *data = tester_get_data();
-
-	/* Make sure Inquiry Command Complete is not called */
-
-	hciemu_del_hook(data->hciemu, HCIEMU_HOOK_PRE_EVT, BT_HCI_CMD_INQUIRY);
-
-	return false;
-}
-
 static bool post_inq_cancel_hook(const void *dummy, uint16_t len,
 							void *user_data)
 {
@@ -2504,9 +2493,6 @@ static void test_discovery_stop_success(const void *test_data)
 
 	init_test_conditions(data);
 
-	hciemu_add_hook(data->hciemu, HCIEMU_HOOK_PRE_EVT, BT_HCI_CMD_INQUIRY,
-					pre_inq_compl_hook, data);
-
 	data->if_bluetooth->start_discovery();
 }
 
@@ -2516,9 +2502,6 @@ static void test_discovery_start_done(const void *test_data)
 
 	init_test_conditions(data);
 
-	hciemu_add_hook(data->hciemu, HCIEMU_HOOK_PRE_EVT, BT_HCI_CMD_INQUIRY,
-					pre_inq_compl_hook, data);
-
 	data->if_bluetooth->start_discovery();
 }
 
-- 
1.8.4


^ permalink raw reply related

* [PATCH 14/17] android/tester: Increase timeout for test failure
From: Lukasz Rymanowski @ 2014-02-26  1:57 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Lukasz Rymanowski
In-Reply-To: <1393379848-4031-1-git-send-email-lukasz.rymanowski@tieto.com>

Inquiry command is sent with inquiry lenght 10.24 sec. There are
testcases where that time is needed to end the test, therefore change
timeout to 12 sec (number choosed based on strong feelings ;))
---
 android/android-tester.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/android/android-tester.c b/android/android-tester.c
index 65516c1..b09834a 100644
--- a/android/android-tester.c
+++ b/android/android-tester.c
@@ -3707,7 +3707,7 @@ static void test_hidhost_get_report(const void *test_data)
 		user->test_data = data; \
 		tester_add_full(name, data, test_pre_setup, test_setup, \
 				test, test_teardown, test_post_teardown, \
-							3, user, g_free); \
+							12, user, g_free); \
 	} while (0)
 
 int main(int argc, char *argv[])
-- 
1.8.4


^ permalink raw reply related

* [PATCH 15/17] android: Add tracking for pending confirm name command
From: Lukasz Rymanowski @ 2014-02-26  1:57 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Lukasz Rymanowski
In-Reply-To: <1393379848-4031-1-git-send-email-lukasz.rymanowski@tieto.com>

This is usefull in case we want to cancel discovery during
big inflow on device found events.
---
 android/bluetooth.c | 32 ++++++++++++++++++++++++++++----
 1 file changed, 28 insertions(+), 4 deletions(-)

diff --git a/android/bluetooth.c b/android/bluetooth.c
index 7f37590..e0bc730 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -96,6 +96,8 @@ struct device {
 	GSList *uuids;
 
 	bool found; /* if device is found in current discovery session */
+	unsigned int confirm_id; /* mgtm command id if command pending */
+
 };
 
 struct browse_req {
@@ -315,6 +317,9 @@ static struct device *find_device(const bdaddr_t *bdaddr)
 
 static void free_device(struct device *dev)
 {
+	if (dev->confirm_id)
+		mgmt_cancel(mgmt_if, dev->confirm_id);
+
 	g_free(dev->name);
 	g_free(dev->friendly_name);
 	g_slist_free_full(dev->uuids, g_free);
@@ -1020,10 +1025,24 @@ static void mgmt_discovering_event(uint16_t index, uint16_t length,
 			HAL_EV_DISCOVERY_STATE_CHANGED, sizeof(cp), &cp);
 }
 
-static void confirm_device_name(const bdaddr_t *addr, uint8_t addr_type,
+static void confirm_device_name_cb(uint8_t status, uint16_t length,
+					const void *param, void *user_data)
+{
+	const struct mgmt_rp_confirm_name *rp = param;
+	struct device *dev;
+
+	dev = find_device(&rp->addr.bdaddr);
+	if (!dev)
+		return;
+
+	dev->confirm_id = 0;
+}
+
+static unsigned int confirm_device_name(const bdaddr_t *addr, uint8_t addr_type,
 							bool resolve_name)
 {
 	struct mgmt_cp_confirm_name cp;
+	unsigned int res;
 
 	memset(&cp, 0, sizeof(cp));
 	bacpy(&cp.addr.bdaddr, addr);
@@ -1032,9 +1051,13 @@ static void confirm_device_name(const bdaddr_t *addr, uint8_t addr_type,
 	if (!resolve_name)
 		cp.name_known = 1;
 
-	if (mgmt_reply(mgmt_if, MGMT_OP_CONFIRM_NAME, adapter.index,
-				sizeof(cp), &cp, NULL, NULL, NULL) == 0)
+	res = mgmt_reply(mgmt_if, MGMT_OP_CONFIRM_NAME, adapter.index,
+				sizeof(cp), &cp, confirm_device_name_cb,
+				NULL, NULL);
+	if (!res)
 		error("Failed to send confirm name request");
+
+	return res;
 }
 
 static int fill_hal_prop(void *buf, uint8_t type, uint16_t len,
@@ -1204,7 +1227,8 @@ static void update_found_device(const bdaddr_t *bdaddr, uint8_t bdaddr_type,
 
 		info("Device %s needs name confirmation (resolve_name=%d)",
 							addr, resolve_name);
-		confirm_device_name(bdaddr, bdaddr_type, resolve_name);
+		dev->confirm_id = confirm_device_name(bdaddr, bdaddr_type,
+								resolve_name);
 	}
 }
 
-- 
1.8.4


^ permalink raw reply related

* [PATCH 16/17] android: Cancel all pending confirm name before stop discovery
From: Lukasz Rymanowski @ 2014-02-26  1:57 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Lukasz Rymanowski
In-Reply-To: <1393379848-4031-1-git-send-email-lukasz.rymanowski@tieto.com>

Make sure there is nothing outstdanign related to discovery before
sending stop discovery.

It is also in order to make sure that stop discovery have a free way to
get the kernel.
---
 android/bluetooth.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/android/bluetooth.c b/android/bluetooth.c
index e0bc730..fb33976 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -2456,6 +2456,14 @@ static bool start_discovery(void)
 	return false;
 }
 
+static void cancel_pending_confirm_name(gpointer data, gpointer user_data)
+{
+	struct device *dev = data;
+
+	mgmt_cancel(mgmt_if, dev->confirm_id);
+	dev->confirm_id = 0;
+}
+
 static bool stop_discovery(void)
 {
 	struct mgmt_cp_stop_discovery cp;
@@ -2468,6 +2476,9 @@ static bool stop_discovery(void)
 
 	DBG("type=0x%x", type);
 
+	/* Lets drop all confirm name request as we don't need it anymore */
+	g_slist_foreach(cached_devices, cancel_pending_confirm_name, NULL);
+
 	if (mgmt_send(mgmt_if, MGMT_OP_STOP_DISCOVERY, adapter.index,
 					sizeof(cp), &cp, NULL, NULL, NULL) > 0)
 		return true;
-- 
1.8.4


^ permalink raw reply related

* [PATCH 17/17] android: Send confirm name request with mgmt_send
From: Lukasz Rymanowski @ 2014-02-26  1:57 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Lukasz Rymanowski
In-Reply-To: <1393379848-4031-1-git-send-email-lukasz.rymanowski@tieto.com>

This patch is needed in scenarios when there is a big inflow of device found
events and we want to cancel discovery. In such case number of confirm
name commands might block mgmt queses and don't let stop discovery to pass
thru.

Even we cancel previous confirm name commands, stop discovery might
still get on the end of line.
---
 android/bluetooth.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/android/bluetooth.c b/android/bluetooth.c
index fb33976..5cb0e78 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -1051,7 +1051,7 @@ static unsigned int confirm_device_name(const bdaddr_t *addr, uint8_t addr_type,
 	if (!resolve_name)
 		cp.name_known = 1;
 
-	res = mgmt_reply(mgmt_if, MGMT_OP_CONFIRM_NAME, adapter.index,
+	res = mgmt_send(mgmt_if, MGMT_OP_CONFIRM_NAME, adapter.index,
 				sizeof(cp), &cp, confirm_device_name_cb,
 				NULL, NULL);
 	if (!res)
-- 
1.8.4


^ permalink raw reply related

* Re: [PATCH 03/17] Bluetooth: Stop scanning on LE connection
From: Marcel Holtmann @ 2014-02-26  6:23 UTC (permalink / raw)
  To: Andre Guedes; +Cc: linux-bluetooth
In-Reply-To: <1393362104-12175-4-git-send-email-andre.guedes@openbossa.org>

Hi Andre,

> Some LE controllers don't support scanning and creating a connection
> at the same time. So we should always stop scanning in order to
> establish the connection.
> 
> Since we may prematurely stop the discovery procedure in favor of
> the connection establishment, we should also cancel hdev->le_scan_
> disable delayed work and set the discovery state to DISCOVERY_STOPPED.
> 
> This change does a small improvement since it is not mandatory the
> user stops scanning before connecting anymore. Moreover, this change
> is required by upcoming LE auto connection mechanism in order to work
> properly with controllers that don't support background scanning and
> connection establishment at the same time.
> 
> In future, we might want to do a small optimization by checking if
> controller is able to scan and connect at the same time. For now,
> we want the simplest approach so we always stop scanning (even if
> the controller is able to carry out both operations).
> 
> Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
> ---
> include/net/bluetooth/hci.h |  1 +
> net/bluetooth/hci_conn.c    | 89 ++++++++++++++++++++++++++++++++++++++++++++-
> 2 files changed, 88 insertions(+), 2 deletions(-)
> 
> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
> index 1bb45a4..c3834d3 100644
> --- a/include/net/bluetooth/hci.h
> +++ b/include/net/bluetooth/hci.h
> @@ -356,6 +356,7 @@ enum {
> 
> /* ---- HCI Error Codes ---- */
> #define HCI_ERROR_AUTH_FAILURE		0x05
> +#define HCI_ERROR_MEMORY_EXCEEDED	0x07
> #define HCI_ERROR_CONNECTION_TIMEOUT	0x08
> #define HCI_ERROR_REJ_BAD_ADDR		0x0f
> #define HCI_ERROR_REMOTE_USER_TERM	0x13
> diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
> index dc8aad9..ae2c3e1 100644
> --- a/net/bluetooth/hci_conn.c
> +++ b/net/bluetooth/hci_conn.c
> @@ -594,12 +594,83 @@ static int hci_create_le_conn(struct hci_conn *conn)
> 	return 0;
> }
> 
> +static void hci_req_add_le_create_conn(struct hci_request *req,
> +				       struct hci_conn *conn)
> +{
> +	struct hci_cp_le_create_conn cp;
> +	struct hci_dev *hdev = conn->hdev;
> +	u8 own_addr_type;
> +
> +	memset(&cp, 0, sizeof(cp));
> +
> +	/* Update random address, but set require_privacy to false so
> +	 * that we never connect with an unresolvable address.
> +	 */
> +	if (hci_update_random_address(req, false, &own_addr_type))
> +		return;
> +
> +	conn->src_type = own_addr_type;
> +
> +	cp.scan_interval = cpu_to_le16(hdev->le_scan_interval);
> +	cp.scan_window = cpu_to_le16(hdev->le_scan_window);
> +	bacpy(&cp.peer_addr, &conn->dst);
> +	cp.peer_addr_type = conn->dst_type;
> +	cp.own_address_type = conn->src_type;

the reason why you get the own_addr_type when setting the random address is to actually use it here.

This is important since in cases where LE Privacy is enabled and we are using RPA, we want the random address used.

Regards

Marcel


^ permalink raw reply

* Re: [PATCH 08/17] Bluetooth: Introduce LE auto connection infrastructure
From: Marcel Holtmann @ 2014-02-26  6:31 UTC (permalink / raw)
  To: Andre Guedes; +Cc: linux-bluetooth
In-Reply-To: <1393362104-12175-9-git-send-email-andre.guedes@openbossa.org>

Hi Andre,

> This patch introduces the LE auto connection infrastructure which
> will be used to implement the LE auto connection options.
> 
> In summary, the auto connection mechanism works as follows: Once the
> first pending LE connection is created, the background scanning is
> started. When the target device is found in range, the kernel
> autonomously starts the connection attempt. If connection is
> established successfully, that pending LE connection is deleted and
> the background is stopped.
> 
> To achieve that, this patch introduces the hci_update_background_scan()
> which controls the background scanning state. This function starts or
> stops the background scanning based on the hdev->pend_le_conns list. If
> there is no pending LE connection, the background scanning is stopped.
> Otherwise, we start the background scanning.
> 
> Then, every time a pending LE connection is added we call hci_update_
> background_scan() so the background scanning is started (in case it is
> not already running). Likewise, every time a pending LE connection is
> deleted we call hci_update_background_scan() so the background scanning
> is stopped (in case this was the last pending LE connection) or it is
> started again (in case we have more pending LE connections). Finally,
> we also call hci_update_background_scan() in hci_le_conn_failed() so
> the background scan is restarted in case the connection establishment
> fails. This way the background scanning keeps running until all pending
> LE connection are established.
> 
> At this point, resolvable addresses are not support by this
> infrastructure. The proper support is added in upcoming patches.
> 
> Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
> ---
> include/net/bluetooth/hci_core.h |  2 +
> net/bluetooth/hci_conn.c         |  5 +++
> net/bluetooth/hci_core.c         | 93 +++++++++++++++++++++++++++++++++++++++-
> net/bluetooth/hci_event.c        | 38 ++++++++++++++++
> 4 files changed, 136 insertions(+), 2 deletions(-)
> 
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index e08405d..617cf49 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -806,6 +806,8 @@ void hci_pend_le_conn_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type);
> void hci_pend_le_conn_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type);
> void hci_pend_le_conns_clear(struct hci_dev *hdev);
> 
> +void hci_update_background_scan(struct hci_dev *hdev);
> +
> void hci_uuids_clear(struct hci_dev *hdev);
> 
> void hci_link_keys_clear(struct hci_dev *hdev);
> diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
> index ccf4a4f..e79351c 100644
> --- a/net/bluetooth/hci_conn.c
> +++ b/net/bluetooth/hci_conn.c
> @@ -527,6 +527,11 @@ void hci_le_conn_failed(struct hci_conn *conn, u8 status)
> 	hci_proto_connect_cfm(conn, status);
> 
> 	hci_conn_del(conn);
> +
> +	/* Since we may have temporarily stopped the background scanning in
> +	 * favor of connection establishment, we should restart it.
> +	 */
> +	hci_update_background_scan(hdev);
> }
> 
> static void create_le_conn_complete(struct hci_dev *hdev, u8 status)
> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> index 142ecd8..d242217 100644
> --- a/net/bluetooth/hci_core.c
> +++ b/net/bluetooth/hci_core.c
> @@ -3281,7 +3281,7 @@ void hci_pend_le_conn_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type)
> 
> 	entry = hci_pend_le_conn_lookup(hdev, addr, addr_type);
> 	if (entry)
> -		return;
> +		goto done;
> 
> 	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
> 	if (!entry) {
> @@ -3295,6 +3295,9 @@ void hci_pend_le_conn_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type)
> 	list_add(&entry->list, &hdev->pend_le_conns);
> 
> 	BT_DBG("addr %pMR (type %u)", addr, addr_type);
> +
> +done:
> +	hci_update_background_scan(hdev);
> }
> 
> /* This function requires the caller holds hdev->lock */
> @@ -3304,12 +3307,15 @@ void hci_pend_le_conn_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type)
> 
> 	entry = hci_pend_le_conn_lookup(hdev, addr, addr_type);
> 	if (!entry)
> -		return;
> +		goto done;
> 
> 	list_del(&entry->list);
> 	kfree(entry);
> 
> 	BT_DBG("addr %pMR (type %u)", addr, addr_type);
> +
> +done:
> +	hci_update_background_scan(hdev);
> }
> 
> /* This function requires the caller holds hdev->lock */
> @@ -4946,3 +4952,86 @@ void hci_req_add_le_scan_disable(struct hci_request *req)
> 	cp.enable = LE_SCAN_DISABLE;
> 	hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
> }
> +
> +static void update_background_scan_complete(struct hci_dev *hdev, u8 status)
> +{
> +	if (status)
> +		BT_DBG("HCI request failed to update background scanning: "
> +		       "status 0x%2.2x", status);
> +}
> +
> +/* This function controls the background scanning based on hdev->pend_le_conns
> + * list. If there are pending LE connection we start the background scanning,
> + * otherwise we stop it.
> + *
> + * This function requires the caller holds hdev->lock.
> + */
> +void hci_update_background_scan(struct hci_dev *hdev)
> +{
> +	struct hci_cp_le_set_scan_param param_cp;
> +	struct hci_cp_le_set_scan_enable enable_cp;
> +	struct hci_request req;
> +	struct hci_conn *conn;
> +	int err;
> +
> +	hci_req_init(&req, hdev);
> +
> +	if (list_empty(&hdev->pend_le_conns)) {
> +		/* If there is no pending LE connections, we should stop
> +		 * the background scanning.
> +		 */
> +
> +		/* If controller is not scanning we are done. */
> +		if (!test_bit(HCI_LE_SCAN, &hdev->dev_flags))
> +			return;
> +
> +		hci_req_add_le_scan_disable(&req);
> +
> +		BT_DBG("%s stopping background scanning", hdev->name);
> +	} else {
> +		u8 own_addr_type;
> +
> +		/* If there is at least one pending LE connection, we should
> +		 * keep the background scan running.
> +		 */
> +
> +		/* If controller is already scanning we are done. */
> +		if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
> +			return;
> +
> +		/* If controller is connecting, we should not start scanning
> +		 * since some controllers are not able to scan and connect at
> +		 * the same time.
> +		 */
> +		conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
> +		if (conn)
> +			return;
> +
> +		/* Use private address since remote doesn't need to identify us.
> +		 * Strictly speaking, this is not required since no SCAN_REQ is
> +		 * sent in passive scanning.
> +		 */
> +		if (hci_update_random_address(&req, true, &own_addr_type))
> +			return;

the comment above is confusing. Reason is simple. We might use a RPA if LE Privacy has been enabled. The require_privacy == true will fallback to URPA in case privacy is not enabled. If privacy is enabled, then no matter what require_privacy is set to, we will use a random address.

It should say something along the lines of this:

	/* Set require_privacy to true to avoid identification from
	 * unknown peer devices. Since this is passive scanning, no
	 * SCAN_REQ using the local identity should be sent. Mandating
	 * privacy is just an extra precaution.
	 */

Regards

Marcel


^ permalink raw reply

* Re: [PATCH 10/17] Bluetooth: Connection parameters and auto connection
From: Marcel Holtmann @ 2014-02-26  6:33 UTC (permalink / raw)
  To: Andre Guedes; +Cc: linux-bluetooth
In-Reply-To: <1393362104-12175-11-git-send-email-andre.guedes@openbossa.org>

Hi Andre,

> This patch modifies hci_conn_params_add() and hci_conn_params_del() so
> they also add/delete pending LE connections according to the auto_
> connect option. This way, background scan is automatically triggered/
> untriggered when connection parameters are added/removed.
> 
> For instance, when a new connection parameters with HCI_AUTO_CONN_ALWAYS
> option is added and we are not connected to the device, we add a pending
> LE connection for that device.
> 
> Likewise, when the connection parameters are updated we add or delete
> a pending LE connection according to its new auto_connect option.
> 
> Finally, when the connection parameter is deleted we also delete the
> pending LE connection (if any).

what about disconnecting an existing connection for a device we have in our auto-connect list. I think that should happen as well.

Regards

Marcel


^ permalink raw reply

* Re: [PATCH 13/17] Bluetooth: Connection parameters and resolvable address
From: Marcel Holtmann @ 2014-02-26  6:37 UTC (permalink / raw)
  To: Andre Guedes; +Cc: linux-bluetooth
In-Reply-To: <1393362104-12175-14-git-send-email-andre.guedes@openbossa.org>

Hi Andre,

> We should only add connection parameters for public, random static and
> random private resolvable with IRK. If we allow non-resolvable or
> resolvable without IRK, the background scan may run indefinitely. So, to
> avoid this undesired behavior, we should check the address type in
> hci_conn_params_add().

this makes no sense. We should only allow auto-connection from public and static random addresses. These two are identity addresses.

Every IRK has an identity address assigned to it. If you want to auto-connect a device using a resolvable private address, then the identity address needs to be programmed into our auto-connection list. The RPA should never ever go there.

That is how connect() works actually. You give it the identity address and it will use the IRK to match it to the RPA in use. We need to do exactly the same.

In addition please keep in mind that userspace only knows about RPA as long as they are not identified. Once they are identified, the kernel will only tell us about identity addresses. The RPA will be in all mgmt commands and events automatically resolved.

Regards

Marcel


^ permalink raw reply

* Re: [PATCH 15/17] Bluetooth: Add le_auto_conn file on debugfs
From: Marcel Holtmann @ 2014-02-26  6:41 UTC (permalink / raw)
  To: Andre Guedes; +Cc: linux-bluetooth
In-Reply-To: <1393362104-12175-16-git-send-email-andre.guedes@openbossa.org>

Hi Andre,

> This patch adds to debugfs the le_auto_conn file. This file will be
> used to test LE auto connection infrastructure.
> 
> To add a new auto connection address we write on le_auto_conn file
> following the format <address> <address type> <auto_connect>.
> 
> The <address type> values are:
>  * 0 for public address
>  * 1 for random address
> 
> The <auto_connect> values are (for more details see struct hci_
> conn_params):
>  * 0 for disabled
>  * 1 for always
>  * 2 for link loss
> 
> So for instance, if you want the kernel autonomously establishes
> connections with device AA:BB:CC:DD:EE:FF (public address) every
> time the device enters in connectable mode (starts advertising),
> you should run the command:
> $ echo "AA:BB:CC:DD:EE:FF 0 1" > /sys/kernel/debug/bluetooth/hci0/le_auto_conn
> 
> To get the list of connection parameters configured in kernel, read
> the le_auto_conn file:
> $ cat /sys/kernel/debug/bluetooth/hci0/le_auto_conn
> 
> Finally, to clear the connection parameters list, write an empty
> string:
> $ echo "" > /sys/kernel/debug/bluetooth/hci0/le_auto_conn
> 
> This file is created only if LE is enabled.

I wonder if this should be prefixed with a command. For example like this:

	“add <address> <address_type> [auto_connect]”
	“del <address> <address_type>”
	“clr”

Regards

Marcel


^ permalink raw reply

* Re: [PATCH 16/17] Bluetooth: Create hci_req_add_le_passive_scan helper
From: Marcel Holtmann @ 2014-02-26  6:44 UTC (permalink / raw)
  To: Andre Guedes; +Cc: linux-bluetooth
In-Reply-To: <1393362104-12175-17-git-send-email-andre.guedes@openbossa.org>

Hi Andre,

> This patches creates the hci_req_add_le_passive_scan helper so it can
> be re-used in the next patch.
> 
> Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
> ---
> net/bluetooth/hci_core.c | 54 +++++++++++++++++++++++++++---------------------
> 1 file changed, 30 insertions(+), 24 deletions(-)
> 
> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> index fb4c961..e776624 100644
> --- a/net/bluetooth/hci_core.c
> +++ b/net/bluetooth/hci_core.c
> @@ -5095,6 +5095,35 @@ void hci_req_add_le_scan_disable(struct hci_request *req)
> 	hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
> }
> 
> +static void hci_req_add_le_passive_scan(struct hci_request *req,
> +					struct hci_dev *hdev)
> +{

	struct hci_dev *hdev = req->hdev;

Regards

Marcel


^ permalink raw reply

* Re: [PATCH 17/17] Bluetooth: Update background scan parameters
From: Marcel Holtmann @ 2014-02-26  6:47 UTC (permalink / raw)
  To: Andre Guedes; +Cc: linux-bluetooth
In-Reply-To: <1393362104-12175-18-git-send-email-andre.guedes@openbossa.org>

Hi Andre,

> If new scanning parameters are set while background scan is running,
> we should restart background scanning so these parameters are updated.
> 
> Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
> ---
> include/net/bluetooth/hci_core.h |  1 +
> net/bluetooth/hci_core.c         | 26 ++++++++++++++++++++++++++
> net/bluetooth/mgmt.c             |  7 +++++++
> 3 files changed, 34 insertions(+)
> 
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index e0e0eab..8f0ddc8 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -814,6 +814,7 @@ void hci_pend_le_conn_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type);
> void hci_pend_le_conns_clear(struct hci_dev *hdev);
> 
> void hci_update_background_scan(struct hci_dev *hdev);
> +void hci_restart_background_scan(struct hci_dev *hdev);
> 
> void hci_uuids_clear(struct hci_dev *hdev);
> 
> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> index e776624..f5c0e97 100644
> --- a/net/bluetooth/hci_core.c
> +++ b/net/bluetooth/hci_core.c
> @@ -5183,3 +5183,29 @@ void hci_update_background_scan(struct hci_dev *hdev)
> 	if (err)
> 		BT_ERR("Failed to run HCI request: err %d", err);
> }
> +
> +static void restart_background_scan_complete(struct hci_dev *hdev, u8 status)
> +{
> +	if (status)
> +		BT_DBG("HCI request failed to restart background scan: "
> +		       "status 0x%2.2x", status);
> +}
> +
> +void hci_restart_background_scan(struct hci_dev *hdev)
> +{
> +	struct hci_request req;
> +	int err;
> +
> +	hci_req_init(&req, hdev);
> +
> +	hci_req_add_le_scan_disable(&req);
> +	hci_req_add_le_passive_scan(&req, hdev);
> +
> +	err = hci_req_run(&req, restart_background_scan_complete);
> +	if (err) {
> +		BT_ERR("Failed to run HCI request: err %d", err);
> +		return;
> +	}
> +
> +	BT_DBG("%s re-starting background scanning", hdev->name);
> +}
> diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
> index 2e6564e..08d52f2 100644
> --- a/net/bluetooth/mgmt.c
> +++ b/net/bluetooth/mgmt.c
> @@ -3924,6 +3924,13 @@ static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
> 
> 	err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
> 
> +	/* If background scan is running, restart it so new parameters are
> +	 * loaded.
> +	 */
> +	if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
> +	    hdev->discovery.state == DISCOVERY_STOPPED)
> +		hci_restart_background_scan(hdev);
> +

unless there are some other plans, then put the hci_req directly into the body of the if statement. No need to split this out into a public function. And even you want to use this later, I rather see this confined right now and keep public function to a minimum.

Regards

Marcel


^ permalink raw reply

* Re: [PATCH 2/3] android/avrcp: Add control handlers to avrcp-lib
From: Andrei Emeltchenko @ 2014-02-26  7:56 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <CABBYNZJGQJ9e7+0M_-kQGn=G3648ZRNuwULg+rKQ+tZXEehDkA@mail.gmail.com>

Hi Luiz,

On Tue, Feb 25, 2014 at 04:19:53PM +0200, Luiz Augusto von Dentz wrote:
> Hi Andrei,
> 
> On Tue, Feb 25, 2014 at 3:56 PM, Andrei Emeltchenko
> <Andrei.Emeltchenko.news@gmail.com> wrote:
> > From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> >
> > ---
> >  android/avrcp-lib.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++
> >  android/avrcp-lib.h | 12 +++++++++++
> >  2 files changed, 72 insertions(+)
> >
> > diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
> > index 136801e..95e10f2 100644
> > --- a/android/avrcp-lib.c
> > +++ b/android/avrcp-lib.c
> > @@ -56,6 +56,15 @@
> >  #define AVRCP_PACKET_TYPE_CONTINUING   0x02
> >  #define AVRCP_PACKET_TYPE_END          0x03
> >
> > +/* Capabilities for AVRCP_GET_CAPABILITIES pdu */
> > +#define CAP_COMPANY_ID         0x02
> > +#define CAP_EVENTS_SUPPORTED   0x03
> > +
> > +/* Company IDs supported by this device */
> > +static uint32_t company_ids[] = {
> > +       IEEEID_BTSIG,
> > +};
> > +
> >  #if __BYTE_ORDER == __LITTLE_ENDIAN
> >
> >  struct avrcp_header {
> > @@ -108,6 +117,8 @@ struct avrcp {
> >         const struct avrcp_passthrough_handler *passthrough_handlers;
> >         void *passthrough_data;
> >         unsigned int passthrough_id;
> > +
> > +       uint16_t supported_events;
> >  };
> >
> >  void avrcp_shutdown(struct avrcp *session)
> > @@ -220,6 +231,53 @@ static void set_company_id(uint8_t cid[3], const uint32_t cid_in)
> >         cid[2] = cid_in;
> >  }
> >
> > +static uint8_t avrcp_handle_get_capabilities(struct avrcp *session,
> > +                               uint8_t transaction, uint16_t *params_len,
> > +                               uint8_t *params, void *user_data)
> > +{
> > +       unsigned int i;
> > +
> > +       DBG("id %d params_len %d", params[0], *params_len);
> > +
> > +       if (*params_len != 1)
> > +               goto fail;
> > +
> > +       switch (params[0]) {
> > +       case CAP_COMPANY_ID:
> > +               for (i = 0; i < G_N_ELEMENTS(company_ids); i++)
> > +                       set_company_id(&params[2 + i * 3], company_ids[i]);
> > +
> > +               *params_len = 2 + (3 * G_N_ELEMENTS(company_ids));
> > +               params[1] = G_N_ELEMENTS(company_ids);
> > +
> > +               return AVC_CTYPE_STABLE;
> > +       case CAP_EVENTS_SUPPORTED:
> > +               params[1] = 0;
> > +               for (i = 1; i <= AVRCP_EVENT_LAST; i++) {
> > +                       if (session->supported_events & (1 << i)) {
> > +                               params[1]++;
> > +                               params[params[1] + 1] = i;
> > +                       }
> > +               }
> > +
> > +               *params_len = 2 + params[1];
> > +
> > +               return AVC_CTYPE_STABLE;
> > +       }
> > +
> > +fail:
> > +       *params_len = htons(1);
> > +       params[0] = AVRCP_STATUS_INVALID_PARAM;
> > +
> > +       return AVC_CTYPE_REJECTED;
> > +}
> > +
> > +static const struct avrcp_control_handler control_handlers[] = {
> > +               { AVRCP_GET_CAPABILITIES, AVC_CTYPE_STATUS,
> > +                                       avrcp_handle_get_capabilities },
> > +               { },
> > +};
> > +
> >  struct avrcp *avrcp_new(int fd, size_t imtu, size_t omtu, uint16_t version)
> >  {
> >         struct avrcp *session;
> > @@ -241,6 +299,8 @@ struct avrcp *avrcp_new(int fd, size_t imtu, size_t omtu, uint16_t version)
> >                                                         handle_vendordep_pdu,
> >                                                         session);
> >
> > +       avrcp_set_control_handlers(session, control_handlers, NULL);
> > +
> >         return session;
> >  }
> >
> > diff --git a/android/avrcp-lib.h b/android/avrcp-lib.h
> > index 4f3a632..0821287 100644
> > --- a/android/avrcp-lib.h
> > +++ b/android/avrcp-lib.h
> > @@ -46,6 +46,18 @@
> >  #define AVRCP_ADD_TO_NOW_PLAYING       0x90
> >  #define AVRCP_GENERAL_REJECT           0xA0
> >
> > +/* Notification events */
> > +#define AVRCP_EVENT_STATUS_CHANGED             0x01
> > +#define AVRCP_EVENT_TRACK_CHANGED              0x02
> > +#define AVRCP_EVENT_TRACK_REACHED_END          0x03
> > +#define AVRCP_EVENT_TRACK_REACHED_START                0x04
> > +#define AVRCP_EVENT_SETTINGS_CHANGED           0x08
> > +#define AVRCP_EVENT_AVAILABLE_PLAYERS_CHANGED  0x0a
> > +#define AVRCP_EVENT_ADDRESSED_PLAYER_CHANGED   0x0b
> > +#define AVRCP_EVENT_UIDS_CHANGED               0x0c
> > +#define AVRCP_EVENT_VOLUME_CHANGED             0x0d
> > +#define AVRCP_EVENT_LAST                       AVRCP_EVENT_VOLUME_CHANGED
> > +
> >  struct avrcp;
> >
> >  struct avrcp_control_handler {
> > --
> > 1.8.3.2
> 
> That is the actual AVRCP implementation not the library, the library
> only offer means to handle the commands but don't parse it there since
> we can't do anything with it. For unit tests you can implement dummy
> handlers as we did for passthrough.

I can implement dummy handlers but this would mean that we are testing
that dummy handlers. Is the idea to test actual production code?

Best regards 
Andrei Emeltchenko 

^ permalink raw reply

* Re: [PATCH 2/3] android/avrcp: Add control handlers to avrcp-lib
From: Luiz Augusto von Dentz @ 2014-02-26  8:16 UTC (permalink / raw)
  To: Andrei Emeltchenko, Luiz Augusto von Dentz,
	linux-bluetooth@vger.kernel.org
In-Reply-To: <20140226075632.GA29630@aemeltch-MOBL1>

Hi Andrei,

On Wed, Feb 26, 2014 at 9:56 AM, Andrei Emeltchenko
<Andrei.Emeltchenko.news@gmail.com> wrote:
> Hi Luiz,
>
> On Tue, Feb 25, 2014 at 04:19:53PM +0200, Luiz Augusto von Dentz wrote:
>> Hi Andrei,
>>
>> On Tue, Feb 25, 2014 at 3:56 PM, Andrei Emeltchenko
>> <Andrei.Emeltchenko.news@gmail.com> wrote:
>> > From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
>> >
>> > ---
>> >  android/avrcp-lib.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>> >  android/avrcp-lib.h | 12 +++++++++++
>> >  2 files changed, 72 insertions(+)
>> >
>> > diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
>> > index 136801e..95e10f2 100644
>> > --- a/android/avrcp-lib.c
>> > +++ b/android/avrcp-lib.c
>> > @@ -56,6 +56,15 @@
>> >  #define AVRCP_PACKET_TYPE_CONTINUING   0x02
>> >  #define AVRCP_PACKET_TYPE_END          0x03
>> >
>> > +/* Capabilities for AVRCP_GET_CAPABILITIES pdu */
>> > +#define CAP_COMPANY_ID         0x02
>> > +#define CAP_EVENTS_SUPPORTED   0x03
>> > +
>> > +/* Company IDs supported by this device */
>> > +static uint32_t company_ids[] = {
>> > +       IEEEID_BTSIG,
>> > +};
>> > +
>> >  #if __BYTE_ORDER == __LITTLE_ENDIAN
>> >
>> >  struct avrcp_header {
>> > @@ -108,6 +117,8 @@ struct avrcp {
>> >         const struct avrcp_passthrough_handler *passthrough_handlers;
>> >         void *passthrough_data;
>> >         unsigned int passthrough_id;
>> > +
>> > +       uint16_t supported_events;
>> >  };
>> >
>> >  void avrcp_shutdown(struct avrcp *session)
>> > @@ -220,6 +231,53 @@ static void set_company_id(uint8_t cid[3], const uint32_t cid_in)
>> >         cid[2] = cid_in;
>> >  }
>> >
>> > +static uint8_t avrcp_handle_get_capabilities(struct avrcp *session,
>> > +                               uint8_t transaction, uint16_t *params_len,
>> > +                               uint8_t *params, void *user_data)
>> > +{
>> > +       unsigned int i;
>> > +
>> > +       DBG("id %d params_len %d", params[0], *params_len);
>> > +
>> > +       if (*params_len != 1)
>> > +               goto fail;
>> > +
>> > +       switch (params[0]) {
>> > +       case CAP_COMPANY_ID:
>> > +               for (i = 0; i < G_N_ELEMENTS(company_ids); i++)
>> > +                       set_company_id(&params[2 + i * 3], company_ids[i]);
>> > +
>> > +               *params_len = 2 + (3 * G_N_ELEMENTS(company_ids));
>> > +               params[1] = G_N_ELEMENTS(company_ids);
>> > +
>> > +               return AVC_CTYPE_STABLE;
>> > +       case CAP_EVENTS_SUPPORTED:
>> > +               params[1] = 0;
>> > +               for (i = 1; i <= AVRCP_EVENT_LAST; i++) {
>> > +                       if (session->supported_events & (1 << i)) {
>> > +                               params[1]++;
>> > +                               params[params[1] + 1] = i;
>> > +                       }
>> > +               }
>> > +
>> > +               *params_len = 2 + params[1];
>> > +
>> > +               return AVC_CTYPE_STABLE;
>> > +       }
>> > +
>> > +fail:
>> > +       *params_len = htons(1);
>> > +       params[0] = AVRCP_STATUS_INVALID_PARAM;
>> > +
>> > +       return AVC_CTYPE_REJECTED;
>> > +}
>> > +
>> > +static const struct avrcp_control_handler control_handlers[] = {
>> > +               { AVRCP_GET_CAPABILITIES, AVC_CTYPE_STATUS,
>> > +                                       avrcp_handle_get_capabilities },
>> > +               { },
>> > +};
>> > +
>> >  struct avrcp *avrcp_new(int fd, size_t imtu, size_t omtu, uint16_t version)
>> >  {
>> >         struct avrcp *session;
>> > @@ -241,6 +299,8 @@ struct avrcp *avrcp_new(int fd, size_t imtu, size_t omtu, uint16_t version)
>> >                                                         handle_vendordep_pdu,
>> >                                                         session);
>> >
>> > +       avrcp_set_control_handlers(session, control_handlers, NULL);
>> > +
>> >         return session;
>> >  }
>> >
>> > diff --git a/android/avrcp-lib.h b/android/avrcp-lib.h
>> > index 4f3a632..0821287 100644
>> > --- a/android/avrcp-lib.h
>> > +++ b/android/avrcp-lib.h
>> > @@ -46,6 +46,18 @@
>> >  #define AVRCP_ADD_TO_NOW_PLAYING       0x90
>> >  #define AVRCP_GENERAL_REJECT           0xA0
>> >
>> > +/* Notification events */
>> > +#define AVRCP_EVENT_STATUS_CHANGED             0x01
>> > +#define AVRCP_EVENT_TRACK_CHANGED              0x02
>> > +#define AVRCP_EVENT_TRACK_REACHED_END          0x03
>> > +#define AVRCP_EVENT_TRACK_REACHED_START                0x04
>> > +#define AVRCP_EVENT_SETTINGS_CHANGED           0x08
>> > +#define AVRCP_EVENT_AVAILABLE_PLAYERS_CHANGED  0x0a
>> > +#define AVRCP_EVENT_ADDRESSED_PLAYER_CHANGED   0x0b
>> > +#define AVRCP_EVENT_UIDS_CHANGED               0x0c
>> > +#define AVRCP_EVENT_VOLUME_CHANGED             0x0d
>> > +#define AVRCP_EVENT_LAST                       AVRCP_EVENT_VOLUME_CHANGED
>> > +
>> >  struct avrcp;
>> >
>> >  struct avrcp_control_handler {
>> > --
>> > 1.8.3.2
>>
>> That is the actual AVRCP implementation not the library, the library
>> only offer means to handle the commands but don't parse it there since
>> we can't do anything with it. For unit tests you can implement dummy
>> handlers as we did for passthrough.
>
> I can implement dummy handlers but this would mean that we are testing
> that dummy handlers. Is the idea to test actual production code?

Which is fine, the capabilities will anyway depend on the underline
player implementation so a dummy one is fine here, in fact the unit
tests should not care what is the capabilities just that the PDU is
formed correctly.


-- 
Luiz Augusto von Dentz

^ permalink raw reply

* Re: [PATCH 4/4] unit/avrcp: Add /TP/PTT/BV-05-I test
From: Luiz Augusto von Dentz @ 2014-02-26  8:26 UTC (permalink / raw)
  To: Andrei Emeltchenko; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <1393322970-27451-4-git-send-email-Andrei.Emeltchenko.news@gmail.com>

Hi Andrei,

On Tue, Feb 25, 2014 at 12:09 PM, Andrei Emeltchenko
<Andrei.Emeltchenko.news@gmail.com> wrote:
> From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
>
> Test verifies that the Target reacts to the PASS THROUGH command in
> category 1 from the Controller. The command chosen is PLAY (0x44).
> The PLAY button is being pressed and released.
> ---
>  unit/test-avrcp.c | 10 ++++++++++
>  1 file changed, 10 insertions(+)
>
> diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
> index 66f0973..53e9237 100644
> --- a/unit/test-avrcp.c
> +++ b/unit/test-avrcp.c
> @@ -354,5 +354,15 @@ int main(int argc, char *argv[])
>                         raw_pdu(0x02, 0x11, 0x0e, 0x09, 0x48, 0x7c,
>                                 AVC_SELECT, 0x00));
>
> +       define_test("/TP/PTT/BV-05-I", test_server,
> +                       raw_pdu(0x00, 0x11, 0x0e, 0x00, 0x48, 0x7c,
> +                               AVC_PLAY, 0x00),
> +                       raw_pdu(0x02, 0x11, 0x0e, 0x09, 0x48, 0x7c,
> +                               AVC_PLAY, 0x00),
> +                       raw_pdu(0x00, 0x11, 0x0e, 0x00, 0x48, 0x7c,
> +                               AVC_PLAY | 0x80, 0x00),
> +                       raw_pdu(0x02, 0x11, 0x0e, 0x09, 0x48, 0x7c,
> +                               AVC_PLAY | 0x80, 0x00));
> +
>         return g_test_run();
>  }
> --
> 1.8.3.2

Applied, thanks.


-- 
Luiz Augusto von Dentz

^ permalink raw reply

* [PATCHv2 00/23] Add GATT Client Messages
From: Jakub Tyszkowski @ 2014-02-26  8:40 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Jakub Tyszkowski

This patchset adds GATT's Client part of ipc messages data.

v2 changes:
  * moved msg structs and opcodes up to message opcodes section of hal-msg.h
  * fixed typo and renamed few struct members to better match those in HAL hdrs
  * corrected tlv field types
  * [PATCHES 14-23/23] added opcodes and structs for the rest of Client messages

Regards,
Jakub Tyszkowski (23):
  android/hal-gatt-api: Add missing opcodes in GATT Service
  android/hal-gatt-api: Add Client Register
  android/hal-gatt-api: Add Client Unregister
  android/hal-gatt-api: Add Client Scan
  android/hal-gatt-api: Add Client Connect Remote
  android/hal-gatt-api: Add Client Disconnect Remote
  android/hal-gatt-api: Add Client Listen
  android/hal-gatt-api: Add Client Refresh Remote Cache
  android/hal-gatt-api: Add Client Search Service
  android/hal-gatt-api: Add Client Get Included Service
  android/hal-gatt-api: Add Client Get Characteristic
  android/hal-gatt-api: Add Client Get Descriptor
  android/hal-gatt-api: Add Client Read Characteristic
  android/hal-gatt-api: Add Client Write Characteristic
  android/hal-gatt-api: Add Client Read Descriptor
  android/hal-gatt-api: Add Client Write Descriptor
  android/hal-gatt-api: Add Client Execute Write
  android/hal-gatt-api: Add Client Register for Notification
  android/hal-gatt-api: Add Client Deregister for Notification
  android/hal-gatt-api: Add Client Read Remote RSSI
  android/hal-gatt-api: Add Client Get Device Type
  android/hal-gatt-api: Add Client Set Advertising Data
  android/hal-gatt-api: Add Client Test Command

 android/hal-ipc-api.txt | 324 +++++++++++++++++++++++++++++++++++++++++-------
 android/hal-msg.h       | 186 +++++++++++++++++++++++++++
 2 files changed, 466 insertions(+), 44 deletions(-)

--
1.9.0


^ 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