Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH] android/client-av: Close audio output stream on a2dp disconnection
From: Jakub Tyszkowski @ 2014-02-06  9:06 UTC (permalink / raw)
  To: linux-bluetooth

This patch makes haltest's audio part aware of a2dp disconnection and
closes audio output stream. This fixes the issue with CPU cycles being
eaten up by playback thread still trying to send audio data after
disconnection.
---
 android/client/if-av.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/android/client/if-av.c b/android/client/if-av.c
index 8d1f69b..ef1d997 100644
--- a/android/client/if-av.c
+++ b/android/client/if-av.c
@@ -41,6 +41,13 @@ static void connection_state(btav_connection_state_t state,
 	haltest_info("%s: connection_state=%s remote_bd_addr=%s\n", __func__,
 					btav_connection_state_t2str(state),
 					bt_bdaddr_t2str(bd_addr, last_addr));
+
+	if (state == BTAV_CONNECTION_STATE_DISCONNECTED) {
+		const struct method *m = get_interface_method("audio",
+							"close_output_stream");
+		if (m)
+			m->func(0, NULL);
+	}
 }
 
 static void audio_state(btav_audio_state_t state, bt_bdaddr_t *bd_addr)
-- 
1.8.5.2


^ permalink raw reply related

* [PATCH v3] android: Add support for Valgrind in debug variants
From: Andrzej Kaczmarek @ 2014-02-06  9:50 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Andrzej Kaczmarek

This patch allows bluetoothd to be run with Valgrind easily in debug
variants.

For userdebug and eng variants bluetoothd is renamed to bluetoothd-main
and bluetoothd acts a wrapper to launch it either with or without
Valgrind (this is decided by value of persist.sys.bluetooth.valgrind
property).
---
 android/Android.mk           | 42 ++++++++++++++++++++++++
 android/bluetoothd-wrapper.c | 76 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 118 insertions(+)
 create mode 100644 android/bluetoothd-wrapper.c

diff --git a/android/Android.mk b/android/Android.mk
index 20105e6..52745fe 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -82,7 +82,15 @@ $(shell mkdir -p $(LOCAL_PATH)/bluez/lib/bluetooth)
 $(foreach file,$(lib_headers), $(shell ln -sf ../$(file) $(LOCAL_PATH)/bluez/lib/bluetooth/$(file)))
 
 LOCAL_MODULE_TAGS := optional
+
+# for userdebug/eng this module is bluetoothd-main since bluetoothd is used as
+# wrapper to launch bluetooth with Valgrind
+ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
+LOCAL_MODULE := bluetoothd-main
+LOCAL_STRIP_MODULE := false
+else
 LOCAL_MODULE := bluetoothd
+endif
 
 include $(BUILD_EXECUTABLE)
 
@@ -406,3 +414,37 @@ LOCAL_CFLAGS:= \
 LOCAL_MODULE := libsbc
 
 include $(BUILD_SHARED_LIBRARY)
+
+ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
+
+#
+# bluetoothd (debug)
+# this is just a wrapper used in userdebug/eng to launch bluetoothd-main
+# with/without Valgrind
+#
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+	bluez/android/bluetoothd-wrapper.c
+
+LOCAL_CFLAGS := $(BLUEZ_COMMON_CFLAGS)
+
+LOCAL_SHARED_LIBRARIES := \
+	libcutils \
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_EXECUTABLES)
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := bluetoothd
+
+LOCAL_REQUIRED_MODULES := \
+	bluetoothd-main \
+	valgrind \
+	memcheck-$(TARGET_ARCH)-linux \
+	vgpreload_core-$(TARGET_ARCH)-linux \
+	vgpreload_memcheck-$(TARGET_ARCH)-linux \
+	default.supp
+
+include $(BUILD_EXECUTABLE)
+
+endif
\ No newline at end of file
diff --git a/android/bluetoothd-wrapper.c b/android/bluetoothd-wrapper.c
new file mode 100644
index 0000000..e90277f
--- /dev/null
+++ b/android/bluetoothd-wrapper.c
@@ -0,0 +1,76 @@
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <cutils/properties.h>
+
+#define PROPERTY_NAME "persist.sys.bluetooth.valgrind"
+
+#define VALGRIND_BIN "/system/bin/valgrind"
+
+#define BLUETOOTHD_BIN "/system/bin/bluetoothd-main"
+
+void run_valgrind(void)
+{
+	char *prg_argv[4];
+	char *prg_envp[3];
+
+	prg_argv[0] = VALGRIND_BIN;
+	prg_argv[1] = "--leak-check=full";
+	prg_argv[2] = BLUETOOTHD_BIN;
+	prg_argv[3] = NULL;
+
+	prg_envp[0] = "G_SLICE=always-malloc";
+	prg_envp[1] = "G_DEBUG=gc-friendly";
+	prg_envp[2] = NULL;
+
+	execve(prg_argv[0], prg_argv, prg_envp);
+}
+
+void run_bluetoothd(void)
+{
+	char *prg_argv[2];
+	char *prg_envp[1];
+
+	prg_argv[0] = BLUETOOTHD_BIN;
+	prg_argv[1] = NULL;
+
+	prg_envp[0] = NULL;
+
+	execve(prg_argv[0], prg_argv, prg_envp);
+}
+
+int main(int argc, char *argv[])
+{
+	char value[PROPERTY_VALUE_MAX];
+
+	if (property_get(PROPERTY_NAME, value, "") > 0 &&
+			(!strcasecmp(value, "true") || atoi(value) > 0))
+		run_valgrind();
+
+	/* In case we failed to execute Valgrind, try to run bluetoothd
+	 * without it
+	 */
+
+	run_bluetoothd();
+
+	return 0;
+}
-- 
1.8.5.3


^ permalink raw reply related

* [PATCH] android/pan: Use ioctl instead of sysfs for setting forward delay
From: Szymon Janc @ 2014-02-06 10:55 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

Using sysfs is causing problems due to filesystem permissions
(bluetoothd is running as bluetooth user) and bluetoothd already has
required capabilities for setting forward delay through ioctl.
---
This should be applied on top of "[PATCH v2 0/5] Android PAN fixes"

 android/pan.c | 31 +++++++++++++++----------------
 1 file changed, 15 insertions(+), 16 deletions(-)

diff --git a/android/pan.c b/android/pan.c
index eeeadeb..ae4079a 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -33,6 +33,9 @@
 #include <sys/wait.h>
 #include <net/if.h>
 #include <linux/sockios.h>
+#include <netinet/in.h>
+#include <netinet/ip6.h>
+#include <linux/if_bridge.h>
 
 #include "btio/btio.h"
 #include "lib/bluetooth.h"
@@ -54,7 +57,6 @@
 #define BNEP_BRIDGE "bt-pan"
 #define BNEP_PANU_INTERFACE "bt-pan"
 #define BNEP_NAP_INTERFACE "bt-pan%d"
-#define FORWARD_DELAY_PATH "/sys/class/net/"BNEP_BRIDGE"/bridge/forward_delay"
 
 static bdaddr_t adapter_addr;
 GSList *devices = NULL;
@@ -80,25 +82,22 @@ static struct {
 	.bridge = false,
 };
 
-
-static int set_forward_delay(void)
+static int set_forward_delay(int sk)
 {
-	int fd, ret;
-
-	fd = open(FORWARD_DELAY_PATH, O_RDWR);
-	if (fd < 0) {
-		int err = -errno;
+	unsigned long args[4] = { BRCTL_SET_BRIDGE_FORWARD_DELAY, 0 ,0, 0 };
+	struct ifreq ifr;
 
-		error("pan: open forward delay file failed: %d (%s)",
-							-err, strerror(-err));
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_name, BNEP_BRIDGE, IFNAMSIZ);
+	ifr.ifr_data = (char *) args;
 
-		return err;
+	if (ioctl(sk, SIOCDEVPRIVATE, &ifr) < 0) {
+		error("pan: setting forward delay failed: %d (%s)",
+						-errno, strerror(-errno));
+		return -1;
 	}
 
-	ret = write(fd, "0", sizeof("0"));
-	close(fd);
-
-	return ret;
+	return 0;
 }
 
 static int nap_create_bridge(void)
@@ -122,7 +121,7 @@ static int nap_create_bridge(void)
 		}
 	}
 
-	err = set_forward_delay();
+	err = set_forward_delay(sk);
 	if (err < 0)
 		ioctl(sk, SIOCBRDELBR, BNEP_BRIDGE);
 
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH V2] android/pan: Use ioctl instead of sysfs for setting forward delay
From: Szymon Janc @ 2014-02-06 11:24 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

Using sysfs is causing problems due to filesystem permissions
(bluetoothd is running as bluetooth user) and bluetoothd already has
required capabilities for setting forward delay through ioctl.
---
This should be applied on top of "[PATCH v2 0/5] Android PAN fixes"

V2: fixed passing negative value to strerror()

 android/pan.c | 31 +++++++++++++++----------------
 1 file changed, 15 insertions(+), 16 deletions(-)

diff --git a/android/pan.c b/android/pan.c
index eeeadeb..faab0b0 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -33,6 +33,9 @@
 #include <sys/wait.h>
 #include <net/if.h>
 #include <linux/sockios.h>
+#include <netinet/in.h>
+#include <netinet/ip6.h>
+#include <linux/if_bridge.h>
 
 #include "btio/btio.h"
 #include "lib/bluetooth.h"
@@ -54,7 +57,6 @@
 #define BNEP_BRIDGE "bt-pan"
 #define BNEP_PANU_INTERFACE "bt-pan"
 #define BNEP_NAP_INTERFACE "bt-pan%d"
-#define FORWARD_DELAY_PATH "/sys/class/net/"BNEP_BRIDGE"/bridge/forward_delay"
 
 static bdaddr_t adapter_addr;
 GSList *devices = NULL;
@@ -80,25 +82,22 @@ static struct {
 	.bridge = false,
 };
 
-
-static int set_forward_delay(void)
+static int set_forward_delay(int sk)
 {
-	int fd, ret;
-
-	fd = open(FORWARD_DELAY_PATH, O_RDWR);
-	if (fd < 0) {
-		int err = -errno;
+	unsigned long args[4] = { BRCTL_SET_BRIDGE_FORWARD_DELAY, 0 ,0, 0 };
+	struct ifreq ifr;
 
-		error("pan: open forward delay file failed: %d (%s)",
-							-err, strerror(-err));
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_name, BNEP_BRIDGE, IFNAMSIZ);
+	ifr.ifr_data = (char *) args;
 
-		return err;
+	if (ioctl(sk, SIOCDEVPRIVATE, &ifr) < 0) {
+		error("pan: setting forward delay failed: %d (%s)",
+							errno, strerror(errno));
+		return -1;
 	}
 
-	ret = write(fd, "0", sizeof("0"));
-	close(fd);
-
-	return ret;
+	return 0;
 }
 
 static int nap_create_bridge(void)
@@ -122,7 +121,7 @@ static int nap_create_bridge(void)
 		}
 	}
 
-	err = set_forward_delay();
+	err = set_forward_delay(sk);
 	if (err < 0)
 		ioctl(sk, SIOCBRDELBR, BNEP_BRIDGE);
 
-- 
1.8.3.2


^ permalink raw reply related

* Re: [PATCH BlueZ 1/2] audio/AVCTP: Add keys that can be mapped to uinput
From: Luiz Augusto von Dentz @ 2014-02-06 14:08 UTC (permalink / raw)
  To: linux-bluetooth@vger.kernel.org
In-Reply-To: <1391610272-12991-1-git-send-email-luiz.dentz@gmail.com>

Hi,

On Wed, Feb 5, 2014 at 4:24 PM, Luiz Augusto von Dentz
<luiz.dentz@gmail.com> wrote:
> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
>
> This adds the remaining AV/C keys that can be mapped to uinput.
> ---
>  android/avctp.c        | 28 ++++++++++++++++++++++++++++
>  android/avctp.h        | 29 +++++++++++++++++++++++++++++
>  profiles/audio/avctp.c | 28 ++++++++++++++++++++++++++++
>  profiles/audio/avctp.h | 29 +++++++++++++++++++++++++++++
>  4 files changed, 114 insertions(+)
>
> diff --git a/android/avctp.c b/android/avctp.c
> index 8f35403..f7544a2 100644
> --- a/android/avctp.c
> +++ b/android/avctp.c
> @@ -215,25 +215,53 @@ static struct {
>         { "ROOT MENU",          AVC_ROOT_MENU,          KEY_MENU },
>         { "CONTENTS MENU",      AVC_CONTENTS_MENU,      KEY_PROGRAM },
>         { "FAVORITE MENU",      AVC_FAVORITE_MENU,      KEY_FAVORITES },
> +       { "EXIT",               AVC_EXIT,               KEY_EXIT },
> +       { "ON DEMAND MENU",     AVC_ON_DEMAND_MENU,     KEY_MENU },
> +       { "APPS MENU",          AVC_APPS_MENU,          KEY_MENU },
> +       { "0",                  AVC_0,                  KEY_0 },
> +       { "1",                  AVC_1,                  KEY_1 },
> +       { "2",                  AVC_2,                  KEY_2 },
> +       { "3",                  AVC_3,                  KEY_3 },
> +       { "4",                  AVC_4,                  KEY_4 },
> +       { "5",                  AVC_5,                  KEY_5 },
> +       { "6",                  AVC_6,                  KEY_6 },
> +       { "7",                  AVC_7,                  KEY_7 },
> +       { "8",                  AVC_8,                  KEY_8 },
> +       { "9",                  AVC_9,                  KEY_9 },
> +       { "DOT",                AVC_DOT,                KEY_DOT },
>         { "ENTER",              AVC_ENTER,              KEY_ENTER },
>         { "CHANNEL UP",         AVC_CHANNEL_UP,         KEY_CHANNELUP },
>         { "CHANNEL DOWN",       AVC_CHANNEL_DOWN,       KEY_CHANNELDOWN },
> +       { "CHANNEL PREVIOUS",   AVC_CHANNEL_PREVIOUS,   KEY_LAST },
>         { "INPUT SELECT",       AVC_INPUT_SELECT,       KEY_CONFIG },
> +       { "INFO",               AVC_INFO,               KEY_INFO },
>         { "HELP",               AVC_HELP,               KEY_HELP },
>         { "POWER",              AVC_POWER,              KEY_POWER2 },
>         { "VOLUME UP",          AVC_VOLUME_UP,          KEY_VOLUMEUP },
>         { "VOLUME DOWN",        AVC_VOLUME_DOWN,        KEY_VOLUMEDOWN },
> +       { "MUTE",               AVC_MUTE,               KEY_MUTE },
>         { "PLAY",               AVC_PLAY,               KEY_PLAYCD },
>         { "STOP",               AVC_STOP,               KEY_STOPCD },
>         { "PAUSE",              AVC_PAUSE,              KEY_PAUSECD },
>         { "FORWARD",            AVC_FORWARD,            KEY_NEXTSONG },
>         { "BACKWARD",           AVC_BACKWARD,           KEY_PREVIOUSSONG },
> +       { "RECORD",             AVC_RECORD,             KEY_RECORD },
>         { "REWIND",             AVC_REWIND,             KEY_REWIND },
>         { "FAST FORWARD",       AVC_FAST_FORWARD,       KEY_FASTFORWARD },
> +       { "LIST",               AVC_LIST,               KEY_LIST },
>         { "F1",                 AVC_F1,                 KEY_F1 },
>         { "F2",                 AVC_F2,                 KEY_F2 },
>         { "F3",                 AVC_F3,                 KEY_F3 },
>         { "F4",                 AVC_F4,                 KEY_F4 },
> +       { "F5",                 AVC_F5,                 KEY_F5 },
> +       { "F6",                 AVC_F6,                 KEY_F6 },
> +       { "F7",                 AVC_F7,                 KEY_F7 },
> +       { "F8",                 AVC_F8,                 KEY_F8 },
> +       { "F9",                 AVC_F9,                 KEY_F9 },
> +       { "RED",                AVC_RED,                KEY_RED },
> +       { "GREEN",              AVC_GREEN,              KEY_GREEN },
> +       { "BLUE",               AVC_BLUE,               KEY_BLUE },
> +       { "YELLOW",             AVC_YELLOW,             KEY_YELLOW },
>         { NULL }
>  };
>
> diff --git a/android/avctp.h b/android/avctp.h
> index e7e0277..dfa0ca6 100644
> --- a/android/avctp.h
> +++ b/android/avctp.h
> @@ -56,11 +56,30 @@
>  #define AVC_ROOT_MENU                  0x09
>  #define AVC_CONTENTS_MENU              0x0b
>  #define AVC_FAVORITE_MENU              0x0c
> +#define AVC_EXIT                       0x0d
> +#define AVC_ON_DEMAND_MENU             0x0e
> +#define AVC_APPS_MENU                  0x0f
> +#define AVC_0                          0x20
> +#define AVC_1                          0x21
> +#define AVC_2                          0x22
> +#define AVC_3                          0x23
> +#define AVC_4                          0x24
> +#define AVC_5                          0x25
> +#define AVC_6                          0x26
> +#define AVC_7                          0x27
> +#define AVC_8                          0x28
> +#define AVC_9                          0x29
> +#define AVC_DOT                                0x2a
>  #define AVC_ENTER                      0x2b
>  #define AVC_CHANNEL_UP                 0x30
>  #define AVC_CHANNEL_DOWN               0x31
> +#define AVC_CHANNEL_PREVIOUS           0x32
>  #define AVC_INPUT_SELECT               0x34
> +#define AVC_INFO                       0x35
>  #define AVC_HELP                       0x36
> +#define AVC_PAGE_UP                    0x37
> +#define AVC_PAGE_DOWN                  0x38
> +#define AVC_LOCK                       0x3a
>  #define AVC_POWER                      0x40
>  #define AVC_VOLUME_UP                  0x41
>  #define AVC_VOLUME_DOWN                        0x42
> @@ -74,10 +93,20 @@
>  #define AVC_EJECT                      0x4a
>  #define AVC_FORWARD                    0x4b
>  #define AVC_BACKWARD                   0x4c
> +#define AVC_LIST                       0x4d
>  #define AVC_F1                         0x71
>  #define AVC_F2                         0x72
>  #define AVC_F3                         0x73
>  #define AVC_F4                         0x74
> +#define AVC_F5                         0x75
> +#define AVC_F6                         0x76
> +#define AVC_F7                         0x77
> +#define AVC_F8                         0x78
> +#define AVC_F9                         0x79
> +#define AVC_RED                                0x7a
> +#define AVC_GREEN                      0x7b
> +#define AVC_BLUE                       0x7c
> +#define AVC_YELLOW                     0x7c
>
>  struct avctp;
>
> diff --git a/profiles/audio/avctp.c b/profiles/audio/avctp.c
> index 9f87859..ae142bd 100644
> --- a/profiles/audio/avctp.c
> +++ b/profiles/audio/avctp.c
> @@ -238,25 +238,53 @@ static struct {
>         { "ROOT MENU",          AVC_ROOT_MENU,          KEY_MENU },
>         { "CONTENTS MENU",      AVC_CONTENTS_MENU,      KEY_PROGRAM },
>         { "FAVORITE MENU",      AVC_FAVORITE_MENU,      KEY_FAVORITES },
> +       { "EXIT",               AVC_EXIT,               KEY_EXIT },
> +       { "ON DEMAND MENU",     AVC_ON_DEMAND_MENU,     KEY_MENU },
> +       { "APPS MENU",          AVC_APPS_MENU,          KEY_MENU },
> +       { "0",                  AVC_0,                  KEY_0 },
> +       { "1",                  AVC_1,                  KEY_1 },
> +       { "2",                  AVC_2,                  KEY_2 },
> +       { "3",                  AVC_3,                  KEY_3 },
> +       { "4",                  AVC_4,                  KEY_4 },
> +       { "5",                  AVC_5,                  KEY_5 },
> +       { "6",                  AVC_6,                  KEY_6 },
> +       { "7",                  AVC_7,                  KEY_7 },
> +       { "8",                  AVC_8,                  KEY_8 },
> +       { "9",                  AVC_9,                  KEY_9 },
> +       { "DOT",                AVC_DOT,                KEY_DOT },
>         { "ENTER",              AVC_ENTER,              KEY_ENTER },
>         { "CHANNEL UP",         AVC_CHANNEL_UP,         KEY_CHANNELUP },
>         { "CHANNEL DOWN",       AVC_CHANNEL_DOWN,       KEY_CHANNELDOWN },
> +       { "CHANNEL PREVIOUS",   AVC_CHANNEL_PREVIOUS,   KEY_LAST },
>         { "INPUT SELECT",       AVC_INPUT_SELECT,       KEY_CONFIG },
> +       { "INFO",               AVC_INFO,               KEY_INFO },
>         { "HELP",               AVC_HELP,               KEY_HELP },
>         { "POWER",              AVC_POWER,              KEY_POWER2 },
>         { "VOLUME UP",          AVC_VOLUME_UP,          KEY_VOLUMEUP },
>         { "VOLUME DOWN",        AVC_VOLUME_DOWN,        KEY_VOLUMEDOWN },
> +       { "MUTE",               AVC_MUTE,               KEY_MUTE },
>         { "PLAY",               AVC_PLAY,               KEY_PLAYCD },
>         { "STOP",               AVC_STOP,               KEY_STOPCD },
>         { "PAUSE",              AVC_PAUSE,              KEY_PAUSECD },
>         { "FORWARD",            AVC_FORWARD,            KEY_NEXTSONG },
>         { "BACKWARD",           AVC_BACKWARD,           KEY_PREVIOUSSONG },
> +       { "RECORD",             AVC_RECORD,             KEY_RECORD },
>         { "REWIND",             AVC_REWIND,             KEY_REWIND },
>         { "FAST FORWARD",       AVC_FAST_FORWARD,       KEY_FASTFORWARD },
> +       { "LIST",               AVC_LIST,               KEY_LIST },
>         { "F1",                 AVC_F1,                 KEY_F1 },
>         { "F2",                 AVC_F2,                 KEY_F2 },
>         { "F3",                 AVC_F3,                 KEY_F3 },
>         { "F4",                 AVC_F4,                 KEY_F4 },
> +       { "F5",                 AVC_F5,                 KEY_F5 },
> +       { "F6",                 AVC_F6,                 KEY_F6 },
> +       { "F7",                 AVC_F7,                 KEY_F7 },
> +       { "F8",                 AVC_F8,                 KEY_F8 },
> +       { "F9",                 AVC_F9,                 KEY_F9 },
> +       { "RED",                AVC_RED,                KEY_RED },
> +       { "GREEN",              AVC_GREEN,              KEY_GREEN },
> +       { "BLUE",               AVC_BLUE,               KEY_BLUE },
> +       { "YELLOW",             AVC_YELLOW,             KEY_YELLOW },
>         { NULL }
>  };
>
> diff --git a/profiles/audio/avctp.h b/profiles/audio/avctp.h
> index f9c665e..05fceb4 100644
> --- a/profiles/audio/avctp.h
> +++ b/profiles/audio/avctp.h
> @@ -57,11 +57,30 @@
>  #define AVC_ROOT_MENU                  0x09
>  #define AVC_CONTENTS_MENU              0x0b
>  #define AVC_FAVORITE_MENU              0x0c
> +#define AVC_EXIT                       0x0d
> +#define AVC_ON_DEMAND_MENU             0x0e
> +#define AVC_APPS_MENU                  0x0f
> +#define AVC_0                          0x20
> +#define AVC_1                          0x21
> +#define AVC_2                          0x22
> +#define AVC_3                          0x23
> +#define AVC_4                          0x24
> +#define AVC_5                          0x25
> +#define AVC_6                          0x26
> +#define AVC_7                          0x27
> +#define AVC_8                          0x28
> +#define AVC_9                          0x29
> +#define AVC_DOT                                0x2a
>  #define AVC_ENTER                      0x2b
>  #define AVC_CHANNEL_UP                 0x30
>  #define AVC_CHANNEL_DOWN               0x31
> +#define AVC_CHANNEL_PREVIOUS           0x32
>  #define AVC_INPUT_SELECT               0x34
> +#define AVC_INFO                       0x35
>  #define AVC_HELP                       0x36
> +#define AVC_PAGE_UP                    0x37
> +#define AVC_PAGE_DOWN                  0x38
> +#define AVC_LOCK                       0x3a
>  #define AVC_POWER                      0x40
>  #define AVC_VOLUME_UP                  0x41
>  #define AVC_VOLUME_DOWN                        0x42
> @@ -75,10 +94,20 @@
>  #define AVC_EJECT                      0x4a
>  #define AVC_FORWARD                    0x4b
>  #define AVC_BACKWARD                   0x4c
> +#define AVC_LIST                       0x4d
>  #define AVC_F1                         0x71
>  #define AVC_F2                         0x72
>  #define AVC_F3                         0x73
>  #define AVC_F4                         0x74
> +#define AVC_F5                         0x75
> +#define AVC_F6                         0x76
> +#define AVC_F7                         0x77
> +#define AVC_F8                         0x78
> +#define AVC_F9                         0x79
> +#define AVC_RED                                0x7a
> +#define AVC_GREEN                      0x7b
> +#define AVC_BLUE                       0x7c
> +#define AVC_YELLOW                     0x7c
>
>  struct avctp;
>
> --
> 1.8.5.3

Pushed.


-- 
Luiz Augusto von Dentz

^ permalink raw reply

* Re: [PATCH] android/client-av: Close audio output stream on a2dp disconnection
From: Szymon Janc @ 2014-02-06 14:12 UTC (permalink / raw)
  To: Jakub Tyszkowski; +Cc: linux-bluetooth
In-Reply-To: <1391677561-5522-1-git-send-email-jakub.tyszkowski@tieto.com>

Hi Jakub,

On Thursday 06 of February 2014 10:06:01 Jakub Tyszkowski wrote:
> This patch makes haltest's audio part aware of a2dp disconnection and
> closes audio output stream. This fixes the issue with CPU cycles being
> eaten up by playback thread still trying to send audio data after
> disconnection.
> ---
>  android/client/if-av.c | 7 +++++++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/android/client/if-av.c b/android/client/if-av.c
> index 8d1f69b..ef1d997 100644
> --- a/android/client/if-av.c
> +++ b/android/client/if-av.c
> @@ -41,6 +41,13 @@ static void connection_state(btav_connection_state_t state,
>  	haltest_info("%s: connection_state=%s remote_bd_addr=%s\n", __func__,
>  					btav_connection_state_t2str(state),
>  					bt_bdaddr_t2str(bd_addr, last_addr));
> +
> +	if (state == BTAV_CONNECTION_STATE_DISCONNECTED) {
> +		const struct method *m = get_interface_method("audio",
> +							"close_output_stream");
> +		if (m)
> +			m->func(0, NULL);
> +	}
>  }

I think haltest should not be that smart and interaction of audio and av should
be handled by user (it is 'emulating' mediaserver, right?). I pushed fix for CPU
eating myself.

>  
>  static void audio_state(btav_audio_state_t state, bt_bdaddr_t *bd_addr)
> 

-- 
Best regards, 
Szymon Janc

^ permalink raw reply

* Re: [PATCH] android/haltest: Close file in case of error
From: Andrei Emeltchenko @ 2014-02-06 14:13 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391615042-22677-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

On Wed, Feb 05, 2014 at 05:44:02PM +0200, Andrei Emeltchenko wrote:
> From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> 
> ---
>  android/client/if-audio.c | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/android/client/if-audio.c b/android/client/if-audio.c
> index 66f8364..bb8f51b 100644
> --- a/android/client/if-audio.c
> +++ b/android/client/if-audio.c
> @@ -258,6 +258,7 @@ static void play_p(int argc, const char **argv)
>  
>  	if (buffer_size == 0) {
>  		haltest_error("Invalid buffer size. Was stream_out opened?\n");
> +		fclose(in);

sorry, need to check for NULL here and below.

Best regards 
Andrei Emeltchenko 

>  		return;
>  	}
>  
> @@ -265,12 +266,15 @@ static void play_p(int argc, const char **argv)
>  	if (current_state != STATE_STOPPED) {
>  		haltest_error("Already playing or stream suspended!\n");
>  		pthread_mutex_unlock(&state_mutex);
> +		fclose(in);
>  		return;
>  	}
>  	pthread_mutex_unlock(&state_mutex);
>  
> -	if (pthread_create(&play_thread, NULL, playback_thread, in) != 0)
> +	if (pthread_create(&play_thread, NULL, playback_thread, in) != 0) {
>  		haltest_error("Cannot create playback thread!\n");
> +		fclose(in);
> +	}
>  }
>  
>  static void stop_p(int argc, const char **argv)
> -- 
> 1.8.3.2
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCHv2 1/2] android/haltest: Close file in case of error
From: Andrei Emeltchenko @ 2014-02-06 14:22 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391615042-22677-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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

---
 android/client/if-audio.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/android/client/if-audio.c b/android/client/if-audio.c
index 66f8364..3b34c95 100644
--- a/android/client/if-audio.c
+++ b/android/client/if-audio.c
@@ -258,19 +258,26 @@ static void play_p(int argc, const char **argv)
 
 	if (buffer_size == 0) {
 		haltest_error("Invalid buffer size. Was stream_out opened?\n");
-		return;
+		goto fail;
 	}
 
 	pthread_mutex_lock(&state_mutex);
 	if (current_state != STATE_STOPPED) {
 		haltest_error("Already playing or stream suspended!\n");
 		pthread_mutex_unlock(&state_mutex);
-		return;
+		goto fail;
 	}
 	pthread_mutex_unlock(&state_mutex);
 
-	if (pthread_create(&play_thread, NULL, playback_thread, in) != 0)
+	if (pthread_create(&play_thread, NULL, playback_thread, in) != 0) {
 		haltest_error("Cannot create playback thread!\n");
+		goto fail;
+	}
+
+	return;
+fail:
+	if (in)
+		fclose(in);
 }
 
 static void stop_p(int argc, const char **argv)
-- 
1.8.3.2


^ permalink raw reply related

* [PATCHv2 2/2] android/haltest: Remove unneeded assignment
From: Andrei Emeltchenko @ 2014-02-06 14:22 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391696563-7478-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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

---
 android/client/if-audio.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/android/client/if-audio.c b/android/client/if-audio.c
index 3b34c95..f449b49 100644
--- a/android/client/if-audio.c
+++ b/android/client/if-audio.c
@@ -225,10 +225,8 @@ static void *playback_thread(void *data)
 		pthread_mutex_unlock(&outstream_mutex);
 	} while (len && w_len);
 
-	if (in) {
+	if (in)
 		fclose(in);
-		in = NULL;
-	}
 
 	pthread_cleanup_pop(1);
 	return NULL;
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH v3 0/8] Android PAN fixes
From: Szymon Janc @ 2014-02-06 15:28 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

V3:
 - fixed not bringing bridge if down
 - add forward_delay with ioctl patch
 - other minor bugfixes

V2:
This is based on patch from Ravi (sent 23.01.2013). Changes include
patch split and some bugfixes.

Ravi kumar Veeramally (1):
  android/pan: Fix bnep interface name

Szymon Janc (7):
  profiles/network: Use interface name passed to bnep_connadd
  profiles/network: Allow to pass interface name to bnep_new
  android/pan: Move functions up to avoid forward declarations
  android/pan: Fix unregistering NAP bridge
  android/pan: Use ioctl instead of sysfs for setting forward delay
  android/pan: Pass error in nap_remove_bridge
  android/pan: Bring bridge interface down before removing it

 android/pan.c                 | 205 ++++++++++++++++++++++++++----------------
 profiles/network/bnep.c       |  10 ++-
 profiles/network/bnep.h       |   3 +-
 profiles/network/connection.c |   6 +-
 profiles/network/server.c     |   4 +
 5 files changed, 146 insertions(+), 82 deletions(-)

-- 
1.8.3.2


^ permalink raw reply

* [PATCH v3 1/8] profiles/network: Use interface name passed to bnep_connadd
From: Szymon Janc @ 2014-02-06 15:28 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1391700522-9036-1-git-send-email-szymon.janc@tieto.com>

---
 profiles/network/bnep.c   | 5 +++--
 profiles/network/server.c | 4 ++++
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/profiles/network/bnep.c b/profiles/network/bnep.c
index 0d57056..82d0d99 100644
--- a/profiles/network/bnep.c
+++ b/profiles/network/bnep.c
@@ -174,9 +174,10 @@ static int bnep_connadd(int sk, uint16_t role, char *dev)
 {
 	struct bnep_connadd_req req;
 
-	memset(dev, 0, 16);
 	memset(&req, 0, sizeof(req));
-	strcpy(req.device, "bnep%d");
+	strncpy(req.device, dev, 16);
+	req.device[15] = '\0';
+
 	req.sock = sk;
 	req.role = role;
 	if (ioctl(ctl, BNEPCONNADD, &req) < 0) {
diff --git a/profiles/network/server.c b/profiles/network/server.c
index f14d688..3fb031f 100644
--- a/profiles/network/server.c
+++ b/profiles/network/server.c
@@ -51,6 +51,7 @@
 #include "server.h"
 
 #define NETWORK_SERVER_INTERFACE "org.bluez.NetworkServer1"
+#define BNEP_INTERFACE "bnep%d"
 #define SETUP_TIMEOUT		1
 
 /* Pending Authorization */
@@ -347,6 +348,9 @@ static gboolean bnep_setup(GIOChannel *chan,
 		goto reply;
 	}
 
+	strncpy(na->setup->dev, BNEP_INTERFACE, 16);
+	na->setup->dev[15] = '\0';
+
 	if (bnep_server_add(sk, dst_role, ns->bridge, na->setup->dev,
 							&na->setup->dst) < 0)
 		goto reply;
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH v3 2/8] profiles/network: Allow to pass interface name to bnep_new
From: Szymon Janc @ 2014-02-06 15:28 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1391700522-9036-1-git-send-email-szymon.janc@tieto.com>

---
 android/pan.c                 | 3 ++-
 profiles/network/bnep.c       | 5 ++++-
 profiles/network/bnep.h       | 3 ++-
 profiles/network/connection.c | 6 ++++--
 4 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/android/pan.c b/android/pan.c
index 6b19120..b8d7404 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -52,6 +52,7 @@
 #define SVC_HINT_NETWORKING 0x02
 
 #define BNEP_BRIDGE "bnep"
+#define BNEP_PANU_INTERFACE "bt-pan"
 #define FORWARD_DELAY_PATH "/sys/class/net/"BNEP_BRIDGE"/bridge/forward_delay"
 
 static bdaddr_t adapter_addr;
@@ -202,7 +203,7 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer data)
 
 	sk = g_io_channel_unix_get_fd(dev->io);
 
-	dev->session = bnep_new(sk, l_role, r_role);
+	dev->session = bnep_new(sk, l_role, r_role, BNEP_PANU_INTERFACE);
 	if (!dev->session)
 		goto fail;
 
diff --git a/profiles/network/bnep.c b/profiles/network/bnep.c
index 82d0d99..1aa0783 100644
--- a/profiles/network/bnep.c
+++ b/profiles/network/bnep.c
@@ -386,7 +386,8 @@ static gboolean bnep_conn_req_to(gpointer user_data)
 	return FALSE;
 }
 
-struct bnep *bnep_new(int sk, uint16_t local_role, uint16_t remote_role)
+struct bnep *bnep_new(int sk, uint16_t local_role, uint16_t remote_role,
+								char *iface)
 {
 	struct bnep *session;
 	int dup_fd;
@@ -399,6 +400,8 @@ struct bnep *bnep_new(int sk, uint16_t local_role, uint16_t remote_role)
 	session->io = g_io_channel_unix_new(dup_fd);
 	session->src = local_role;
 	session->dst = remote_role;
+	strncpy(session->iface, iface, 16);
+	session->iface[15] = '\0';
 
 	g_io_channel_set_close_on_unref(session->io, TRUE);
 	session->watch = g_io_add_watch(session->io,
diff --git a/profiles/network/bnep.h b/profiles/network/bnep.h
index 87cdacf..bc43d4f 100644
--- a/profiles/network/bnep.h
+++ b/profiles/network/bnep.h
@@ -30,7 +30,8 @@ uint16_t bnep_service_id(const char *svc);
 const char *bnep_uuid(uint16_t id);
 const char *bnep_name(uint16_t id);
 
-struct bnep *bnep_new(int sk, uint16_t local_role, uint16_t remote_role);
+struct bnep *bnep_new(int sk, uint16_t local_role, uint16_t remote_role,
+								char *iface);
 void bnep_free(struct bnep *session);
 
 typedef void (*bnep_connect_cb) (char *iface, int err, void *data);
diff --git a/profiles/network/connection.c b/profiles/network/connection.c
index 5f45fdb..cc73989 100644
--- a/profiles/network/connection.c
+++ b/profiles/network/connection.c
@@ -51,6 +51,7 @@
 #include "connection.h"
 
 #define NETWORK_PEER_INTERFACE "org.bluez.Network1"
+#define BNEP_INTERFACE "bnep%d"
 
 typedef enum {
 	CONNECTED,
@@ -128,7 +129,8 @@ static void bnep_disconn_cb(gpointer data)
 
 	nc->state = DISCONNECTED;
 	memset(nc->dev, 0, sizeof(nc->dev));
-	strcpy(nc->dev, "bnep%d");
+	strncpy(nc->dev, BNEP_INTERFACE, 16);
+	nc->dev[15] = '\0';
 
 	bnep_free(nc->session);
 	nc->session = NULL;
@@ -243,7 +245,7 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer data)
 	}
 
 	sk = g_io_channel_unix_get_fd(nc->io);
-	nc->session = bnep_new(sk, BNEP_SVC_PANU, nc->id);
+	nc->session = bnep_new(sk, BNEP_SVC_PANU, nc->id, BNEP_INTERFACE);
 	if (!nc->session)
 		goto failed;
 
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH v3 3/8] android/pan: Move functions up to avoid forward declarations
From: Szymon Janc @ 2014-02-06 15:28 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1391700522-9036-1-git-send-email-szymon.janc@tieto.com>

---
 android/pan.c | 132 +++++++++++++++++++++++++++++-----------------------------
 1 file changed, 66 insertions(+), 66 deletions(-)

diff --git a/android/pan.c b/android/pan.c
index b8d7404..d010e09 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -77,6 +77,72 @@ static struct {
 	.io = NULL,
 };
 
+static int set_forward_delay(void)
+{
+	int fd, ret;
+
+	fd = open(FORWARD_DELAY_PATH, O_RDWR);
+	if (fd < 0) {
+		int err = -errno;
+
+		error("pan: open forward delay file failed: %d (%s)",
+							-err, strerror(-err));
+
+		return err;
+	}
+
+	ret = write(fd, "0", sizeof("0"));
+	close(fd);
+
+	return ret;
+}
+
+static int nap_create_bridge(void)
+{
+	int sk, err;
+
+	DBG("%s", BNEP_BRIDGE);
+
+	sk = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
+	if (sk < 0)
+		return -EOPNOTSUPP;
+
+	if (ioctl(sk, SIOCBRADDBR, BNEP_BRIDGE) < 0) {
+		err = -errno;
+		if (err != -EEXIST) {
+			close(sk);
+			return -EOPNOTSUPP;
+		}
+	}
+
+	err = set_forward_delay();
+	if (err < 0)
+		ioctl(sk, SIOCBRDELBR, BNEP_BRIDGE);
+
+	close(sk);
+
+	return err;
+}
+
+static int nap_remove_bridge(void)
+{
+	int sk, err;
+
+	DBG("%s", BNEP_BRIDGE);
+
+	sk = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
+	if (sk < 0)
+		return -EOPNOTSUPP;
+
+	err = ioctl(sk, SIOCBRDELBR, BNEP_BRIDGE);
+	close(sk);
+
+	if (err < 0)
+		return -EOPNOTSUPP;
+
+	return 0;
+}
+
 static int device_cmp(gconstpointer s, gconstpointer user_data)
 {
 	const struct pan_device *dev = s;
@@ -475,72 +541,6 @@ failed:
 	bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
 }
 
-static int set_forward_delay(void)
-{
-	int fd, ret;
-
-	fd = open(FORWARD_DELAY_PATH, O_RDWR);
-	if (fd < 0) {
-		int err = -errno;
-
-		error("pan: open forward delay file failed: %d (%s)",
-							-err, strerror(-err));
-
-		return err;
-	}
-
-	ret = write(fd, "0", sizeof("0"));
-	close(fd);
-
-	return ret;
-}
-
-static int nap_create_bridge(void)
-{
-	int sk, err;
-
-	DBG("%s", BNEP_BRIDGE);
-
-	sk = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
-	if (sk < 0)
-		return -EOPNOTSUPP;
-
-	if (ioctl(sk, SIOCBRADDBR, BNEP_BRIDGE) < 0) {
-		err = -errno;
-		if (err != -EEXIST) {
-			close(sk);
-			return -EOPNOTSUPP;
-		}
-	}
-
-	err = set_forward_delay();
-	if (err < 0)
-		ioctl(sk, SIOCBRDELBR, BNEP_BRIDGE);
-
-	close(sk);
-
-	return err;
-}
-
-static int nap_remove_bridge(void)
-{
-	int sk, err;
-
-	DBG("%s", BNEP_BRIDGE);
-
-	sk = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
-	if (sk < 0)
-		return -EOPNOTSUPP;
-
-	err = ioctl(sk, SIOCBRDELBR, BNEP_BRIDGE);
-	close(sk);
-
-	if (err < 0)
-		return -EOPNOTSUPP;
-
-	return 0;
-}
-
 static void destroy_nap_device(void)
 {
 	DBG("");
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH v3 4/8] android/pan: Fix unregistering NAP bridge
From: Szymon Janc @ 2014-02-06 15:28 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1391700522-9036-1-git-send-email-szymon.janc@tieto.com>

This fix not removing NAP bridge in case of error or last device
disconnect.
---
 android/pan.c | 26 ++++++++++++++++++++------
 1 file changed, 20 insertions(+), 6 deletions(-)

diff --git a/android/pan.c b/android/pan.c
index d010e09..0d6adaf 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -72,11 +72,14 @@ struct pan_device {
 static struct {
 	uint32_t	record_id;
 	GIOChannel	*io;
+	bool		bridge;
 } nap_dev = {
 	.record_id = 0,
 	.io = NULL,
+	.bridge = false,
 };
 
+
 static int set_forward_delay(void)
 {
 	int fd, ret;
@@ -103,6 +106,9 @@ static int nap_create_bridge(void)
 
 	DBG("%s", BNEP_BRIDGE);
 
+	if (nap_dev.bridge)
+		return 0;
+
 	sk = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
 	if (sk < 0)
 		return -EOPNOTSUPP;
@@ -121,6 +127,8 @@ static int nap_create_bridge(void)
 
 	close(sk);
 
+	nap_dev.bridge = err == 0;
+
 	return err;
 }
 
@@ -130,6 +138,9 @@ static int nap_remove_bridge(void)
 
 	DBG("%s", BNEP_BRIDGE);
 
+	if (!nap_dev.bridge)
+		return 0;
+
 	sk = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
 	if (sk < 0)
 		return -EOPNOTSUPP;
@@ -140,6 +151,8 @@ static int nap_remove_bridge(void)
 	if (err < 0)
 		return -EOPNOTSUPP;
 
+	nap_dev.bridge = false;
+
 	return 0;
 }
 
@@ -175,8 +188,10 @@ static void pan_device_remove(struct pan_device *dev)
 {
 	devices = g_slist_remove(devices, dev);
 
-	if (g_slist_length(devices) == 0)
+	if (g_slist_length(devices) == 0) {
 		local_role = HAL_PAN_ROLE_NONE;
+		nap_remove_bridge();
+	}
 
 	pan_device_free(dev);
 }
@@ -455,8 +470,12 @@ static gboolean nap_setup_cb(GIOChannel *chan, GIOCondition cond,
 		goto failed;
 	}
 
+	if (nap_create_bridge() < 0)
+		goto failed;
+
 	if (bnep_server_add(sk, dst_role, BNEP_BRIDGE, dev->iface,
 							&dev->dst) < 0) {
+		nap_remove_bridge();
 		error("server_connadd failed");
 		rsp = BNEP_CONN_NOT_ALLOWED;
 		goto failed;
@@ -557,14 +576,9 @@ static void destroy_nap_device(void)
 static int register_nap_server(void)
 {
 	GError *gerr = NULL;
-	int err;
 
 	DBG("");
 
-	err = nap_create_bridge();
-	if (err < 0)
-		return err;
-
 	nap_dev.io = bt_io_listen(NULL, nap_confirm_cb, NULL, NULL, &gerr,
 					BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
 					BT_IO_OPT_PSM, BNEP_PSM,
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH v3 5/8] android/pan: Fix bnep interface name
From: Szymon Janc @ 2014-02-06 15:28 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1391700522-9036-1-git-send-email-szymon.janc@tieto.com>

From: Ravi kumar Veeramally <ravikumar.veeramally@linux.intel.com>

Android uses bt-pan static interface in PAN profile. In server role
it uses it as bridge name. But current implementaion passes interface
names like bnep0, bnep1... Android Framework is unaware of this name
and unable to allocate IP address after profile connection setup.
---
 android/pan.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/android/pan.c b/android/pan.c
index 0d6adaf..83def53 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -51,8 +51,9 @@
 
 #define SVC_HINT_NETWORKING 0x02
 
-#define BNEP_BRIDGE "bnep"
+#define BNEP_BRIDGE "bt-pan"
 #define BNEP_PANU_INTERFACE "bt-pan"
+#define BNEP_NAP_INTERFACE "bt-pan%d"
 #define FORWARD_DELAY_PATH "/sys/class/net/"BNEP_BRIDGE"/bridge/forward_delay"
 
 static bdaddr_t adapter_addr;
@@ -229,8 +230,13 @@ static void bt_pan_notify_ctrl_state(struct pan_device *dev, uint8_t state)
 	ev.state = state;
 	ev.local_role = local_role;
 	ev.status = HAL_STATUS_SUCCESS;
+
 	memset(ev.name, 0, sizeof(ev.name));
-	memcpy(ev.name, dev->iface, sizeof(dev->iface));
+
+	if (local_role == HAL_PAN_ROLE_NAP)
+		memcpy(ev.name, BNEP_BRIDGE, sizeof(BNEP_BRIDGE));
+	else
+		memcpy(ev.name, dev->iface, sizeof(dev->iface));
 
 	ipc_send_notif(HAL_SERVICE_ID_PAN, HAL_EV_PAN_CTRL_STATE, sizeof(ev),
 									&ev);
@@ -542,6 +548,9 @@ static void nap_confirm_cb(GIOChannel *chan, gpointer data)
 	local_role = HAL_PAN_ROLE_NAP;
 	dev->role = HAL_PAN_ROLE_PANU;
 
+	strncpy(dev->iface, BNEP_NAP_INTERFACE, 16);
+	dev->iface[15] = '\0';
+
 	dev->io = g_io_channel_ref(chan);
 	g_io_channel_set_close_on_unref(dev->io, TRUE);
 
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH v3 6/8] android/pan: Use ioctl instead of sysfs for setting forward delay
From: Szymon Janc @ 2014-02-06 15:28 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1391700522-9036-1-git-send-email-szymon.janc@tieto.com>

Using sysfs is causing problems due to filesystem permissions
(bluetoothd is running as bluetooth user) and bluetoothd already has
required capabilities for setting forward delay through ioctl.
---
 android/pan.c | 31 +++++++++++++++----------------
 1 file changed, 15 insertions(+), 16 deletions(-)

diff --git a/android/pan.c b/android/pan.c
index 83def53..1cb82a1 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -33,6 +33,9 @@
 #include <sys/wait.h>
 #include <net/if.h>
 #include <linux/sockios.h>
+#include <netinet/in.h>
+#include <netinet/ip6.h>
+#include <linux/if_bridge.h>
 
 #include "btio/btio.h"
 #include "lib/bluetooth.h"
@@ -54,7 +57,6 @@
 #define BNEP_BRIDGE "bt-pan"
 #define BNEP_PANU_INTERFACE "bt-pan"
 #define BNEP_NAP_INTERFACE "bt-pan%d"
-#define FORWARD_DELAY_PATH "/sys/class/net/"BNEP_BRIDGE"/bridge/forward_delay"
 
 static bdaddr_t adapter_addr;
 GSList *devices = NULL;
@@ -80,25 +82,22 @@ static struct {
 	.bridge = false,
 };
 
-
-static int set_forward_delay(void)
+static int set_forward_delay(int sk)
 {
-	int fd, ret;
-
-	fd = open(FORWARD_DELAY_PATH, O_RDWR);
-	if (fd < 0) {
-		int err = -errno;
+	unsigned long args[4] = { BRCTL_SET_BRIDGE_FORWARD_DELAY, 0 ,0, 0 };
+	struct ifreq ifr;
 
-		error("pan: open forward delay file failed: %d (%s)",
-							-err, strerror(-err));
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_name, BNEP_BRIDGE, IFNAMSIZ);
+	ifr.ifr_data = (char *) args;
 
-		return err;
+	if (ioctl(sk, SIOCDEVPRIVATE, &ifr) < 0) {
+		error("pan: setting forward delay failed: %d (%s)",
+							errno, strerror(errno));
+		return -1;
 	}
 
-	ret = write(fd, "0", sizeof("0"));
-	close(fd);
-
-	return ret;
+	return 0;
 }
 
 static int nap_create_bridge(void)
@@ -122,7 +121,7 @@ static int nap_create_bridge(void)
 		}
 	}
 
-	err = set_forward_delay();
+	err = set_forward_delay(sk);
 	if (err < 0)
 		ioctl(sk, SIOCBRDELBR, BNEP_BRIDGE);
 
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH v3 7/8] android/pan: Pass error in nap_remove_bridge
From: Szymon Janc @ 2014-02-06 15:28 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1391700522-9036-1-git-send-email-szymon.janc@tieto.com>

Don't return EOPNOTSUPP but just pass error from errno.
---
 android/pan.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/android/pan.c b/android/pan.c
index 1cb82a1..418e2a4 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -146,10 +146,13 @@ static int nap_remove_bridge(void)
 		return -EOPNOTSUPP;
 
 	err = ioctl(sk, SIOCBRDELBR, BNEP_BRIDGE);
+	if (err < 0)
+		err = -errno;
+
 	close(sk);
 
 	if (err < 0)
-		return -EOPNOTSUPP;
+		return err;
 
 	nap_dev.bridge = false;
 
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH v3 8/8] android/pan: Bring bridge interface down before removing it
From: Szymon Janc @ 2014-02-06 15:28 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1391700522-9036-1-git-send-email-szymon.janc@tieto.com>

Otherwise bridge will be 'in use' and won't be removed.
---
 android/pan.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/android/pan.c b/android/pan.c
index 418e2a4..bcbb3d8 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -132,6 +132,31 @@ static int nap_create_bridge(void)
 	return err;
 }
 
+static int bridge_if_down(void)
+{
+	struct ifreq ifr;
+	int sk, err;
+
+	sk = socket(AF_INET, SOCK_DGRAM, 0);
+
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_name, BNEP_BRIDGE, IF_NAMESIZE - 1);
+
+	ifr.ifr_flags &= ~IFF_UP;
+
+	/* Bring down the interface */
+	err = ioctl(sk, SIOCSIFFLAGS, (caddr_t) &ifr);
+
+	close(sk);
+
+	if (err < 0) {
+		error("pan: Could not bring down %s", BNEP_BRIDGE);
+		return err;
+	}
+
+	return 0;
+}
+
 static int nap_remove_bridge(void)
 {
 	int sk, err;
@@ -141,6 +166,8 @@ static int nap_remove_bridge(void)
 	if (!nap_dev.bridge)
 		return 0;
 
+	bridge_if_down();
+
 	sk = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
 	if (sk < 0)
 		return -EOPNOTSUPP;
-- 
1.8.3.2


^ permalink raw reply related

* Re: [RFC v8 06/10] Bluetooth: Introduce LE auto connection infrastructure
From: Vinicius Costa Gomes @ 2014-02-06 16:02 UTC (permalink / raw)
  To: Andre Guedes; +Cc: linux-bluetooth
In-Reply-To: <1391639006-26311-6-git-send-email-andre.guedes@openbossa.org>

Hi Andre,

On 19:23 Wed 05 Feb, Andre Guedes wrote:
> 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.
>
> Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
> ---

[snip]

>  static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
>  {
>  	u8 num_reports = skb->data[0];
>  	void *ptr = &skb->data[1];
>  	s8 rssi;
>
> +	hci_dev_lock(hdev);
> +
>  	while (num_reports--) {
>  		struct hci_ev_le_advertising_info *ev = ptr;
>
> +		check_pending_le_conn(hdev, &ev->bdaddr, ev->bdaddr_type);
> +

Shouldn't the event type be checked to see if it is a connectable event?

>  		rssi = ev->data[ev->length];
>  		mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
>  				  NULL, rssi, 0, 1, ev->data, ev->length);
>
>  		ptr += sizeof(*ev) + ev->length + 1;
>  	}
> +
> +	hci_dev_unlock(hdev);
>  }
>
>  static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
> --
> 1.8.5.3
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


Cheers,
--
Vinicius

^ permalink raw reply

* [PATCH 1/4] android/avrcp: Decouple AVRCP logic from btio
From: Andrei Emeltchenko @ 2014-02-06 16:06 UTC (permalink / raw)
  To: linux-bluetooth

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

The patch makes AVRCP to be channel-agnostic so that it might be used in
unit tests. The idea is that all AVRCP logic would come to avrcp-lib and
channel stuff got to avrcp.
---
 android/Android.mk  |  1 +
 android/Makefile.am |  1 +
 android/avrcp-lib.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 android/avrcp-lib.h | 34 +++++++++++++++++++++++
 android/avrcp.c     | 60 ++++++----------------------------------
 5 files changed, 125 insertions(+), 51 deletions(-)
 create mode 100644 android/avrcp-lib.c
 create mode 100644 android/avrcp-lib.h

diff --git a/android/Android.mk b/android/Android.mk
index 20105e6..9b10cfe 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -30,6 +30,7 @@ LOCAL_SRC_FILES := \
 	bluez/android/avdtp.c \
 	bluez/android/a2dp.c \
 	bluez/android/avctp.c \
+	bluez/android/avrcp-lib.c \
 	bluez/android/avrcp.c \
 	bluez/android/pan.c \
 	bluez/android/handsfree.c \
diff --git a/android/Makefile.am b/android/Makefile.am
index 5baa8db..3032940 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -36,6 +36,7 @@ android_bluetoothd_SOURCES = android/main.c \
 				android/avdtp.h android/avdtp.c \
 				android/a2dp.h android/a2dp.c \
 				android/avctp.h android/avctp.c \
+				android/avrcp-lib.h android/avrcp-lib.c \
 				android/avrcp.h android/avrcp.c \
 				android/socket.h android/socket.c \
 				android/pan.h android/pan.c \
diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
new file mode 100644
index 0000000..6dcc8ac
--- /dev/null
+++ b/android/avrcp-lib.c
@@ -0,0 +1,80 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2014  Intel Corporation. All rights reserved.
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdbool.h>
+#include <glib.h>
+
+#include "lib/bluetooth.h"
+
+#include "src/log.h"
+
+#include "avctp.h"
+#include "avrcp-lib.h"
+
+static GSList *devices = NULL;
+
+void avrcp_device_remove(struct avrcp_device *dev)
+{
+	devices = g_slist_remove(devices, dev);
+	avrcp_device_free(dev);
+}
+
+void avrcp_free_all(void)
+{
+	g_slist_free_full(devices, avrcp_device_free);
+	devices = NULL;
+}
+
+struct avrcp_device *avrcp_device_new(const bdaddr_t *dst)
+{
+	struct avrcp_device *dev;
+
+	dev = g_new0(struct avrcp_device, 1);
+	bacpy(&dev->dst, dst);
+	devices = g_slist_prepend(devices, dev);
+
+	return dev;
+}
+
+static int device_cmp(gconstpointer s, gconstpointer user_data)
+{
+	const struct avrcp_device *dev = s;
+	const bdaddr_t *dst = user_data;
+
+	return bacmp(&dev->dst, dst);
+}
+
+struct avrcp_device *avrcp_find(const bdaddr_t *dst)
+{
+	GSList *l;
+
+	l = g_slist_find_custom(devices, dst, device_cmp);
+	if (!l)
+		return NULL;
+
+	return l->data;
+}
diff --git a/android/avrcp-lib.h b/android/avrcp-lib.h
new file mode 100644
index 0000000..bf6872e
--- /dev/null
+++ b/android/avrcp-lib.h
@@ -0,0 +1,34 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2014  Intel Corporation. All rights reserved.
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+struct avrcp_device {
+	bdaddr_t	dst;
+	struct avctp	*session;
+	GIOChannel      *io;
+};
+
+struct avrcp_device *avrcp_device_new(const bdaddr_t *dst);
+void avrcp_device_free(void *data);
+void avrcp_device_remove(struct avrcp_device *dev);
+void avrcp_free_all(void);
+struct avrcp_device *avrcp_find(const bdaddr_t *dst);
diff --git a/android/avrcp.c b/android/avrcp.c
index 7ee5a8a..22f0a04 100644
--- a/android/avrcp.c
+++ b/android/avrcp.c
@@ -38,6 +38,7 @@
 #include "hal-msg.h"
 #include "ipc.h"
 #include "avctp.h"
+#include "avrcp-lib.h"
 
 #define L2CAP_PSM_AVCTP 0x17
 
@@ -48,15 +49,8 @@
 
 static bdaddr_t adapter_addr;
 static uint32_t record_id = 0;
-static GSList *devices = NULL;
 static GIOChannel *server = NULL;
 
-struct avrcp_device {
-	bdaddr_t	dst;
-	struct avctp	*session;
-	GIOChannel	*io;
-};
-
 static const struct ipc_handler cmd_handlers[] = {
 };
 
@@ -128,7 +122,7 @@ static sdp_record_t *avrcp_record(void)
 	return record;
 }
 
-static void avrcp_device_free(void *data)
+void avrcp_device_free(void *data)
 {
 	struct avrcp_device *dev = data;
 
@@ -143,31 +137,6 @@ static void avrcp_device_free(void *data)
 	g_free(dev);
 }
 
-static void avrcp_device_remove(struct avrcp_device *dev)
-{
-	devices = g_slist_remove(devices, dev);
-	avrcp_device_free(dev);
-}
-
-static struct avrcp_device *avrcp_device_new(const bdaddr_t *dst)
-{
-	struct avrcp_device *dev;
-
-	dev = g_new0(struct avrcp_device, 1);
-	bacpy(&dev->dst, dst);
-	devices = g_slist_prepend(devices, dev);
-
-	return dev;
-}
-
-static int device_cmp(gconstpointer s, gconstpointer user_data)
-{
-	const struct avrcp_device *dev = s;
-	const bdaddr_t *dst = user_data;
-
-	return bacmp(&dev->dst, dst);
-}
-
 static void disconnect_cb(void *data)
 {
 	struct avrcp_device *dev = data;
@@ -186,7 +155,6 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
 	char address[18];
 	uint16_t imtu, omtu;
 	GError *gerr = NULL;
-	GSList *l;
 	int fd;
 
 	if (err) {
@@ -209,13 +177,9 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
 
 	ba2str(&dst, address);
 
-	l = g_slist_find_custom(devices, &dst, device_cmp);
-	if (l) {
-		dev = l->data;
-		if (dev->session) {
-			error("Unexpected connection");
-			return;
-		}
+	if (avrcp_find(&dst)) {
+		error("Unexpected connection");
+		return;
 	} else {
 		DBG("Incoming connection from %s", address);
 		dev = avrcp_device_new(&dst);
@@ -293,8 +257,7 @@ void bt_avrcp_unregister(void)
 {
 	DBG("");
 
-	g_slist_free_full(devices, avrcp_device_free);
-	devices = NULL;
+	avrcp_free_all();
 
 	ipc_unregister(HAL_SERVICE_ID_AVRCP);
 
@@ -331,12 +294,10 @@ void bt_avrcp_connect(const bdaddr_t *dst)
 {
 	struct avrcp_device *dev;
 	char addr[18];
-	GSList *l;
 
 	DBG("");
 
-	l = g_slist_find_custom(devices, dst, device_cmp);
-	if (l)
+	if (avrcp_find(dst))
 		return;
 
 	dev = avrcp_device_new(dst);
@@ -352,16 +313,13 @@ void bt_avrcp_connect(const bdaddr_t *dst)
 void bt_avrcp_disconnect(const bdaddr_t *dst)
 {
 	struct avrcp_device *dev;
-	GSList *l;
 
 	DBG("");
 
-	l = g_slist_find_custom(devices, dst, device_cmp);
-	if (!l)
+	dev = avrcp_find(dst);
+	if (!dev)
 		return;
 
-	dev = l->data;
-
 	if (dev->session) {
 		avctp_shutdown(dev->session);
 		return;
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH 2/4] unit/avrcp: First unit test for AVRCP profile
From: Andrei Emeltchenko @ 2014-02-06 16:06 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391702774-18972-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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

Test TP/MPS/BV-01-C [SetAddressedPlayer – CT] verifies
SetAddressedPlayer command.
---
 Makefile.am       |   9 ++
 unit/test-avrcp.c | 331 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 340 insertions(+)
 create mode 100644 unit/test-avrcp.c

diff --git a/Makefile.am b/Makefile.am
index 1a44a9f..67b7167 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -281,6 +281,15 @@ unit_test_avctp_SOURCES = unit/test-avctp.c \
 				android/avctp.c android/avctp.h
 unit_test_avctp_LDADD = @GLIB_LIBS@
 
+unit_tests += unit/test-avrcp
+
+unit_test_avrcp_SOURCES = unit/test-avrcp.c \
+				src/shared/util.h src/shared/util.c \
+				src/log.h src/log.c \
+				android/avctp.c android/avctp.h \
+				android/avrcp-lib.c android/avrcp-lib.h
+unit_test_avrcp_LDADD = @GLIB_LIBS@ lib/libbluetooth-internal.la
+
 unit_tests += unit/test-gdbus-client
 
 unit_test_gdbus_client_SOURCES = unit/test-gdbus-client.c
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
new file mode 100644
index 0000000..7efdaea
--- /dev/null
+++ b/unit/test-avrcp.c
@@ -0,0 +1,331 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2014  Intel Corporation. All rights reserved.
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <inttypes.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+
+#include <glib.h>
+
+#include "src/shared/util.h"
+#include "src/log.h"
+#include "lib/bluetooth.h"
+
+#include "android/avctp.h"
+#include "android/avrcp-lib.h"
+
+#define IEEEID_BTSIG		0x001958
+
+struct test_pdu {
+	bool valid;
+	bool fragmented;
+	const uint8_t *data;
+	size_t size;
+};
+
+struct test_data {
+	char *test_name;
+	struct test_pdu *pdu_list;
+};
+
+struct context {
+	GMainLoop *main_loop;
+	struct avrcp_device *dev;
+	guint source;
+	guint process;
+	int fd;
+	unsigned int pdu_offset;
+	const struct test_data *data;
+};
+
+#define data(args...) ((const unsigned char[]) { args })
+
+#define raw_pdu(args...)					\
+	{							\
+		.valid = true,					\
+		.data = data(args),				\
+		.size = sizeof(data(args)),			\
+	}
+
+#define frg_pdu(args...)					\
+	{							\
+		.valid = true,					\
+		.fragmented = true,				\
+		.data = data(args),				\
+		.size = sizeof(data(args)),			\
+	}
+
+#define define_test(name, function, args...)				\
+	do {								\
+		const struct test_pdu pdus[] = {			\
+			args, { }					\
+		};							\
+		static struct test_data data;				\
+		data.test_name = g_strdup(name);			\
+		data.pdu_list = g_malloc(sizeof(pdus));			\
+		memcpy(data.pdu_list, pdus, sizeof(pdus));		\
+		g_test_add_data_func(name, &data, function);		\
+	} while (0)
+
+static void test_debug(const char *str, void *user_data)
+{
+	const char *prefix = user_data;
+
+	g_print("%s%s\n", prefix, str);
+}
+
+static void test_free(gconstpointer user_data)
+{
+	const struct test_data *data = user_data;
+
+	g_free(data->test_name);
+	g_free(data->pdu_list);
+}
+
+static gboolean context_quit(gpointer user_data)
+{
+	struct context *context = user_data;
+
+	if (context->process > 0)
+		g_source_remove(context->process);
+
+	g_main_loop_quit(context->main_loop);
+
+	return FALSE;
+}
+
+static gboolean send_pdu(gpointer user_data)
+{
+	struct context *context = user_data;
+	const struct test_pdu *pdu;
+	ssize_t len;
+
+	pdu = &context->data->pdu_list[context->pdu_offset++];
+
+	len = write(context->fd, pdu->data, pdu->size);
+
+	if (g_test_verbose())
+		util_hexdump('<', pdu->data, len, test_debug, "AVCTP: ");
+
+	g_assert_cmpint(len, ==, pdu->size);
+
+	if (pdu->fragmented)
+		return send_pdu(user_data);
+
+	context->process = 0;
+	return FALSE;
+}
+
+static void context_process(struct context *context)
+{
+	if (!context->data->pdu_list[context->pdu_offset].valid) {
+		context_quit(context);
+		return;
+	}
+
+	context->process = g_idle_add(send_pdu, context);
+}
+
+static gboolean test_handler(GIOChannel *channel, GIOCondition cond,
+							gpointer user_data)
+{
+	struct context *context = user_data;
+	const struct test_pdu *pdu;
+	unsigned char buf[512];
+	ssize_t len;
+	int fd;
+
+	pdu = &context->data->pdu_list[context->pdu_offset++];
+
+	if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
+		context->source = 0;
+		g_print("%s: cond %x\n", __func__, cond);
+		return FALSE;
+	}
+
+	fd = g_io_channel_unix_get_fd(channel);
+
+	len = read(fd, buf, sizeof(buf));
+
+	g_assert(len > 0);
+
+	if (g_test_verbose())
+		util_hexdump('>', buf, len, test_debug, "AVCTP: ");
+
+	g_assert_cmpint(len, ==, pdu->size);
+
+	g_assert(memcmp(buf, pdu->data, pdu->size) == 0);
+
+	if (!pdu->fragmented)
+		context_process(context);
+
+	return TRUE;
+}
+
+static struct context *create_context(uint16_t version, gconstpointer data)
+{
+	struct context *context = g_new0(struct context, 1);
+	GIOChannel *channel;
+	int err, sv[2];
+	bdaddr_t dst = {};
+
+	context->main_loop = g_main_loop_new(NULL, FALSE);
+	g_assert(context->main_loop);
+
+	err = socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0, sv);
+	g_assert(err == 0);
+
+	context->dev = avrcp_device_new(&dst);
+	context->dev->session = avctp_new(sv[0], 672, 672, version);
+	g_assert(context->dev->session != NULL);
+
+	channel = g_io_channel_unix_new(sv[1]);
+
+	g_io_channel_set_close_on_unref(channel, TRUE);
+	g_io_channel_set_encoding(channel, NULL, NULL);
+	g_io_channel_set_buffered(channel, FALSE);
+
+	context->source = g_io_add_watch(channel,
+				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+				test_handler, context);
+	g_assert(context->source > 0);
+
+	g_io_channel_unref(channel);
+
+	context->fd = sv[1];
+	context->data = data;
+
+	return context;
+}
+
+static void execute_context(struct context *context)
+{
+	g_main_loop_run(context->main_loop);
+
+	if (context->source > 0)
+		g_source_remove(context->source);
+
+	avrcp_device_free(context->dev);
+
+	g_main_loop_unref(context->main_loop);
+
+	test_free(context->data);
+	g_free(context);
+}
+
+#define AVRCP_SET_ADDRESSED_PLAYER	0x60
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+
+struct avrcp_header {
+	uint8_t company_id[3];
+	uint8_t pdu_id;
+	uint8_t packet_type:2;
+	uint8_t rsvd:6;
+	uint16_t params_len;
+	uint8_t params[0];
+} __attribute__ ((packed));
+#define AVRCP_HEADER_LENGTH 7
+
+#elif __BYTE_ORDER == __BIG_ENDIAN
+
+struct avrcp_header {
+	uint8_t company_id[3];
+	uint8_t pdu_id;
+	uint8_t rsvd:6;
+	uint8_t packet_type:2;
+	uint16_t params_len;
+	uint8_t params[0];
+} __attribute__ ((packed));
+#define AVRCP_HEADER_LENGTH 7
+
+#else
+#error "Unknown byte order"
+#endif
+
+static void set_company_id(uint8_t cid[3], const uint32_t cid_in)
+{
+	cid[0] = cid_in >> 16;
+	cid[1] = cid_in >> 8;
+	cid[2] = cid_in;
+}
+
+static int avrcp_set_addr_player(struct context *context)
+{
+	uint8_t buf[AVRCP_HEADER_LENGTH + 2];
+	struct avrcp_header *pdu = (void *) buf;
+	struct avctp *session = context->dev->session;
+
+	memset(buf, 0, sizeof(buf));
+
+	set_company_id(pdu->company_id, IEEEID_BTSIG);
+
+	pdu->pdu_id = AVRCP_SET_ADDRESSED_PLAYER;
+	pdu->params[0] = 0xab;
+	pdu->params[1] = 0xcd;
+	pdu->params_len = htons(2);
+
+	return avctp_send_vendordep_req(session, AVC_CTYPE_CONTROL,
+					AVC_SUBUNIT_PANEL, buf, sizeof(buf),
+					NULL, NULL);
+}
+
+static void test_client(gconstpointer data)
+{
+	struct context *context = create_context(0x0100, data);
+	int ret = 0;
+
+	if (g_str_equal(context->data->test_name, "/TP/MPS/BV-01-C"))
+		ret = avrcp_set_addr_player(context);
+
+	DBG("ret = %d", ret);
+
+	g_assert(!ret);
+
+	execute_context(context);
+}
+
+int main(int argc, char *argv[])
+{
+	g_test_init(&argc, &argv, NULL);
+
+	if (g_test_verbose())
+		__btd_log_init("*", 0);
+
+	/* Media Player Selection Commands and Notifications tests */
+
+	define_test("/TP/MPS/BV-01-C", test_client,
+			raw_pdu(0x00, 0x11, 0x0e, 0x00, 0x48, 0x00,
+				0x00, 0x19, 0x58, 0x60, 0x00, 0x00,
+				0x02, 0xab, 0xcd));
+
+	return g_test_run();
+}
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH 3/4] unit/avrcp: Add support for browsing AVCTP channel
From: Andrei Emeltchenko @ 2014-02-06 16:06 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391702774-18972-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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

---
 unit/test-avrcp.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 92 insertions(+), 4 deletions(-)

diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index 7efdaea..58e4c15 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -47,6 +47,7 @@
 struct test_pdu {
 	bool valid;
 	bool fragmented;
+	bool browse;
 	const uint8_t *data;
 	size_t size;
 };
@@ -60,8 +61,10 @@ struct context {
 	GMainLoop *main_loop;
 	struct avrcp_device *dev;
 	guint source;
+	guint browse_source;
 	guint process;
 	int fd;
+	int browse_fd;
 	unsigned int pdu_offset;
 	const struct test_data *data;
 };
@@ -75,6 +78,14 @@ struct context {
 		.size = sizeof(data(args)),			\
 	}
 
+#define brs_pdu(args...)					\
+	{							\
+		.valid = true,					\
+		.browse = true,					\
+		.data = data(args),				\
+		.size = sizeof(data(args)),			\
+	}
+
 #define frg_pdu(args...)					\
 	{							\
 		.valid = true,					\
@@ -130,7 +141,10 @@ static gboolean send_pdu(gpointer user_data)
 
 	pdu = &context->data->pdu_list[context->pdu_offset++];
 
-	len = write(context->fd, pdu->data, pdu->size);
+	if (pdu->browse)
+		len = write(context->browse_fd, pdu->data, pdu->size);
+	else
+		len = write(context->fd, pdu->data, pdu->size);
 
 	if (g_test_verbose())
 		util_hexdump('<', pdu->data, len, test_debug, "AVCTP: ");
@@ -163,6 +177,8 @@ static gboolean test_handler(GIOChannel *channel, GIOCondition cond,
 	ssize_t len;
 	int fd;
 
+	DBG("");
+
 	pdu = &context->data->pdu_list[context->pdu_offset++];
 
 	if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
@@ -190,23 +206,68 @@ static gboolean test_handler(GIOChannel *channel, GIOCondition cond,
 	return TRUE;
 }
 
+static gboolean browse_test_handler(GIOChannel *channel, GIOCondition cond,
+							gpointer user_data)
+{
+	struct context *context = user_data;
+	const struct test_pdu *pdu;
+	unsigned char buf[512];
+	ssize_t len;
+	int fd;
+
+	pdu = &context->data->pdu_list[context->pdu_offset++];
+
+	if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
+		context->browse_source = 0;
+		g_print("%s: cond %x\n", __func__, cond);
+		return FALSE;
+	}
+
+	fd = g_io_channel_unix_get_fd(channel);
+
+	len = read(fd, buf, sizeof(buf));
+
+	g_assert(len > 0);
+
+	if (g_test_verbose())
+		util_hexdump('>', buf, len, test_debug, "AVCTP: ");
+
+	g_assert_cmpint(len, ==, pdu->size);
+
+	g_assert(memcmp(buf, pdu->data, pdu->size) == 0);
+
+	if (!pdu->fragmented)
+		context_process(context);
+
+	return TRUE;
+}
+
 static struct context *create_context(uint16_t version, gconstpointer data)
 {
 	struct context *context = g_new0(struct context, 1);
+	struct avctp *session;
 	GIOChannel *channel;
 	int err, sv[2];
 	bdaddr_t dst = {};
+	int ret;
+
+	DBG("");
 
 	context->main_loop = g_main_loop_new(NULL, FALSE);
 	g_assert(context->main_loop);
 
+	/* Control channel setup */
+
 	err = socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0, sv);
-	g_assert(err == 0);
+	g_assert(!err);
 
 	context->dev = avrcp_device_new(&dst);
-	context->dev->session = avctp_new(sv[0], 672, 672, version);
-	g_assert(context->dev->session != NULL);
+	g_assert(context->dev);
 
+	session = avctp_new(sv[0], 672, 672, version);
+	g_assert(session);
+
+	context->dev->session = session;
 	channel = g_io_channel_unix_new(sv[1]);
 
 	g_io_channel_set_close_on_unref(channel, TRUE);
@@ -221,6 +282,30 @@ static struct context *create_context(uint16_t version, gconstpointer data)
 	g_io_channel_unref(channel);
 
 	context->fd = sv[1];
+
+	/* Browsing channel setup */
+
+	err = socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0, sv);
+	g_assert(!err);
+
+	ret = avctp_connect_browsing(session, sv[0], 672, 672);
+	g_assert(!ret);
+
+	channel = g_io_channel_unix_new(sv[1]);
+
+	g_io_channel_set_close_on_unref(channel, TRUE);
+	g_io_channel_set_encoding(channel, NULL, NULL);
+	g_io_channel_set_buffered(channel, FALSE);
+
+	context->browse_source = g_io_add_watch(channel,
+				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+				browse_test_handler, context);
+	g_assert(context->browse_source > 0);
+
+	g_io_channel_unref(channel);
+
+	context->browse_fd = sv[1];
+
 	context->data = data;
 
 	return context;
@@ -233,6 +318,9 @@ static void execute_context(struct context *context)
 	if (context->source > 0)
 		g_source_remove(context->source);
 
+	if (context->browse_source > 0)
+		g_source_remove(context->browse_source);
+
 	avrcp_device_free(context->dev);
 
 	g_main_loop_unref(context->main_loop);
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH 4/4] unit/avrcp: Add TP/MPS/BV-03-C test case
From: Andrei Emeltchenko @ 2014-02-06 16:06 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391702774-18972-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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

Test verifies that the Set Browsed Player command issued by the
AVRCP controller.
---
 unit/test-avrcp.c | 43 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index 58e4c15..211ea36 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -330,6 +330,7 @@ static void execute_context(struct context *context)
 }
 
 #define AVRCP_SET_ADDRESSED_PLAYER	0x60
+#define AVRCP_SET_BROWSED_PLAYER	0x70
 
 #if __BYTE_ORDER == __LITTLE_ENDIAN
 
@@ -359,6 +360,13 @@ struct avrcp_header {
 #error "Unknown byte order"
 #endif
 
+struct avrcp_browsing_header {
+	uint8_t pdu_id;
+	uint16_t param_len;
+	uint8_t params[0];
+} __attribute__ ((packed));
+#define AVRCP_BROWSING_HEADER_LENGTH 3
+
 static void set_company_id(uint8_t cid[3], const uint32_t cid_in)
 {
 	cid[0] = cid_in >> 16;
@@ -386,6 +394,35 @@ static int avrcp_set_addr_player(struct context *context)
 					NULL, NULL);
 }
 
+static gboolean avrcp_set_browsed_player_rsp(struct avctp *conn,
+						uint8_t *operands,
+						size_t operand_count,
+						void *user_data)
+{
+	DBG("");
+
+	return FALSE;
+}
+
+static int avrcp_set_browsed_player(struct context *context)
+{
+	uint8_t buf[AVRCP_BROWSING_HEADER_LENGTH + 2];
+	struct avrcp_browsing_header *pdu = (void *) buf;
+	struct avctp *session = context->dev->session;
+
+	DBG("");
+
+	memset(buf, 0, sizeof(buf));
+
+	pdu->pdu_id = AVRCP_SET_BROWSED_PLAYER;
+	pdu->params[0] = 0xab;
+	pdu->params[1] = 0xcd;
+	pdu->param_len = htons(2);
+
+	return avctp_send_browsing_req(session, buf, sizeof(buf),
+					avrcp_set_browsed_player_rsp, session);
+}
+
 static void test_client(gconstpointer data)
 {
 	struct context *context = create_context(0x0100, data);
@@ -394,6 +431,9 @@ static void test_client(gconstpointer data)
 	if (g_str_equal(context->data->test_name, "/TP/MPS/BV-01-C"))
 		ret = avrcp_set_addr_player(context);
 
+	if (g_str_equal(context->data->test_name, "/TP/MPS/BV-03-C"))
+		ret = avrcp_set_browsed_player(context);
+
 	DBG("ret = %d", ret);
 
 	g_assert(!ret);
@@ -415,5 +455,8 @@ int main(int argc, char *argv[])
 				0x00, 0x19, 0x58, 0x60, 0x00, 0x00,
 				0x02, 0xab, 0xcd));
 
+	define_test("/TP/MPS/BV-03-C", test_client,
+			raw_pdu(0x00, 0x11, 0x0e, 0x70, 0x00, 0x02,
+				0xab, 0xcd));
 	return g_test_run();
 }
-- 
1.8.3.2


^ permalink raw reply related

* Re: LE Connection Update Disallowed
From: Sandy Chapman @ 2014-02-06 16:21 UTC (permalink / raw)
  To: Anderson Lizardo; +Cc: BlueZ development
In-Reply-To: <CAJdJm_MScMpFNekv-9E3eFneNmLsgdurKb-R3kMTP66Gy40yaQ@mail.gmail.com>

Hi Anderson,

On Wed, Feb 5, 2014 at 11:23 AM, Anderson Lizardo
<anderson.lizardo@openbossa.org> wrote:
> HI Sandy,
>
> On Wed, Feb 5, 2014 at 10:51 AM, Sandy Chapman <schapman@lixar.com> wrote:
>>>> How do I initiate a Connection Update from the peripheral?
>>>
>>> I never tried this procedure myself, but my guess it that you are
>>> using the incorrect mechanism on the slave role. Take a look at the
>>> "Connection Parameters Update Request" on Vol 3, Part A, Section 4.20.
>>> I believe this is the correct way to request from the slave (from what
>>> I understand while reading the Linux kernel implementation of the
>>> master side).
>>>
>>> Note that when Linux is the master, this command is issued
>>> automatically by the kernel when requested by the slave.
>>
>> I've taken a look at that section and it appears that this is what is
>> used to trigger the Connection Update. It states that the command
>> shall only be issued from the slave to the master. I can confirm that
>> my device is in the slave role using 'hcitool con'.
>
> I think you didn't notice that the section I mentioned is about a
> L2CAP signalling packet, not an HCI command (which in this case is to
> be used on the master side). I suggest you read a bit more on the
> L2CAP section to understand how these signalling packets work. Then
> you can try building such packet with "hcitool cmd" (unless there is
> some support for it on the current kernel, which I didn't check)
>

Yes, you right, I missed that part. I've built out what my packet
should look like, but I'm having troubles sending it to the
controller. I really am stuck on issuing this packet. It appears that
I need to send an HCI ACL Data Packet which holds a Signalling
Command. This signalling command then holds the connection parameter
update request as it's payload. It looks like 'hcitool cmd' can't send
ACL packets though as the command requires an OGF and OCF which are
part of the HCI Command Packet, not the HCI ACL Data Packet. From what
I can tell, the best chance I'd have is to send it via the l2test tool
over L2CAP, but attempting to use le_public address type doesn't work
(which I believe will send the message over CID 0x0005 - the fixed LE
channel). It fails on getsockopt/setsockopt for the SOL_BLUETOOTH
type. From what I can tell, it requires a kernel with CoC (not sure
what it means or if I have it). I'm really hoping I'm not going to
have to compile the bluetooth kernel module myself to send this
connection update packet.

>>> You may want to take a look at the "GAP Peripheral Preferred
>>> Connection Parameters" characteristic (see Vol 3, Part C, Section
>>> 12.3). If iPhones reads this characteristic and honours the
>>> parameters, it may help.
>>
>> Unfortunately, it appears Apple explicitly ignores this parameter
>> (section 3.6 in this document
>> https://developer.apple.com/hardwaredrivers/BluetoothDesignGuidelines.pdf).
>
> This is unfortunate. It would be the easiest way to pass custom
> connection parameters IMHO.
>
>> I believe that 'hcitool lecup' is exactly supposed to initiate this
>> process. I've also tried to use 'hcitool cmd' to issue direct commands
>> to the controller (using Vol 3, Part A, Section 4.20 as a guide), but
>> I am having no luck. It's stating that the command is disallowed (not
>> that the parameters are invalid), so I'm guessing there's something
>> else wrong. Since this is directly communicating with the controller,
>> where would the problem be? In the kernel, itself? Could it be a
>> problem with the Broadcom chipset in my MacBook?
>
> "hcitool lecup" is just a helper, it uses the same mechanism that
> "hcitool cmd" uses (and both are just "raw" interfaces to the
> Bluetooth controller). If you are getting an "Invalid Parameters" on
> any of them, is either because you built the packet incorrectly on
> "hcitool cmd" or given invalid values as per the spec.
>
> By the way, I suggest using "btmon" instead of "hcidump", as the
> former has nicer output and is more up-to-date (although I'm not sure
> it supports parsing "LE Connection Update" parameters).
>

You're right btmon is much nicer and does support recognition of the
LE commands.

> Best Regards,
> --
> Anderson Lizardo
> http://www.indt.org/?lang=en
> INdT - Manaus - Brazil

I know what I'm doing might not be typical, but I really appreciate
your help. If there's any direction you could point me in, I'd be
really thankful. I don't really know what to try next.

Thanks again,

Sandy

-- 


^ permalink raw reply

* Re: [RFC v8 06/10] Bluetooth: Introduce LE auto connection infrastructure
From: Andre Guedes @ 2014-02-06 17:34 UTC (permalink / raw)
  To: Vinicius Costa Gomes; +Cc: linux-bluetooth
In-Reply-To: <20140206160209.GA26623@molly>

Hi Vinicius,

On Thu, 2014-02-06 at 14:02 -0200, Vinicius Costa Gomes wrote:
> Hi Andre,
> 
> On 19:23 Wed 05 Feb, Andre Guedes wrote:
> > 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.
> >
> > Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
> > ---
> 
> [snip]
> 
> >  static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
> >  {
> >  	u8 num_reports = skb->data[0];
> >  	void *ptr = &skb->data[1];
> >  	s8 rssi;
> >
> > +	hci_dev_lock(hdev);
> > +
> >  	while (num_reports--) {
> >  		struct hci_ev_le_advertising_info *ev = ptr;
> >
> > +		check_pending_le_conn(hdev, &ev->bdaddr, ev->bdaddr_type);
> > +
> 
> Shouldn't the event type be checked to see if it is a connectable event?

Sure. I'm fixing it.

Thanks,

Andre



^ 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