Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCHv5 4/7] android: Rename hal_bluetooth.c to hal-bluetooth.c
From: Andrei Emeltchenko @ 2013-10-17  8:26 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1381998406-16662-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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

---
 android/Android.mk      |    2 +-
 android/hal-bluetooth.c |  384 +++++++++++++++++++++++++++++++++++++++++++++++
 android/hal_bluetooth.c |  384 -----------------------------------------------
 3 files changed, 385 insertions(+), 385 deletions(-)
 create mode 100644 android/hal-bluetooth.c
 delete mode 100644 android/hal_bluetooth.c

diff --git a/android/Android.mk b/android/Android.mk
index 22f8b92..753267a 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -51,7 +51,7 @@ include $(BUILD_EXECUTABLE)
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES := \
-	hal_bluetooth.c \
+	hal-bluetooth.c \
 	hal_bt_sock.c \
 
 LOCAL_SHARED_LIBRARIES := \
diff --git a/android/hal-bluetooth.c b/android/hal-bluetooth.c
new file mode 100644
index 0000000..89b8ebb
--- /dev/null
+++ b/android/hal-bluetooth.c
@@ -0,0 +1,384 @@
+/*
+ * Copyright (C) 2013 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 <unistd.h>
+#include <stdbool.h>
+
+#include <hardware/bluetooth.h>
+#include <hardware/bt_sock.h>
+
+#include <cutils/sockets.h>
+#include <cutils/properties.h>
+
+#define LOG_TAG "BlueZ"
+#include <cutils/log.h>
+
+#include "hal.h"
+
+#define SERVICE_NAME "bluetoothd"
+
+bt_callbacks_t *bt_hal_cbacks = NULL;
+
+static bool interface_ready(void)
+{
+	return bt_hal_cbacks != NULL;
+}
+
+static bool start_bt_daemon(void)
+{
+	int tries = 40; /* wait 4 seconds for completion */
+
+	ALOGD(__func__);
+
+	/* Start Android Bluetooth daemon service */
+	property_set("ctl.start", SERVICE_NAME);
+
+	while (tries-- > 0) {
+		char val[PROPERTY_VALUE_MAX];
+
+		if (property_get("init.svc." SERVICE_NAME, val, NULL)) {
+			if (!strcmp(val, "running")) {
+				ALOGI("Android BlueZ daemon started");
+				return true;
+			}
+		} else {
+			return false;
+		}
+
+		usleep(100000);
+	}
+
+	return false;
+}
+
+static int init(bt_callbacks_t *callbacks)
+{
+	ALOGD(__func__);
+
+	if (interface_ready())
+		return BT_STATUS_SUCCESS;
+
+	if (start_bt_daemon()) {
+		/* TODO: open channel */
+
+		bt_hal_cbacks = callbacks;
+
+		return BT_STATUS_SUCCESS;
+	}
+
+	return BT_STATUS_UNSUPPORTED;
+}
+
+static int enable(void)
+{
+	ALOGD(__func__);
+
+	return BT_STATUS_UNSUPPORTED;
+}
+
+static int disable(void)
+{
+	ALOGD(__func__);
+
+	if (!interface_ready())
+		return BT_STATUS_NOT_READY;
+
+	return BT_STATUS_UNSUPPORTED;
+}
+
+static void cleanup(void)
+{
+	ALOGD(__func__);
+
+	if (!interface_ready())
+		return;
+
+	bt_hal_cbacks = NULL;
+}
+
+static int get_adapter_properties(void)
+{
+	ALOGD(__func__);
+
+	if (!interface_ready())
+		return BT_STATUS_NOT_READY;
+
+	return BT_STATUS_UNSUPPORTED;
+}
+
+static int get_adapter_property(bt_property_type_t type)
+{
+	ALOGD(__func__);
+
+	if (!interface_ready())
+		return BT_STATUS_NOT_READY;
+
+	return BT_STATUS_UNSUPPORTED;
+}
+
+static int set_adapter_property(const bt_property_t *property)
+{
+	ALOGD(__func__);
+
+	if (!interface_ready())
+		return BT_STATUS_NOT_READY;
+
+	if (property == NULL)
+		return BT_STATUS_PARM_INVALID;
+
+	return BT_STATUS_UNSUPPORTED;
+}
+
+static int get_remote_device_properties(bt_bdaddr_t *remote_addr)
+{
+	ALOGD(__func__);
+
+	if (!interface_ready())
+		return BT_STATUS_NOT_READY;
+
+	return BT_STATUS_UNSUPPORTED;
+}
+
+static int get_remote_device_property(bt_bdaddr_t *remote_addr,
+						bt_property_type_t type)
+{
+	ALOGD(__func__);
+
+	if (!interface_ready())
+		return BT_STATUS_NOT_READY;
+
+	return BT_STATUS_UNSUPPORTED;
+}
+
+static int set_remote_device_property(bt_bdaddr_t *remote_addr,
+						const bt_property_t *property)
+{
+	ALOGD(__func__);
+
+	if (!interface_ready())
+		return BT_STATUS_NOT_READY;
+
+	return BT_STATUS_UNSUPPORTED;
+}
+
+static int get_remote_service_record(bt_bdaddr_t *remote_addr, bt_uuid_t *uuid)
+{
+	ALOGD(__func__);
+
+	if (!interface_ready())
+		return BT_STATUS_NOT_READY;
+
+	return BT_STATUS_UNSUPPORTED;
+}
+
+static int get_remote_services(bt_bdaddr_t *remote_addr)
+{
+	ALOGD(__func__);
+
+	if (!interface_ready())
+		return BT_STATUS_NOT_READY;
+
+	return BT_STATUS_UNSUPPORTED;
+}
+
+static int start_discovery(void)
+{
+	ALOGD(__func__);
+
+	if (!interface_ready())
+		return BT_STATUS_NOT_READY;
+
+	return BT_STATUS_UNSUPPORTED;
+}
+
+static int cancel_discovery(void)
+{
+	ALOGD(__func__);
+
+	if (!interface_ready())
+		return BT_STATUS_NOT_READY;
+
+	return BT_STATUS_UNSUPPORTED;
+}
+
+static int create_bond(const bt_bdaddr_t *bd_addr)
+{
+	ALOGD(__func__);
+
+	if (!interface_ready())
+		return BT_STATUS_NOT_READY;
+
+	if (!bd_addr)
+		return BT_STATUS_PARM_INVALID;
+
+	return BT_STATUS_UNSUPPORTED;
+}
+
+static int cancel_bond(const bt_bdaddr_t *bd_addr)
+{
+	ALOGD(__func__);
+
+	if (!interface_ready())
+		return BT_STATUS_NOT_READY;
+
+	return BT_STATUS_UNSUPPORTED;
+}
+
+static int remove_bond(const bt_bdaddr_t *bd_addr)
+{
+	ALOGD(__func__);
+
+	if (!interface_ready())
+		return BT_STATUS_NOT_READY;
+
+	return BT_STATUS_UNSUPPORTED;
+}
+
+static int pin_reply(const bt_bdaddr_t *bd_addr, uint8_t accept,
+				uint8_t pin_len, bt_pin_code_t *pin_code)
+{
+	ALOGD(__func__);
+
+	if (!interface_ready())
+		return BT_STATUS_NOT_READY;
+
+	return BT_STATUS_UNSUPPORTED;
+}
+
+static int ssp_reply(const bt_bdaddr_t *bd_addr, bt_ssp_variant_t variant,
+					uint8_t accept, uint32_t passkey)
+{
+	ALOGD(__func__);
+
+	if (!interface_ready())
+		return BT_STATUS_NOT_READY;
+
+	if (!bd_addr)
+		return BT_STATUS_PARM_INVALID;
+
+	return BT_STATUS_UNSUPPORTED;
+}
+
+static const void *get_profile_interface(const char *profile_id)
+{
+	ALOGD("%s: %s", __func__, profile_id);
+
+	if (!interface_ready())
+		return NULL;
+
+	if (!strcmp(profile_id, BT_PROFILE_SOCKETS_ID))
+		return bt_get_sock_interface();
+
+	return NULL;
+}
+
+static int dut_mode_configure(uint8_t enable)
+{
+	ALOGD(__func__);
+
+	if (!interface_ready())
+		return BT_STATUS_NOT_READY;
+
+	return BT_STATUS_UNSUPPORTED;
+}
+
+static int dut_mode_send(uint16_t opcode, uint8_t *buf, uint8_t len)
+{
+	ALOGD(__func__);
+
+	if (!interface_ready())
+		return BT_STATUS_NOT_READY;
+
+	return BT_STATUS_UNSUPPORTED;
+}
+
+static const bt_interface_t bluetooth_if = {
+	.size = sizeof(bt_interface_t),
+	.init = init,
+	.enable = enable,
+	.disable = disable,
+	.cleanup = cleanup,
+	.get_adapter_properties = get_adapter_properties,
+	.get_adapter_property = get_adapter_property,
+	.set_adapter_property = set_adapter_property,
+	.get_remote_device_properties = get_remote_device_properties,
+	.get_remote_device_property = get_remote_device_property,
+	.set_remote_device_property = set_remote_device_property,
+	.get_remote_service_record = get_remote_service_record,
+	.get_remote_services = get_remote_services,
+	.start_discovery = start_discovery,
+	.cancel_discovery = cancel_discovery,
+	.create_bond = create_bond,
+	.remove_bond = remove_bond,
+	.cancel_bond = cancel_bond,
+	.pin_reply = pin_reply,
+	.ssp_reply = ssp_reply,
+	.get_profile_interface = get_profile_interface,
+	.dut_mode_configure = dut_mode_configure,
+	.dut_mode_send = dut_mode_send
+};
+
+static const bt_interface_t *get_bluetooth_interface(void)
+{
+	ALOGD(__func__);
+
+	return &bluetooth_if;
+}
+
+static int close_bluetooth(struct hw_device_t *device)
+{
+	ALOGD(__func__);
+
+	cleanup();
+
+	return 0;
+}
+
+static int open_bluetooth(const struct hw_module_t *module, char const *name,
+					struct hw_device_t **device)
+{
+	bluetooth_device_t *dev = malloc(sizeof(bluetooth_device_t));
+
+	ALOGD(__func__);
+
+	memset(dev, 0, sizeof(bluetooth_device_t));
+	dev->common.tag = HARDWARE_DEVICE_TAG;
+	dev->common.version = 0;
+	dev->common.module = (struct hw_module_t *) module;
+	dev->common.close = close_bluetooth;
+	dev->get_bluetooth_interface = get_bluetooth_interface;
+
+	*device = (struct hw_device_t *) dev;
+
+	return 0;
+}
+
+static struct hw_module_methods_t bluetooth_module_methods = {
+	.open = open_bluetooth,
+};
+
+struct hw_module_t HAL_MODULE_INFO_SYM = {
+	.tag = HARDWARE_MODULE_TAG,
+	.version_major = 1,
+	.version_minor = 0,
+	.id = BT_HARDWARE_MODULE_ID,
+	.name = "BlueZ Bluetooth stack",
+	.author = "Intel Corporation",
+	.methods = &bluetooth_module_methods
+};
diff --git a/android/hal_bluetooth.c b/android/hal_bluetooth.c
deleted file mode 100644
index 89b8ebb..0000000
--- a/android/hal_bluetooth.c
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- * Copyright (C) 2013 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 <unistd.h>
-#include <stdbool.h>
-
-#include <hardware/bluetooth.h>
-#include <hardware/bt_sock.h>
-
-#include <cutils/sockets.h>
-#include <cutils/properties.h>
-
-#define LOG_TAG "BlueZ"
-#include <cutils/log.h>
-
-#include "hal.h"
-
-#define SERVICE_NAME "bluetoothd"
-
-bt_callbacks_t *bt_hal_cbacks = NULL;
-
-static bool interface_ready(void)
-{
-	return bt_hal_cbacks != NULL;
-}
-
-static bool start_bt_daemon(void)
-{
-	int tries = 40; /* wait 4 seconds for completion */
-
-	ALOGD(__func__);
-
-	/* Start Android Bluetooth daemon service */
-	property_set("ctl.start", SERVICE_NAME);
-
-	while (tries-- > 0) {
-		char val[PROPERTY_VALUE_MAX];
-
-		if (property_get("init.svc." SERVICE_NAME, val, NULL)) {
-			if (!strcmp(val, "running")) {
-				ALOGI("Android BlueZ daemon started");
-				return true;
-			}
-		} else {
-			return false;
-		}
-
-		usleep(100000);
-	}
-
-	return false;
-}
-
-static int init(bt_callbacks_t *callbacks)
-{
-	ALOGD(__func__);
-
-	if (interface_ready())
-		return BT_STATUS_SUCCESS;
-
-	if (start_bt_daemon()) {
-		/* TODO: open channel */
-
-		bt_hal_cbacks = callbacks;
-
-		return BT_STATUS_SUCCESS;
-	}
-
-	return BT_STATUS_UNSUPPORTED;
-}
-
-static int enable(void)
-{
-	ALOGD(__func__);
-
-	return BT_STATUS_UNSUPPORTED;
-}
-
-static int disable(void)
-{
-	ALOGD(__func__);
-
-	if (!interface_ready())
-		return BT_STATUS_NOT_READY;
-
-	return BT_STATUS_UNSUPPORTED;
-}
-
-static void cleanup(void)
-{
-	ALOGD(__func__);
-
-	if (!interface_ready())
-		return;
-
-	bt_hal_cbacks = NULL;
-}
-
-static int get_adapter_properties(void)
-{
-	ALOGD(__func__);
-
-	if (!interface_ready())
-		return BT_STATUS_NOT_READY;
-
-	return BT_STATUS_UNSUPPORTED;
-}
-
-static int get_adapter_property(bt_property_type_t type)
-{
-	ALOGD(__func__);
-
-	if (!interface_ready())
-		return BT_STATUS_NOT_READY;
-
-	return BT_STATUS_UNSUPPORTED;
-}
-
-static int set_adapter_property(const bt_property_t *property)
-{
-	ALOGD(__func__);
-
-	if (!interface_ready())
-		return BT_STATUS_NOT_READY;
-
-	if (property == NULL)
-		return BT_STATUS_PARM_INVALID;
-
-	return BT_STATUS_UNSUPPORTED;
-}
-
-static int get_remote_device_properties(bt_bdaddr_t *remote_addr)
-{
-	ALOGD(__func__);
-
-	if (!interface_ready())
-		return BT_STATUS_NOT_READY;
-
-	return BT_STATUS_UNSUPPORTED;
-}
-
-static int get_remote_device_property(bt_bdaddr_t *remote_addr,
-						bt_property_type_t type)
-{
-	ALOGD(__func__);
-
-	if (!interface_ready())
-		return BT_STATUS_NOT_READY;
-
-	return BT_STATUS_UNSUPPORTED;
-}
-
-static int set_remote_device_property(bt_bdaddr_t *remote_addr,
-						const bt_property_t *property)
-{
-	ALOGD(__func__);
-
-	if (!interface_ready())
-		return BT_STATUS_NOT_READY;
-
-	return BT_STATUS_UNSUPPORTED;
-}
-
-static int get_remote_service_record(bt_bdaddr_t *remote_addr, bt_uuid_t *uuid)
-{
-	ALOGD(__func__);
-
-	if (!interface_ready())
-		return BT_STATUS_NOT_READY;
-
-	return BT_STATUS_UNSUPPORTED;
-}
-
-static int get_remote_services(bt_bdaddr_t *remote_addr)
-{
-	ALOGD(__func__);
-
-	if (!interface_ready())
-		return BT_STATUS_NOT_READY;
-
-	return BT_STATUS_UNSUPPORTED;
-}
-
-static int start_discovery(void)
-{
-	ALOGD(__func__);
-
-	if (!interface_ready())
-		return BT_STATUS_NOT_READY;
-
-	return BT_STATUS_UNSUPPORTED;
-}
-
-static int cancel_discovery(void)
-{
-	ALOGD(__func__);
-
-	if (!interface_ready())
-		return BT_STATUS_NOT_READY;
-
-	return BT_STATUS_UNSUPPORTED;
-}
-
-static int create_bond(const bt_bdaddr_t *bd_addr)
-{
-	ALOGD(__func__);
-
-	if (!interface_ready())
-		return BT_STATUS_NOT_READY;
-
-	if (!bd_addr)
-		return BT_STATUS_PARM_INVALID;
-
-	return BT_STATUS_UNSUPPORTED;
-}
-
-static int cancel_bond(const bt_bdaddr_t *bd_addr)
-{
-	ALOGD(__func__);
-
-	if (!interface_ready())
-		return BT_STATUS_NOT_READY;
-
-	return BT_STATUS_UNSUPPORTED;
-}
-
-static int remove_bond(const bt_bdaddr_t *bd_addr)
-{
-	ALOGD(__func__);
-
-	if (!interface_ready())
-		return BT_STATUS_NOT_READY;
-
-	return BT_STATUS_UNSUPPORTED;
-}
-
-static int pin_reply(const bt_bdaddr_t *bd_addr, uint8_t accept,
-				uint8_t pin_len, bt_pin_code_t *pin_code)
-{
-	ALOGD(__func__);
-
-	if (!interface_ready())
-		return BT_STATUS_NOT_READY;
-
-	return BT_STATUS_UNSUPPORTED;
-}
-
-static int ssp_reply(const bt_bdaddr_t *bd_addr, bt_ssp_variant_t variant,
-					uint8_t accept, uint32_t passkey)
-{
-	ALOGD(__func__);
-
-	if (!interface_ready())
-		return BT_STATUS_NOT_READY;
-
-	if (!bd_addr)
-		return BT_STATUS_PARM_INVALID;
-
-	return BT_STATUS_UNSUPPORTED;
-}
-
-static const void *get_profile_interface(const char *profile_id)
-{
-	ALOGD("%s: %s", __func__, profile_id);
-
-	if (!interface_ready())
-		return NULL;
-
-	if (!strcmp(profile_id, BT_PROFILE_SOCKETS_ID))
-		return bt_get_sock_interface();
-
-	return NULL;
-}
-
-static int dut_mode_configure(uint8_t enable)
-{
-	ALOGD(__func__);
-
-	if (!interface_ready())
-		return BT_STATUS_NOT_READY;
-
-	return BT_STATUS_UNSUPPORTED;
-}
-
-static int dut_mode_send(uint16_t opcode, uint8_t *buf, uint8_t len)
-{
-	ALOGD(__func__);
-
-	if (!interface_ready())
-		return BT_STATUS_NOT_READY;
-
-	return BT_STATUS_UNSUPPORTED;
-}
-
-static const bt_interface_t bluetooth_if = {
-	.size = sizeof(bt_interface_t),
-	.init = init,
-	.enable = enable,
-	.disable = disable,
-	.cleanup = cleanup,
-	.get_adapter_properties = get_adapter_properties,
-	.get_adapter_property = get_adapter_property,
-	.set_adapter_property = set_adapter_property,
-	.get_remote_device_properties = get_remote_device_properties,
-	.get_remote_device_property = get_remote_device_property,
-	.set_remote_device_property = set_remote_device_property,
-	.get_remote_service_record = get_remote_service_record,
-	.get_remote_services = get_remote_services,
-	.start_discovery = start_discovery,
-	.cancel_discovery = cancel_discovery,
-	.create_bond = create_bond,
-	.remove_bond = remove_bond,
-	.cancel_bond = cancel_bond,
-	.pin_reply = pin_reply,
-	.ssp_reply = ssp_reply,
-	.get_profile_interface = get_profile_interface,
-	.dut_mode_configure = dut_mode_configure,
-	.dut_mode_send = dut_mode_send
-};
-
-static const bt_interface_t *get_bluetooth_interface(void)
-{
-	ALOGD(__func__);
-
-	return &bluetooth_if;
-}
-
-static int close_bluetooth(struct hw_device_t *device)
-{
-	ALOGD(__func__);
-
-	cleanup();
-
-	return 0;
-}
-
-static int open_bluetooth(const struct hw_module_t *module, char const *name,
-					struct hw_device_t **device)
-{
-	bluetooth_device_t *dev = malloc(sizeof(bluetooth_device_t));
-
-	ALOGD(__func__);
-
-	memset(dev, 0, sizeof(bluetooth_device_t));
-	dev->common.tag = HARDWARE_DEVICE_TAG;
-	dev->common.version = 0;
-	dev->common.module = (struct hw_module_t *) module;
-	dev->common.close = close_bluetooth;
-	dev->get_bluetooth_interface = get_bluetooth_interface;
-
-	*device = (struct hw_device_t *) dev;
-
-	return 0;
-}
-
-static struct hw_module_methods_t bluetooth_module_methods = {
-	.open = open_bluetooth,
-};
-
-struct hw_module_t HAL_MODULE_INFO_SYM = {
-	.tag = HARDWARE_MODULE_TAG,
-	.version_major = 1,
-	.version_minor = 0,
-	.id = BT_HARDWARE_MODULE_ID,
-	.name = "BlueZ Bluetooth stack",
-	.author = "Intel Corporation",
-	.methods = &bluetooth_module_methods
-};
-- 
1.7.10.4


^ permalink raw reply related

* [PATCHv5 3/7] android: Use kernel style to initialize struct fields
From: Andrei Emeltchenko @ 2013-10-17  8:26 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1381998406-16662-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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

---
 android/hal_bluetooth.c |   46 +++++++++++++++++++++++-----------------------
 1 file changed, 23 insertions(+), 23 deletions(-)

diff --git a/android/hal_bluetooth.c b/android/hal_bluetooth.c
index 9bb9dcf..89b8ebb 100644
--- a/android/hal_bluetooth.c
+++ b/android/hal_bluetooth.c
@@ -309,29 +309,29 @@ static int dut_mode_send(uint16_t opcode, uint8_t *buf, uint8_t len)
 }
 
 static const bt_interface_t bluetooth_if = {
-	sizeof(bt_interface_t),
-	init,
-	enable,
-	disable,
-	cleanup,
-	get_adapter_properties,
-	get_adapter_property,
-	set_adapter_property,
-	get_remote_device_properties,
-	get_remote_device_property,
-	set_remote_device_property,
-	get_remote_service_record,
-	get_remote_services,
-	start_discovery,
-	cancel_discovery,
-	create_bond,
-	remove_bond,
-	cancel_bond,
-	pin_reply,
-	ssp_reply,
-	get_profile_interface,
-	dut_mode_configure,
-	dut_mode_send
+	.size = sizeof(bt_interface_t),
+	.init = init,
+	.enable = enable,
+	.disable = disable,
+	.cleanup = cleanup,
+	.get_adapter_properties = get_adapter_properties,
+	.get_adapter_property = get_adapter_property,
+	.set_adapter_property = set_adapter_property,
+	.get_remote_device_properties = get_remote_device_properties,
+	.get_remote_device_property = get_remote_device_property,
+	.set_remote_device_property = set_remote_device_property,
+	.get_remote_service_record = get_remote_service_record,
+	.get_remote_services = get_remote_services,
+	.start_discovery = start_discovery,
+	.cancel_discovery = cancel_discovery,
+	.create_bond = create_bond,
+	.remove_bond = remove_bond,
+	.cancel_bond = cancel_bond,
+	.pin_reply = pin_reply,
+	.ssp_reply = ssp_reply,
+	.get_profile_interface = get_profile_interface,
+	.dut_mode_configure = dut_mode_configure,
+	.dut_mode_send = dut_mode_send
 };
 
 static const bt_interface_t *get_bluetooth_interface(void)
-- 
1.7.10.4


^ permalink raw reply related

* [PATCHv5 2/7] android: Implement read_info_complete callback
From: Andrei Emeltchenko @ 2013-10-17  8:26 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1381998406-16662-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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

Handle read info complete callback from mgmt interface.
---
 Makefile.android   |    3 +-
 android/Android.mk |    1 +
 android/adapter.c  |  108 +++++++++++++++++++++++++++++++++++++++++++++++-----
 android/main.c     |   19 +++++----
 4 files changed, 111 insertions(+), 20 deletions(-)

diff --git a/Makefile.android b/Makefile.android
index 4d7da39..11eadc2 100644
--- a/Makefile.android
+++ b/Makefile.android
@@ -7,7 +7,8 @@ android_bluetoothd_SOURCES =	android/main.c \
 				src/sdpd-database.c src/sdpd-server.c \
 				src/sdpd-service.c src/sdpd-request.c \
 				src/shared/util.h src/shared/util.c \
-				src/shared/mgmt.h src/shared/mgmt.c
+				src/shared/mgmt.h src/shared/mgmt.c \
+				android/adapter.h android/adapter.c
 
 android_bluetoothd_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
 endif
diff --git a/android/Android.mk b/android/Android.mk
index d6bd5b8..22f8b92 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -15,6 +15,7 @@ include $(CLEAR_VARS)
 LOCAL_SRC_FILES := \
 	main.c \
 	log.c \
+	adapter.c \
 	../src/shared/mgmt.c \
 	../src/shared/util.c \
 	../src/sdpd-database.c \
diff --git a/android/adapter.c b/android/adapter.c
index 9763530..b384c5d 100644
--- a/android/adapter.c
+++ b/android/adapter.c
@@ -21,24 +21,24 @@
  *
  */
 
+#include "lib/bluetooth.h"
 #include "src/shared/mgmt.h"
+#include "lib/mgmt.h"
 #include "log.h"
 #include "adapter.h"
 
 struct bt_adapter {
 	struct mgmt *mgmt;
-};
+	bdaddr_t bdaddr;
+	uint32_t dev_class;
 
-struct bt_adapter *bt_adapter_new(uint16_t index, struct mgmt *mgmt_if)
-{
-	struct bt_adapter *adapter;
+	char *name;
 
-	adapter = g_new0(struct bt_adapter, 1);
-
-	adapter->mgmt = mgmt_ref(mgmt_if);
+	uint32_t supported_settings;
+	uint32_t current_settings;
+};
 
-	return adapter;
-}
+extern struct bt_adapter *default_adapter;
 
 void bt_adapter_start(struct bt_adapter *adapter)
 {
@@ -52,3 +52,93 @@ void bt_adapter_stop(struct bt_adapter *adapter)
 {
 	DBG("");
 }
+
+static void load_link_keys_complete(uint8_t status, uint16_t length,
+					const void *param, void *user_data)
+{
+	DBG("status %u", status);
+}
+
+static void load_link_keys(struct bt_adapter *adapter, GSList *keys)
+{
+	struct mgmt_cp_load_link_keys *cp;
+	size_t key_len = g_slist_length(keys);
+	struct mgmt_link_key_info *key;
+	size_t len;
+
+	DBG("");
+
+	len = sizeof(*cp) + key_len * sizeof(*key);
+	cp = g_malloc0(len);
+
+	cp->debug_keys = 0;
+	cp->key_count = htobs(key_len);
+
+	mgmt_send(adapter->mgmt, MGMT_OP_LOAD_LINK_KEYS, 0, len,
+				cp, load_link_keys_complete, adapter, NULL);
+
+	free(cp);
+}
+
+static void read_info_complete(uint8_t status, uint16_t length, const void *param,
+							void *user_data)
+{
+	struct bt_adapter *adapter = user_data;
+	const struct mgmt_rp_read_info *rp = param;
+
+	DBG("");
+
+	if (status) {
+		error("Failed to read info for index %u: %s (0x%02x)",
+			0, mgmt_errstr(status), status);
+		goto failed;
+	}
+
+	if (length < sizeof(*rp)) {
+		error("Too small read info complete response");
+		goto failed;
+	}
+
+	if (!bacmp(&rp->bdaddr, BDADDR_ANY)) {
+		error("No Bluetooth address");
+		goto failed;
+	}
+
+	/* Store adapter information */
+	bacpy(&adapter->bdaddr, &rp->bdaddr);
+	adapter->dev_class = rp->dev_class[0] | (rp->dev_class[1] << 8) |
+						(rp->dev_class[2] << 16);
+	adapter->name = g_strdup((const char *) rp->name);
+
+	adapter->supported_settings = btohs(rp->supported_settings);
+	adapter->current_settings = btohs(rp->current_settings);
+
+	/* TODO: Register all event notification handlers */
+
+	if (adapter->current_settings & MGMT_SETTING_POWERED)
+		bt_adapter_start(adapter);
+
+	load_link_keys(adapter, NULL);
+
+	return;
+
+failed:
+	default_adapter = NULL;
+}
+
+struct bt_adapter *bt_adapter_new(uint16_t index, struct mgmt *mgmt_if)
+{
+	struct bt_adapter *adapter;
+
+	adapter = g_new0(struct bt_adapter, 1);
+
+	adapter->mgmt = mgmt_ref(mgmt_if);
+
+	if (mgmt_send(mgmt_if, MGMT_OP_READ_INFO, index, 0, NULL,
+				read_info_complete, adapter, NULL) > 0) {
+		mgmt_unref(mgmt_if);
+		return NULL;
+	}
+
+	return adapter;
+}
diff --git a/android/main.c b/android/main.c
index 2b2e4d8..cc09ecd 100644
--- a/android/main.c
+++ b/android/main.c
@@ -49,6 +49,8 @@
 #include "lib/mgmt.h"
 #include "src/shared/mgmt.h"
 
+#include "adapter.h"
+
 #define SHUTDOWN_GRACE_SECONDS 10
 
 static GMainLoop *event_loop;
@@ -57,6 +59,8 @@ static struct mgmt *mgmt_if = NULL;
 static uint8_t mgmt_version = 0;
 static uint8_t mgmt_revision = 0;
 
+struct bt_adapter *default_adapter = NULL;
+
 static gboolean quit_eventloop(gpointer user_data)
 {
 	g_main_loop_quit(event_loop);
@@ -84,22 +88,17 @@ static GOptionEntry options[] = {
 	{ NULL }
 };
 
-static void read_info_complete(uint8_t status, uint16_t length,
-					const void *param, void *user_data)
-{
-	/* TODO: Store Controller information */
-
-	/* TODO: Register all event notification handlers */
-}
-
 static void mgmt_index_added_event(uint16_t index, uint16_t length,
 					const void *param, void *user_data)
 {
 	DBG("index %u", index);
 
-	if (mgmt_send(mgmt_if, MGMT_OP_READ_INFO, index, 0, NULL,
-					read_info_complete, NULL, NULL) > 0)
+	if (default_adapter) {
+		DBG("skip event for index %u", index);
 		return;
+	}
+
+	default_adapter = bt_adapter_new(index, mgmt_if);
 
 	error("Failed to read adapter info for index %u", index);
 }
-- 
1.7.10.4


^ permalink raw reply related

* [PATCHv5 1/7] android: Add capabilities and set userid
From: Andrei Emeltchenko @ 2013-10-17  8:26 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1381998406-16662-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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

The patch set UID as standard Bluetooth user for Android (AID_BLUETOOTH).
For SDP server we need to bind to lower port, acquire this capability.
Other capabilities are required to access management interface.
---
 android/main.c |   58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 configure.ac   |    4 ++++
 2 files changed, 62 insertions(+)

diff --git a/android/main.c b/android/main.c
index 3a20148..2b2e4d8 100644
--- a/android/main.c
+++ b/android/main.c
@@ -32,6 +32,13 @@
 #include <stdlib.h>
 #include <stdbool.h>
 #include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#if defined(ANDROID)
+#include <sys/prctl.h>
+#include <private/android_filesystem_config.h>
+#endif
 
 #include <glib.h>
 
@@ -230,6 +237,54 @@ static void cleanup_mgmt_interface(void)
 	mgmt_if = NULL;
 }
 
+static bool set_capabilities(void)
+{
+#if defined(ANDROID)
+	struct __user_cap_header_struct header;
+	struct __user_cap_data_struct cap;
+	gid_t groups[] = {AID_NET_BT, AID_NET_BT_ADMIN, AID_NET_ADMIN};
+
+	DBG("pid %d uid %d gid %d", getpid(), getuid(), getgid());
+
+	header.version = _LINUX_CAPABILITY_VERSION;
+
+	prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
+
+	if (setgid(AID_BLUETOOTH) < 0)
+		warn("%s: setgid(): %s", __func__, strerror(errno));
+
+	if (setuid(AID_BLUETOOTH) < 0)
+		warn("%s: setuid(): %s", __func__, strerror(errno));
+
+	header.version = _LINUX_CAPABILITY_VERSION;
+	header.pid = 0;
+
+	cap.effective = cap.permitted =
+		CAP_TO_MASK(CAP_SETGID) |
+		CAP_TO_MASK(CAP_NET_RAW) |
+		CAP_TO_MASK(CAP_NET_ADMIN) |
+		CAP_TO_MASK(CAP_NET_BIND_SERVICE);
+	cap.inheritable = 0;
+
+	if (capset(&header, &cap) < 0) {
+		error("%s: capset(): %s", __func__, strerror(errno));
+		return false;
+	}
+
+	if (setgroups(sizeof(groups)/sizeof(groups[0]), groups) < 0)
+		warn("%s: setgroups: %s", __func__, strerror(errno));
+
+	if (capget(&header, &cap) < 0)
+		error("%s: capget(): %s", __func__, strerror(errno));
+	else
+		DBG("Caps: eff: 0x%x, perm: 0x%x, inh: 0x%x", cap.effective,
+					cap.permitted, cap.inheritable);
+
+	DBG("pid %d uid %d gid %d", getpid(), getuid(), getgid());
+#endif
+	return true;
+}
+
 int main(int argc, char *argv[])
 {
 	GOptionContext *context;
@@ -263,6 +318,9 @@ int main(int argc, char *argv[])
 	sigaction(SIGINT, &sa, NULL);
 	sigaction(SIGTERM, &sa, NULL);
 
+	if (!set_capabilities())
+		return EXIT_FAILURE;
+
 	if (!init_mgmt_interface())
 		return EXIT_FAILURE;
 
diff --git a/configure.ac b/configure.ac
index b4d3998..e3b5220 100644
--- a/configure.ac
+++ b/configure.ac
@@ -247,4 +247,8 @@ AC_ARG_ENABLE(android, AC_HELP_STRING([--enable-android],
 					[enable_android=${enableval}])
 AM_CONDITIONAL(ANDROID, test "${enable_android}" = "yes")
 
+if (test "${enable_android}" = "yes"); then
+	AC_CHECK_LIB(cap, capget, dummy=yes, AC_MSG_ERROR(libcap is required))
+fi
+
 AC_OUTPUT(Makefile src/bluetoothd.8 lib/bluez.pc)
-- 
1.7.10.4


^ permalink raw reply related

* [PATCHv5 0/7] Android BlueZ patches, second chunk
From: Andrei Emeltchenko @ 2013-10-17  8:26 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1381833423-862-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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

This is second chunk from my initial big patch set. Fixed style issues commented
by Marcel.

Changes:
	* v5: Rebased against upstream, hid and pan now uses explicit struct initialization,
	adapter-related functionality moved to adapter.c, fixed issues reported by Johan.
	* v4: Fixes several typos and missing style issues commented by Marcel earlier.
	* v3: Following upstream comments file names are changed from "_" to "-", added kernel style
	struct initialization, fixed bug checking status for mgmt commands, added 2 HALs skeletons.
	* v2: Corrected android_daemon -> enable_android autoconf stuff, better name for acquiring caps,
	renamed hal_msg.h to hal-msg.h due to Johan's comment. Added small test-sdp fix.

Note that due to Marcel comment this cannot be built unless you include my patch
for Android bionic library:
http://code.google.com/p/android-bluez/source/detail?r=77a07e7703b63e280d9880baad30b3375e7df079&repo=bionic#

Andrei Emeltchenko (7):
  android: Add capabilities and set userid
  android: Implement read_info_complete callback
  android: Use kernel style to initialize struct fields
  android: Rename hal_bluetooth.c to hal-bluetooth.c
  android: Rename hal_bt_sock.c to hal-bt-sock.c
  android: Add HID Host skeleton
  android: Add PAN skeleton

 Makefile.android        |    3 +-
 android/Android.mk      |    7 +-
 android/adapter.c       |  108 +++++++++++--
 android/hal-bluetooth.c |  392 +++++++++++++++++++++++++++++++++++++++++++++++
 android/hal-bt-sock.c   |   85 ++++++++++
 android/hal-hidhost.c   |  204 ++++++++++++++++++++++++
 android/hal-pan.c       |  120 +++++++++++++++
 android/hal.h           |    2 +
 android/hal_bluetooth.c |  384 ----------------------------------------------
 android/hal_bt_sock.c   |   85 ----------
 android/main.c          |   77 ++++++++--
 configure.ac            |    4 +
 12 files changed, 980 insertions(+), 491 deletions(-)
 create mode 100644 android/hal-bluetooth.c
 create mode 100644 android/hal-bt-sock.c
 create mode 100644 android/hal-hidhost.c
 create mode 100644 android/hal-pan.c
 delete mode 100644 android/hal_bluetooth.c
 delete mode 100644 android/hal_bt_sock.c

-- 
1.7.10.4


^ permalink raw reply

* Re: [PATCH 1/2] android: Make toool compile on Android 4.2.2
From: Jerzy Kasenberg @ 2013-10-17  8:16 UTC (permalink / raw)
  To: Andrei Emeltchenko, Jerzy Kasenberg, linux-bluetooth
In-Reply-To: <20131017081100.GN2861@aemeltch-MOBL1>

Hi Andrei,

No error, but since it's not defined code is never included in version above 17

-- 
Best regards
Jerzy Kasenberg

On 17 October 2013 10:11, Andrei Emeltchenko
<Andrei.Emeltchenko.news@gmail.com> wrote:
> Hi Jerzy,
>
> On Thu, Oct 17, 2013 at 10:06:52AM +0200, Jerzy Kasenberg wrote:
>> Hi Andrei,
>>
>> Shouldn't PLATFORM_SDK_VERSION be defined in Android.mk?
>
> No, it works as is for me. Do you have errors?
>
> Best regards
> Andrei Emeltchenko
>
>>
>> LOCAL_CFLAGS := -DPLATFORM_SDK_VERSION=$(PLATFORM_SDK_VERSION)
>>
>> --
>> Best regards
>> Jerzy Kasenberg
>>
>> On 17 October 2013 09:11, Andrei Emeltchenko
>> <Andrei.Emeltchenko.news@gmail.com> wrote:
>> > From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
>> >
>> > On our current target the tools cannot be compiled.
>> > ---
>> >  android/client/if-bt.c    |    4 ++++
>> >  android/client/if-main.h  |    3 +++
>> >  android/client/textconv.c |    2 ++
>> >  3 files changed, 9 insertions(+)
>> >
>> > diff --git a/android/client/if-bt.c b/android/client/if-bt.c
>> > index a0a4bd9..7b4e71e 100644
>> > --- a/android/client/if-bt.c
>> > +++ b/android/client/if-bt.c
>> > @@ -277,7 +277,9 @@ static bt_callbacks_t bt_callbacks = {
>> >         .acl_state_changed_cb = acl_state_changed_cb,
>> >         .thread_evt_cb = thread_evt_cb,
>> >         .dut_mode_recv_cb = dut_mode_recv_cb,
>> > +#if PLATFORM_SDK_VERSION > 17
>> >         .le_test_mode_cb = le_test_mode_cb
>> > +#endif
>> >  };
>> >
>> >  static void init_p(int argc, const char **argv)
>> > @@ -577,8 +579,10 @@ static void get_profile_interface_p(int argc, const char **argv)
>> >                 pif = &dummy; /* TODO: chenge when if_hh is there */
>> >         else if (strcmp(BT_PROFILE_PAN_ID, id) == 0)
>> >                 pif = &dummy; /* TODO: chenge when if_pan is there */
>> > +#if PLATFORM_SDK_VERSION > 17
>> >         else if (strcmp(BT_PROFILE_AV_RC_ID, id) == 0)
>> >                 pif = &dummy; /* TODO: chenge when if_rc is there */
>> > +#endif
>> >         else
>> >                 haltest_error("%s is not correct for get_profile_interface\n",
>> >                      id);
>> > diff --git a/android/client/if-main.h b/android/client/if-main.h
>> > index 9cac7ef..1cebb72 100644
>> > --- a/android/client/if-main.h
>> > +++ b/android/client/if-main.h
>> > @@ -35,7 +35,10 @@
>> >  #include <hardware/bt_sock.h>
>> >  #include <hardware/bt_hf.h>
>> >  #include <hardware/bt_hl.h>
>> > +
>> > +#if PLATFORM_SDK_VERSION > 17
>> >  #include <hardware/bt_rc.h>
>> > +#endif
>> >
>> >  #include "textconv.h"
>> >
>> > diff --git a/android/client/textconv.c b/android/client/textconv.c
>> > index eebad70..f38e368 100644
>> > --- a/android/client/textconv.c
>> > +++ b/android/client/textconv.c
>> > @@ -94,7 +94,9 @@ INTMAP(bt_property_type_t, -1, "(unknown)")
>> >         DELEMENT(BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT),
>> >         DELEMENT(BT_PROPERTY_REMOTE_FRIENDLY_NAME),
>> >         DELEMENT(BT_PROPERTY_REMOTE_RSSI),
>> > +#if PLATFORM_SDK_VERSION > 17
>> >         DELEMENT(BT_PROPERTY_REMOTE_VERSION_INFO),
>> > +#endif
>> >         DELEMENT(BT_PROPERTY_REMOTE_DEVICE_TIMESTAMP),
>> >  ENDMAP
>> >
>> > --
>> > 1.7.10.4
>> >
>> > --
>> > 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

* Re: [PATCH 1/2] android: Make toool compile on Android 4.2.2
From: Andrei Emeltchenko @ 2013-10-17  8:11 UTC (permalink / raw)
  To: Jerzy Kasenberg; +Cc: linux-bluetooth
In-Reply-To: <CAHCYCoyLsS5oj5Q+4Z_vmvPfjri3Jkvc9HrQzza2=bCn8UG+sg@mail.gmail.com>

Hi Jerzy,

On Thu, Oct 17, 2013 at 10:06:52AM +0200, Jerzy Kasenberg wrote:
> Hi Andrei,
> 
> Shouldn't PLATFORM_SDK_VERSION be defined in Android.mk?

No, it works as is for me. Do you have errors?

Best regards 
Andrei Emeltchenko 

> 
> LOCAL_CFLAGS := -DPLATFORM_SDK_VERSION=$(PLATFORM_SDK_VERSION)
> 
> -- 
> Best regards
> Jerzy Kasenberg
> 
> On 17 October 2013 09:11, Andrei Emeltchenko
> <Andrei.Emeltchenko.news@gmail.com> wrote:
> > From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> >
> > On our current target the tools cannot be compiled.
> > ---
> >  android/client/if-bt.c    |    4 ++++
> >  android/client/if-main.h  |    3 +++
> >  android/client/textconv.c |    2 ++
> >  3 files changed, 9 insertions(+)
> >
> > diff --git a/android/client/if-bt.c b/android/client/if-bt.c
> > index a0a4bd9..7b4e71e 100644
> > --- a/android/client/if-bt.c
> > +++ b/android/client/if-bt.c
> > @@ -277,7 +277,9 @@ static bt_callbacks_t bt_callbacks = {
> >         .acl_state_changed_cb = acl_state_changed_cb,
> >         .thread_evt_cb = thread_evt_cb,
> >         .dut_mode_recv_cb = dut_mode_recv_cb,
> > +#if PLATFORM_SDK_VERSION > 17
> >         .le_test_mode_cb = le_test_mode_cb
> > +#endif
> >  };
> >
> >  static void init_p(int argc, const char **argv)
> > @@ -577,8 +579,10 @@ static void get_profile_interface_p(int argc, const char **argv)
> >                 pif = &dummy; /* TODO: chenge when if_hh is there */
> >         else if (strcmp(BT_PROFILE_PAN_ID, id) == 0)
> >                 pif = &dummy; /* TODO: chenge when if_pan is there */
> > +#if PLATFORM_SDK_VERSION > 17
> >         else if (strcmp(BT_PROFILE_AV_RC_ID, id) == 0)
> >                 pif = &dummy; /* TODO: chenge when if_rc is there */
> > +#endif
> >         else
> >                 haltest_error("%s is not correct for get_profile_interface\n",
> >                      id);
> > diff --git a/android/client/if-main.h b/android/client/if-main.h
> > index 9cac7ef..1cebb72 100644
> > --- a/android/client/if-main.h
> > +++ b/android/client/if-main.h
> > @@ -35,7 +35,10 @@
> >  #include <hardware/bt_sock.h>
> >  #include <hardware/bt_hf.h>
> >  #include <hardware/bt_hl.h>
> > +
> > +#if PLATFORM_SDK_VERSION > 17
> >  #include <hardware/bt_rc.h>
> > +#endif
> >
> >  #include "textconv.h"
> >
> > diff --git a/android/client/textconv.c b/android/client/textconv.c
> > index eebad70..f38e368 100644
> > --- a/android/client/textconv.c
> > +++ b/android/client/textconv.c
> > @@ -94,7 +94,9 @@ INTMAP(bt_property_type_t, -1, "(unknown)")
> >         DELEMENT(BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT),
> >         DELEMENT(BT_PROPERTY_REMOTE_FRIENDLY_NAME),
> >         DELEMENT(BT_PROPERTY_REMOTE_RSSI),
> > +#if PLATFORM_SDK_VERSION > 17
> >         DELEMENT(BT_PROPERTY_REMOTE_VERSION_INFO),
> > +#endif
> >         DELEMENT(BT_PROPERTY_REMOTE_DEVICE_TIMESTAMP),
> >  ENDMAP
> >
> > --
> > 1.7.10.4
> >
> > --
> > 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

* Re: [PATCH 1/2] android: Make toool compile on Android 4.2.2
From: Jerzy Kasenberg @ 2013-10-17  8:06 UTC (permalink / raw)
  To: Andrei Emeltchenko; +Cc: linux-bluetooth
In-Reply-To: <1381993898-30445-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

Hi Andrei,

Shouldn't PLATFORM_SDK_VERSION be defined in Android.mk?

LOCAL_CFLAGS := -DPLATFORM_SDK_VERSION=$(PLATFORM_SDK_VERSION)

-- 
Best regards
Jerzy Kasenberg

On 17 October 2013 09:11, Andrei Emeltchenko
<Andrei.Emeltchenko.news@gmail.com> wrote:
> From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
>
> On our current target the tools cannot be compiled.
> ---
>  android/client/if-bt.c    |    4 ++++
>  android/client/if-main.h  |    3 +++
>  android/client/textconv.c |    2 ++
>  3 files changed, 9 insertions(+)
>
> diff --git a/android/client/if-bt.c b/android/client/if-bt.c
> index a0a4bd9..7b4e71e 100644
> --- a/android/client/if-bt.c
> +++ b/android/client/if-bt.c
> @@ -277,7 +277,9 @@ static bt_callbacks_t bt_callbacks = {
>         .acl_state_changed_cb = acl_state_changed_cb,
>         .thread_evt_cb = thread_evt_cb,
>         .dut_mode_recv_cb = dut_mode_recv_cb,
> +#if PLATFORM_SDK_VERSION > 17
>         .le_test_mode_cb = le_test_mode_cb
> +#endif
>  };
>
>  static void init_p(int argc, const char **argv)
> @@ -577,8 +579,10 @@ static void get_profile_interface_p(int argc, const char **argv)
>                 pif = &dummy; /* TODO: chenge when if_hh is there */
>         else if (strcmp(BT_PROFILE_PAN_ID, id) == 0)
>                 pif = &dummy; /* TODO: chenge when if_pan is there */
> +#if PLATFORM_SDK_VERSION > 17
>         else if (strcmp(BT_PROFILE_AV_RC_ID, id) == 0)
>                 pif = &dummy; /* TODO: chenge when if_rc is there */
> +#endif
>         else
>                 haltest_error("%s is not correct for get_profile_interface\n",
>                      id);
> diff --git a/android/client/if-main.h b/android/client/if-main.h
> index 9cac7ef..1cebb72 100644
> --- a/android/client/if-main.h
> +++ b/android/client/if-main.h
> @@ -35,7 +35,10 @@
>  #include <hardware/bt_sock.h>
>  #include <hardware/bt_hf.h>
>  #include <hardware/bt_hl.h>
> +
> +#if PLATFORM_SDK_VERSION > 17
>  #include <hardware/bt_rc.h>
> +#endif
>
>  #include "textconv.h"
>
> diff --git a/android/client/textconv.c b/android/client/textconv.c
> index eebad70..f38e368 100644
> --- a/android/client/textconv.c
> +++ b/android/client/textconv.c
> @@ -94,7 +94,9 @@ INTMAP(bt_property_type_t, -1, "(unknown)")
>         DELEMENT(BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT),
>         DELEMENT(BT_PROPERTY_REMOTE_FRIENDLY_NAME),
>         DELEMENT(BT_PROPERTY_REMOTE_RSSI),
> +#if PLATFORM_SDK_VERSION > 17
>         DELEMENT(BT_PROPERTY_REMOTE_VERSION_INFO),
> +#endif
>         DELEMENT(BT_PROPERTY_REMOTE_DEVICE_TIMESTAMP),
>  ENDMAP
>
> --
> 1.7.10.4
>
> --
> 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

* [PATCH 2/2] android: trivial typo fix
From: Andrei Emeltchenko @ 2013-10-17  7:11 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1381993898-30445-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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

---
 android/client/if-bt.c |   14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/android/client/if-bt.c b/android/client/if-bt.c
index 7b4e71e..6aadeef 100644
--- a/android/client/if-bt.c
+++ b/android/client/if-bt.c
@@ -568,20 +568,20 @@ static void get_profile_interface_p(int argc, const char **argv)
 	RETURN_IF_NULL(if_bluetooth);
 
 	if (strcmp(BT_PROFILE_HANDSFREE_ID, id) == 0)
-		pif = &dummy; /* TODO: chenge when if_hf is there */
+		pif = &dummy; /* TODO: change when if_hf is there */
 	else if (strcmp(BT_PROFILE_ADVANCED_AUDIO_ID, id) == 0)
-		pif = &dummy; /* TODO: chenge when if_av is there */
+		pif = &dummy; /* TODO: change when if_av is there */
 	else if (strcmp(BT_PROFILE_HEALTH_ID, id) == 0)
-		pif = &dummy; /* TODO: chenge when if_hl is there */
+		pif = &dummy; /* TODO: change when if_hl is there */
 	else if (strcmp(BT_PROFILE_SOCKETS_ID, id) == 0)
-		pif = &dummy; /* TODO: chenge when if_sock is there */
+		pif = &dummy; /* TODO: change when if_sock is there */
 	else if (strcmp(BT_PROFILE_HIDHOST_ID, id) == 0)
-		pif = &dummy; /* TODO: chenge when if_hh is there */
+		pif = &dummy; /* TODO: change when if_hh is there */
 	else if (strcmp(BT_PROFILE_PAN_ID, id) == 0)
-		pif = &dummy; /* TODO: chenge when if_pan is there */
+		pif = &dummy; /* TODO: change when if_pan is there */
 #if PLATFORM_SDK_VERSION > 17
 	else if (strcmp(BT_PROFILE_AV_RC_ID, id) == 0)
-		pif = &dummy; /* TODO: chenge when if_rc is there */
+		pif = &dummy; /* TODO: change when if_rc is there */
 #endif
 	else
 		haltest_error("%s is not correct for get_profile_interface\n",
-- 
1.7.10.4


^ permalink raw reply related

* [PATCH 1/2] android: Make toool compile on Android 4.2.2
From: Andrei Emeltchenko @ 2013-10-17  7:11 UTC (permalink / raw)
  To: linux-bluetooth

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

On our current target the tools cannot be compiled.
---
 android/client/if-bt.c    |    4 ++++
 android/client/if-main.h  |    3 +++
 android/client/textconv.c |    2 ++
 3 files changed, 9 insertions(+)

diff --git a/android/client/if-bt.c b/android/client/if-bt.c
index a0a4bd9..7b4e71e 100644
--- a/android/client/if-bt.c
+++ b/android/client/if-bt.c
@@ -277,7 +277,9 @@ static bt_callbacks_t bt_callbacks = {
 	.acl_state_changed_cb = acl_state_changed_cb,
 	.thread_evt_cb = thread_evt_cb,
 	.dut_mode_recv_cb = dut_mode_recv_cb,
+#if PLATFORM_SDK_VERSION > 17
 	.le_test_mode_cb = le_test_mode_cb
+#endif
 };
 
 static void init_p(int argc, const char **argv)
@@ -577,8 +579,10 @@ static void get_profile_interface_p(int argc, const char **argv)
 		pif = &dummy; /* TODO: chenge when if_hh is there */
 	else if (strcmp(BT_PROFILE_PAN_ID, id) == 0)
 		pif = &dummy; /* TODO: chenge when if_pan is there */
+#if PLATFORM_SDK_VERSION > 17
 	else if (strcmp(BT_PROFILE_AV_RC_ID, id) == 0)
 		pif = &dummy; /* TODO: chenge when if_rc is there */
+#endif
 	else
 		haltest_error("%s is not correct for get_profile_interface\n",
 		     id);
diff --git a/android/client/if-main.h b/android/client/if-main.h
index 9cac7ef..1cebb72 100644
--- a/android/client/if-main.h
+++ b/android/client/if-main.h
@@ -35,7 +35,10 @@
 #include <hardware/bt_sock.h>
 #include <hardware/bt_hf.h>
 #include <hardware/bt_hl.h>
+
+#if PLATFORM_SDK_VERSION > 17
 #include <hardware/bt_rc.h>
+#endif
 
 #include "textconv.h"
 
diff --git a/android/client/textconv.c b/android/client/textconv.c
index eebad70..f38e368 100644
--- a/android/client/textconv.c
+++ b/android/client/textconv.c
@@ -94,7 +94,9 @@ INTMAP(bt_property_type_t, -1, "(unknown)")
 	DELEMENT(BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT),
 	DELEMENT(BT_PROPERTY_REMOTE_FRIENDLY_NAME),
 	DELEMENT(BT_PROPERTY_REMOTE_RSSI),
+#if PLATFORM_SDK_VERSION > 17
 	DELEMENT(BT_PROPERTY_REMOTE_VERSION_INFO),
+#endif
 	DELEMENT(BT_PROPERTY_REMOTE_DEVICE_TIMESTAMP),
 ENDMAP
 
-- 
1.7.10.4


^ permalink raw reply related

* [RFC 15/15] Bluetooth: Auto connection and power off/on
From: Andre Guedes @ 2013-10-16 23:18 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1381965485-9159-1-git-send-email-andre.guedes@openbossa.org>

If hdev is closed (e.g. Mgmt power off command, RFKILL or controller is
reset), the established connections are dropped and no Disconnection
Complete Event is sent to host. This way, the background scan is not
triggered when devices configured with BT_AUTO_CONN_ALWAYS option
disconnect. To fix this issue, before dropping the LE connections, we
trigger the background scan for each connected device that requires
BT_AUTO_CONN_ALWAYS auto connection.

Moreover, once the adapter is powered on, we should start the background
scan if we have triggers registered. This way, we keep the background
scan running after a power off and power on sequence.

Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
 net/bluetooth/hci_conn.c | 35 +++++++++++++++++++++++++++++++++++
 net/bluetooth/hci_core.c |  2 ++
 2 files changed, 37 insertions(+)

diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 5caf13b..66823eb 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -954,6 +954,31 @@ timer:
 				   msecs_to_jiffies(hdev->idle_timeout));
 }
 
+static void le_conn_drop_fixup(struct hci_conn *conn)
+{
+	struct hci_dev *hdev = conn->hdev;
+	struct hci_conn_param *param;
+	int err;
+
+	param = hci_find_conn_param(hdev, &conn->dst, conn->dst_type);
+	if (!param)
+		return;
+
+	if (param->auto_connect != BT_AUTO_CONN_ALWAYS)
+		goto done;
+
+	err = hci_trigger_background_scan(hdev);
+	if (err) {
+		BT_ERR("Failed to trigger background scanning: %d", err);
+		goto done;
+	}
+
+	param->bg_scan_triggered = true;
+
+done:
+	hci_conn_param_put(param);
+}
+
 /* Drop all connection on the device */
 void hci_conn_hash_flush(struct hci_dev *hdev)
 {
@@ -963,6 +988,16 @@ void hci_conn_hash_flush(struct hci_dev *hdev)
 	BT_DBG("hdev %s", hdev->name);
 
 	list_for_each_entry_safe(c, n, &h->list, list) {
+		/* If this is a LE connection in connected state we should do
+		 * some fixup before dropping this connection. Since no
+		 * Disconnection Complete Event will be sent to the host, we
+		 * have to trigger the background scan in case this is a
+		 * BT_AUTO_CONN_ALWAYS device. This is handled by the le_conn_
+		 * drop_fixup() helper.
+		 */
+		if (c->type == LE_LINK && c->state == BT_CONNECTED)
+			le_conn_drop_fixup(c);
+
 		c->state = BT_CLOSED;
 
 		hci_proto_disconn_cfm(c, HCI_ERROR_LOCAL_HOST_TERM);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index ace77e3..fe18801 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1748,6 +1748,8 @@ static void hci_power_on(struct work_struct *work)
 
 	if (test_and_clear_bit(HCI_SETUP, &hdev->dev_flags))
 		mgmt_index_added(hdev);
+
+	hci_check_background_scan(hdev);
 }
 
 static void hci_power_off(struct work_struct *work)
-- 
1.8.4


^ permalink raw reply related

* [RFC 14/15] Bluetooth: Fix hci_create_le_conn()
From: Andre Guedes @ 2013-10-16 23:18 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1381965485-9159-1-git-send-email-andre.guedes@openbossa.org>

When a LE device we want automatically connect to is found during the
device discovery procedure, we create the connection. Since some LE
controllers don't support scanning and initiating state combination,
the scanning will be disabled therefore we should set the discovery
state to DISCOVERY_STOPPED

Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
 net/bluetooth/hci_conn.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 6ae42c2..5caf13b 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -576,6 +576,11 @@ static int hci_create_le_conn(struct hci_conn *conn)
 		enable_cp.enable = LE_SCAN_DISABLE;
 		hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
 			    &enable_cp);
+
+		if (hdev->discovery.state == DISCOVERY_FINDING) {
+			cancel_delayed_work(&hdev->le_scan_disable);
+			hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
+		}
 	}
 
 	memset(&cp, 0, sizeof(cp));
-- 
1.8.4


^ permalink raw reply related

* [RFC 13/15] Bluetooth: Fix background trigger/untrigger functions
From: Andre Guedes @ 2013-10-16 23:18 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1381965485-9159-1-git-send-email-andre.guedes@openbossa.org>

This patch fixes to hci_trigger_background_scan() and hci_untrigger_
background_scan() so they can be called concurrently with the device
discovery procedure.

In hci_trigger_background_scan(), if it is the first trigger, we are
supposed to start the background scanning. However, if device discovery
is running, we should not send any HCI command. The background scanning
will be started once the discovery procedure is finished.

In hci_untrigger_background_scan(), if it is the last trigger, we are
supposed to stop the background scanning. However, if discovery is
running, it means the background is stopped so we don't need to send
any HCI command.

Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
 net/bluetooth/hci_core.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index ed5ce58..ace77e3 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -3929,6 +3929,12 @@ int hci_trigger_background_scan(struct hci_dev *hdev)
 	if (atomic_read(&hdev->background_scan_cnt) > 0)
 		goto done;
 
+	/* If discovery is running, we should not start the background
+	 * scanning. It will be started once the discovery procedure finishes.
+	 */
+	if (hdev->discovery.state == DISCOVERY_FINDING)
+		goto done;
+
 	err = start_background_scan(hdev);
 	if (err)
 		return err;
@@ -3958,6 +3964,10 @@ int hci_untrigger_background_scan(struct hci_dev *hdev)
 	if (!test_bit(HCI_LE_SCAN, &hdev->dev_flags))
 		goto done;
 
+	/* If device discovery is running, don't stop scanning. */
+	if (hdev->discovery.state == DISCOVERY_FINDING)
+		goto done;
+
 	hci_req_init(&req, hdev);
 
 	memset(&cp, 0, sizeof(cp));
-- 
1.8.4


^ permalink raw reply related

* [RFC 12/15] Bluetooth: Temporarily stop background scanning on discovery
From: Andre Guedes @ 2013-10-16 23:18 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1381965485-9159-1-git-send-email-andre.guedes@openbossa.org>

If the user send a mgmt start discovery command while the background
scanning is running, we should temporarily stop it. Once the discovery
finishes, we start the background scanning again.

Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
 net/bluetooth/hci_core.c |  5 +++++
 net/bluetooth/mgmt.c     | 12 ++++++++----
 2 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index e1e8f8a..ed5ce58 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -877,6 +877,11 @@ void hci_discovery_set_state(struct hci_dev *hdev, int state)
 
 	switch (state) {
 	case DISCOVERY_STOPPED:
+		/* Check the background scanning since it may have been
+		 * temporarily stopped by the start discovery command.
+		 */
+		hci_check_background_scan(hdev);
+
 		if (hdev->discovery.state != DISCOVERY_STARTING)
 			mgmt_discovering(hdev, 0);
 		break;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index c68aea5..f6f1524 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -3228,11 +3228,15 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
 			goto failed;
 		}
 
+		/* If controller is scanning, it means the background scanning
+		 * is running. Thus, we should temporarily stop it in order to
+		 * set the discovery scanning parameters.
+		 */
 		if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) {
-			err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
-					 MGMT_STATUS_BUSY);
-			mgmt_pending_remove(cmd);
-			goto failed;
+			memset(&enable_cp, 0, sizeof(enable_cp));
+			enable_cp.enable = LE_SCAN_DISABLE;
+			hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE,
+				    sizeof(enable_cp), &enable_cp);
 		}
 
 		memset(&param_cp, 0, sizeof(param_cp));
-- 
1.8.4


^ permalink raw reply related

* [RFC 11/15] Bluetooth: Temporarily stop background scanning on connection
From: Andre Guedes @ 2013-10-16 23:18 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1381965485-9159-1-git-send-email-andre.guedes@openbossa.org>

Some LE controllers don't support scanning and initiating a connection
at the same time. So, for those controllers, we should temporarily
stop the background scanning and start it again once the connection
attempt is finished (successfully or not).

So this patch introduces the hci_check_background_scan() which checks
if the background scanning should be started.

Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
 include/net/bluetooth/hci_core.h |  1 +
 net/bluetooth/hci_conn.c         | 25 +++++++++++++++++++++++++
 net/bluetooth/hci_core.c         | 18 ++++++++++++++++++
 net/bluetooth/hci_event.c        |  6 ++++++
 4 files changed, 50 insertions(+)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index db39eca..017decc 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -1201,5 +1201,6 @@ void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8],
 
 int hci_trigger_background_scan(struct hci_dev *hdev);
 int hci_untrigger_background_scan(struct hci_dev *hdev);
+void hci_check_background_scan(struct hci_dev *hdev);
 
 #endif /* __HCI_CORE_H */
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index d64000e..6ae42c2 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -541,6 +541,18 @@ static void create_le_conn_complete(struct hci_dev *hdev, u8 status)
 
 done:
 	hci_dev_unlock(hdev);
+
+	/* Check the background scanning since it may have been temporarily
+	 * stopped if the controller doesn't support scanning and initiate
+	 * state combination.
+	 */
+	hci_check_background_scan(hdev);
+}
+
+/* Check if controller supports scanning and initiating states combination */
+static bool is_state_combination_supported(struct hci_dev *hdev)
+{
+        return (hdev->le_states[2] & BIT(6)) ? true : false;
 }
 
 static int hci_create_le_conn(struct hci_conn *conn)
@@ -553,6 +565,19 @@ static int hci_create_le_conn(struct hci_conn *conn)
 
 	hci_req_init(&req, hdev);
 
+	/* If controller is scanning but it doesn't support initiating and
+	 * scanning states combination, we stop scanning.
+	 */
+	if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
+	    !is_state_combination_supported(hdev)) {
+		struct hci_cp_le_set_scan_enable enable_cp;
+
+		memset(&enable_cp, 0, sizeof(enable_cp));
+		enable_cp.enable = LE_SCAN_DISABLE;
+		hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
+			    &enable_cp);
+	}
+
 	memset(&cp, 0, sizeof(cp));
 	cp.scan_interval = cpu_to_le16(hdev->le_scan_interval);
 	cp.scan_window = cpu_to_le16(hdev->le_scan_window);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 68f3c0a..e1e8f8a 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -3967,3 +3967,21 @@ done:
 	atomic_dec(&hdev->background_scan_cnt);
 	return 0;
 }
+
+/* This function checks if there is background scan triggers and starts
+ * scanning.
+ */
+void hci_check_background_scan(struct hci_dev *hdev)
+{
+	int err;
+
+	if (atomic_read(&hdev->background_scan_cnt) == 0)
+		return;
+
+	if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
+		return;
+
+	err = start_background_scan(hdev);
+	if (err)
+		BT_ERR("Failed to start background scanning: err %d", err);
+}
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 570f27d..a8c7b47 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -3592,6 +3592,12 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 
 unlock:
 	hci_dev_unlock(hdev);
+
+	/* Check the background scanning since it may have been temporarily
+	 * stopped if the controller doesn't support scanning and initiate
+	 * state combination.
+	 */
+	hci_check_background_scan(hdev);
 }
 
 static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
-- 
1.8.4


^ permalink raw reply related

* [RFC 10/15] Bluetooth: Create start_background_scan helper
From: Andre Guedes @ 2013-10-16 23:18 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1381965485-9159-1-git-send-email-andre.guedes@openbossa.org>

This patch creates the start_background_scan() function so it can
be reused in the next patch.

Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
 net/bluetooth/hci_core.c | 28 +++++++++++++++++-----------
 1 file changed, 17 insertions(+), 11 deletions(-)

diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index f232965..68f3c0a 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -3888,20 +3888,11 @@ static void start_background_scan_complete(struct hci_dev *hdev, u8 status)
 		       "status 0x%2.2x", status);
 }
 
-int hci_trigger_background_scan(struct hci_dev *hdev)
+static int start_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;
-	int err;
-
-	BT_DBG("%s", hdev->name);
-
-	/* If we already have triggers, there is no need to send HCI command
-	 * to start the background scanning.
-	 */
-	if (atomic_read(&hdev->background_scan_cnt) > 0)
-		goto done;
 
 	hci_req_init(&req, hdev);
 
@@ -3918,7 +3909,22 @@ int hci_trigger_background_scan(struct hci_dev *hdev)
 	hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
 		    &enable_cp);
 
-	err = hci_req_run(&req, start_background_scan_complete);
+	return hci_req_run(&req, start_background_scan_complete);
+}
+
+int hci_trigger_background_scan(struct hci_dev *hdev)
+{
+	int err;
+
+	BT_DBG("%s", hdev->name);
+
+	/* If we already have triggers, there is no need to send HCI command
+	 * to start the background scanning.
+	 */
+	if (atomic_read(&hdev->background_scan_cnt) > 0)
+		goto done;
+
+	err = start_background_scan(hdev);
 	if (err)
 		return err;
 
-- 
1.8.4


^ permalink raw reply related

* [RFC 09/15] Bluetooth: Add support for BT_AUTO_CONN_LINK_LOSS option
From: Andre Guedes @ 2013-10-16 23:17 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1381965485-9159-1-git-send-email-andre.guedes@openbossa.org>

This patch adds support for the BT_AUTO_CONN_LINK_LOSS option which
configures the kernel to autonomously reconnect to a certainn device
in case the connection is terminated by link loss (which maps to HCI
Connection Timeout error.

This feature is required by the majority of LE profiles such as
Proximity, Find Me, Cycling Speed and Cadence and Time.

Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
 net/bluetooth/hci_event.c | 22 ++++++++++++++++------
 1 file changed, 16 insertions(+), 6 deletions(-)

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index b34ff1d..570f27d 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1820,15 +1820,25 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 	 * device.
 	 */
 	param = hci_find_conn_param(hdev, &conn->dst, conn->dst_type);
-	if (param && param->auto_connect == BT_AUTO_CONN_ALWAYS) {
+	if (param) {
 		int err;
 
-		err = hci_trigger_background_scan(hdev);
-		if (err)
-			BT_ERR("Failed to trigger background "
-					"scanning: %d", err);
+		switch (param->auto_connect){
+		case BT_AUTO_CONN_LINK_LOSS:
+			if (ev->reason != HCI_ERROR_CONNECTION_TIMEOUT)
+				break;
+			/* Fall through */
+
+		case BT_AUTO_CONN_ALWAYS:
+			err = hci_trigger_background_scan(hdev);
+			if (err)
+				BT_ERR("Failed to trigger background "
+						"scanning: %d", err);
+
+			param->bg_scan_triggered = true;
+			break;
+		}
 
-		param->bg_scan_triggered = true;
 		hci_conn_param_put(param);
 	}
 
-- 
1.8.4


^ permalink raw reply related

* [RFC 08/15] Bluetooth: Add support for BT_AUTO_CONN_ALWAYS
From: Andre Guedes @ 2013-10-16 23:17 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1381965485-9159-1-git-send-email-andre.guedes@openbossa.org>

This patch adds support for the BT_AUTO_CONN_ALWAYS option which
configures the kernel to autonomously establish a connection to
certain device. This option configures the kernel to always
establish the connection, no matter the reason the connection was
terminated.

This feature is required by some LE profiles such as HID over GATT,
Health Termomether and Blood Pressure. These profiles require the
host autonomously connect to the device as soon as it enters in
connectable mode (start advertising) so the device is able to
delivery a notification or indication.

The auto connection procedure the BT_AUTO_CONN_ALWAYS option implements
is summarized as follows: when a new device configured with BT_AUTO_
CONN_ALWAYS is added to the connection parameter list, the background
scan is triggered. Once the target device is found in range, the kernel
creates a connection to the device. If the connection is established
successfully, the background scan is untriggered. If the target device
disconnects, the background scan is triggered again and the whole auto
connect procedure starts again.

Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
 include/net/bluetooth/hci_core.h |  4 ++
 net/bluetooth/hci_core.c         | 92 ++++++++++++++++++++++++++++++++++++++++
 net/bluetooth/hci_event.c        | 36 ++++++++++++++++
 3 files changed, 132 insertions(+)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index cb6458a..db39eca 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -383,6 +383,7 @@ struct hci_conn_param {
 	u8 addr_type;
 
 	u8 auto_connect;
+	bool bg_scan_triggered;
 
 	u16 min_conn_interval;
 	u16 max_conn_interval;
@@ -765,6 +766,9 @@ int hci_add_conn_param(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type,
 		       u16 max_conn_interval);
 void hci_remove_conn_param(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type);
 
+void hci_auto_connect_check(struct hci_dev *hdev, bdaddr_t *addr,
+			    u8 addr_type);
+
 int hci_uuids_clear(struct hci_dev *hdev);
 
 int hci_link_keys_clear(struct hci_dev *hdev);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index c3e47e9..f232965 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2200,6 +2200,24 @@ struct hci_conn_param *hci_find_conn_param(struct hci_dev *hdev,
 	return NULL;
 }
 
+static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type)
+{
+	struct hci_conn *conn;
+
+	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, addr);
+
+	if (!conn)
+		return false;
+
+	if (conn->dst_type != type)
+		return false;
+
+	if (conn->state != BT_CONNECTED)
+		return false;
+
+	return true;
+}
+
 int hci_add_conn_param(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type,
 		       u8 auto_connect, u16 min_conn_interval,
 		       u16 max_conn_interval)
@@ -2221,12 +2239,29 @@ int hci_add_conn_param(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type,
 	bacpy(&param->addr, addr);
 	param->addr_type = addr_type;
 	param->auto_connect = auto_connect;
+	param->bg_scan_triggered = false;
 	param->min_conn_interval = min_conn_interval;
 	param->max_conn_interval = max_conn_interval;
 
 	hci_dev_lock(hdev);
 	list_add_rcu(&param->list, &hdev->conn_param);
 	hci_dev_unlock(hdev);
+
+	/* If it is configured to always automatically connect and we are not
+	 * connected to the given device, we trigger the background scan so
+	 * the connection is established as soon as the device gets in range.
+	 */
+	if (auto_connect == BT_AUTO_CONN_ALWAYS &&
+	    !is_connected(hdev, addr, addr_type)) {
+		int err;
+
+		err = hci_trigger_background_scan(hdev);
+		if (err)
+			return err;
+
+		param->bg_scan_triggered = true;
+	}
+
 	return 0;
 }
 
@@ -2251,6 +2286,17 @@ void hci_remove_conn_param(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type)
 	if (!param)
 		return;
 
+	if (param->bg_scan_triggered) {
+		int err;
+
+		err = hci_untrigger_background_scan(hdev);
+		if (err)
+			BT_ERR("Failed to untrigger background scanning: %d",
+			       err);
+
+		param->bg_scan_triggered = false;
+	}
+
 	hci_dev_lock(hdev);
 	__remove_conn_param(param);
 	hci_dev_unlock(hdev);
@@ -2271,6 +2317,52 @@ static void __clear_conn_param(struct hci_dev *hdev)
 		__remove_conn_param(param);
 }
 
+void hci_auto_connect_check(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type)
+{
+	struct hci_conn_param *param;
+	struct hci_conn *conn;
+	u8 bdaddr_type;
+
+	/* If there is no background scan trigger, it means the auto connection
+	 * procedure is not runninng.
+	 */
+	if (atomic_read(&hdev->background_scan_cnt) == 0)
+		return;
+
+	param = hci_find_conn_param(hdev, addr, addr_type);
+	if (!param)
+		return;
+
+	if (!param->bg_scan_triggered)
+		goto done;
+
+	if (addr_type == ADDR_LE_DEV_PUBLIC)
+		bdaddr_type = BDADDR_LE_PUBLIC;
+	else
+		bdaddr_type = BDADDR_LE_RANDOM;
+
+	conn = hci_connect(hdev, LE_LINK, addr, bdaddr_type, BT_SECURITY_LOW,
+			   HCI_AT_NO_BONDING);
+	if (IS_ERR(conn)) {
+		switch(PTR_ERR(conn)) {
+		case -EBUSY:
+			/* When hci_connect() returns EBUSY it means there is
+			 * already an LE connection attempt going on. Since the
+			 * controller supports only one connection attempt at
+			 * the time, we simply return.
+			 */
+			goto done;
+		default:
+			BT_ERR("Failed to auto connect: err %ld",
+			       PTR_ERR(conn));
+			goto done;
+		}
+	}
+
+done:
+	hci_conn_param_put(param);
+}
+
 static void inquiry_complete(struct hci_dev *hdev, u8 status)
 {
 	if (status) {
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index edb2342..b34ff1d 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1782,6 +1782,7 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
 	struct hci_conn *conn;
 	u8 type;
+	struct hci_conn_param *param;
 	bool send_mgmt_event = false;
 
 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
@@ -1815,6 +1816,22 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 	if (conn->type == ACL_LINK && conn->flush_key)
 		hci_remove_link_key(hdev, &conn->dst);
 
+	/* Trigger the background scan if auto connection is required for this
+	 * device.
+	 */
+	param = hci_find_conn_param(hdev, &conn->dst, conn->dst_type);
+	if (param && param->auto_connect == BT_AUTO_CONN_ALWAYS) {
+		int err;
+
+		err = hci_trigger_background_scan(hdev);
+		if (err)
+			BT_ERR("Failed to trigger background "
+					"scanning: %d", err);
+
+		param->bg_scan_triggered = true;
+		hci_conn_param_put(param);
+	}
+
 	type = conn->type;
 	hci_proto_disconn_cfm(conn, ev->reason);
 	hci_conn_del(conn);
@@ -3493,6 +3510,7 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
 	struct hci_conn *conn;
+	struct hci_conn_param *param;
 
 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
 
@@ -3546,6 +3564,22 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 
 	hci_proto_connect_cfm(conn, ev->status);
 
+	/* Since the connection has been established successfully, we should
+	 * untrigger the background scan if this is an auto connect device.
+	 */
+	param = hci_find_conn_param(hdev, &ev->bdaddr, ev->bdaddr_type);
+	if (param && param->bg_scan_triggered) {
+		int err;
+
+		err = hci_untrigger_background_scan(hdev);
+		if (err)
+			BT_ERR("Failed to untrigger background "
+					"scanning: %d", err);
+
+		param->bg_scan_triggered = false;
+		hci_conn_param_put(param);
+	}
+
 unlock:
 	hci_dev_unlock(hdev);
 }
@@ -3559,6 +3593,8 @@ static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
 	while (num_reports--) {
 		struct hci_ev_le_advertising_info *ev = ptr;
 
+		hci_auto_connect_check(hdev, &ev->bdaddr, ev->bdaddr_type);
+
 		rssi = ev->data[ev->length];
 		mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
 				  NULL, rssi, 0, 1, ev->data, ev->length);
-- 
1.8.4


^ permalink raw reply related

* [RFC 07/15] Bluetooth: Refactor hci_disconn_complete_evt
From: Andre Guedes @ 2013-10-16 23:17 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1381965485-9159-1-git-send-email-andre.guedes@openbossa.org>

hci_disconn_complete_evt() logic is more complicated than what it
should be, making it hard to follow and add new features. This patch
does some code refactoring by letting the main flow of the function
in first level of function scope.

Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
 net/bluetooth/hci_event.c | 62 +++++++++++++++++++++++++----------------------
 1 file changed, 33 insertions(+), 29 deletions(-)

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 6c3b193..edb2342 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1781,6 +1781,8 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
 	struct hci_conn *conn;
+	u8 type;
+	bool send_mgmt_event = false;
 
 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
 
@@ -1790,44 +1792,46 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 	if (!conn)
 		goto unlock;
 
-	if (ev->status == 0)
-		conn->state = BT_CLOSED;
-
 	if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
-	    (conn->type == ACL_LINK || conn->type == LE_LINK)) {
-		if (ev->status) {
+	    (conn->type == ACL_LINK || conn->type == LE_LINK))
+		send_mgmt_event = true;
+
+	if (ev->status) {
+		if (send_mgmt_event)
 			mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
 					       conn->dst_type, ev->status);
-		} else {
-			u8 reason = hci_to_mgmt_reason(ev->reason);
-
-			mgmt_device_disconnected(hdev, &conn->dst, conn->type,
-						 conn->dst_type, reason);
-		}
+		return;
 	}
 
-	if (ev->status == 0) {
-		u8 type = conn->type;
+	conn->state = BT_CLOSED;
 
-		if (type == ACL_LINK && conn->flush_key)
-			hci_remove_link_key(hdev, &conn->dst);
-		hci_proto_disconn_cfm(conn, ev->reason);
-		hci_conn_del(conn);
+	if (send_mgmt_event) {
+		u8 reason = hci_to_mgmt_reason(ev->reason);
 
-		/* Re-enable advertising if necessary, since it might
-		 * have been disabled by the connection. From the
-		 * HCI_LE_Set_Advertise_Enable command description in
-		 * the core specification (v4.0):
-		 * "The Controller shall continue advertising until the Host
-		 * issues an LE_Set_Advertise_Enable command with
-		 * Advertising_Enable set to 0x00 (Advertising is disabled)
-		 * or until a connection is created or until the Advertising
-		 * is timed out due to Directed Advertising."
-		 */
-		if (type == LE_LINK)
-			mgmt_reenable_advertising(hdev);
+		mgmt_device_disconnected(hdev, &conn->dst, conn->type,
+					 conn->dst_type, reason);
 	}
 
+	if (conn->type == ACL_LINK && conn->flush_key)
+		hci_remove_link_key(hdev, &conn->dst);
+
+	type = conn->type;
+	hci_proto_disconn_cfm(conn, ev->reason);
+	hci_conn_del(conn);
+
+	/* Re-enable advertising if necessary, since it might
+	 * have been disabled by the connection. From the
+	 * HCI_LE_Set_Advertise_Enable command description in
+	 * the core specification (v4.0):
+	 * "The Controller shall continue advertising until the Host
+	 * issues an LE_Set_Advertise_Enable command with
+	 * Advertising_Enable set to 0x00 (Advertising is disabled)
+	 * or until a connection is created or until the Advertising
+	 * is timed out due to Directed Advertising."
+	 */
+	if (type == LE_LINK)
+		mgmt_reenable_advertising(hdev);
+
 unlock:
 	hci_dev_unlock(hdev);
 }
-- 
1.8.4


^ permalink raw reply related

* [RFC 06/15] Bluetooth: Background scanning
From: Andre Guedes @ 2013-10-16 23:17 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1381965485-9159-1-git-send-email-andre.guedes@openbossa.org>

This patch adds helpers to trigger and untrigger the background
scanning. As long as the number of triggers are greater than zero,
we keep the background scanning running. Once the number of triggers
reaches zero, it is stopped.

Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
 include/net/bluetooth/hci_core.h |  7 ++++
 net/bluetooth/hci_core.c         | 83 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 90 insertions(+)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 1e67da5..cb6458a 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -288,6 +288,10 @@ struct hci_dev {
 	__u8			scan_rsp_data[HCI_MAX_AD_LENGTH];
 	__u8			scan_rsp_data_len;
 
+	/* This counter tracks the number of background scanning triggers
+	 */
+	atomic_t		background_scan_cnt;
+
 	int (*open)(struct hci_dev *hdev);
 	int (*close)(struct hci_dev *hdev);
 	int (*flush)(struct hci_dev *hdev);
@@ -1191,4 +1195,7 @@ void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8],
 #define SCO_AIRMODE_CVSD       0x0000
 #define SCO_AIRMODE_TRANSP     0x0003
 
+int hci_trigger_background_scan(struct hci_dev *hdev);
+int hci_untrigger_background_scan(struct hci_dev *hdev);
+
 #endif /* __HCI_CORE_H */
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index c9c3390..c3e47e9 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2402,6 +2402,8 @@ struct hci_dev *hci_alloc_dev(void)
 	hci_init_sysfs(hdev);
 	discovery_init(hdev);
 
+	atomic_set(&hdev->background_scan_cnt, 0);
+
 	return hdev;
 }
 EXPORT_SYMBOL(hci_alloc_dev);
@@ -3786,3 +3788,84 @@ static void hci_cmd_work(struct work_struct *work)
 		}
 	}
 }
+
+static void start_background_scan_complete(struct hci_dev *hdev, u8 status)
+{
+	if (status)
+		BT_DBG("HCI request failed to start background scanning: "
+		       "status 0x%2.2x", status);
+}
+
+int hci_trigger_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;
+	int err;
+
+	BT_DBG("%s", hdev->name);
+
+	/* If we already have triggers, there is no need to send HCI command
+	 * to start the background scanning.
+	 */
+	if (atomic_read(&hdev->background_scan_cnt) > 0)
+		goto done;
+
+	hci_req_init(&req, hdev);
+
+	memset(&param_cp, 0, sizeof(param_cp));
+	param_cp.type = LE_SCAN_PASSIVE;
+	param_cp.interval = cpu_to_le16(hdev->le_scan_interval);
+	param_cp.window = cpu_to_le16(hdev->le_scan_window);
+	hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
+		    &param_cp);
+
+	memset(&enable_cp, 0, sizeof(enable_cp));
+	enable_cp.enable = LE_SCAN_ENABLE;
+	enable_cp.filter_dup = LE_SCAN_FILTER_DUP_DISABLE;
+	hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
+		    &enable_cp);
+
+	err = hci_req_run(&req, start_background_scan_complete);
+	if (err)
+		return err;
+
+done:
+	atomic_inc(&hdev->background_scan_cnt);
+	return 0;
+}
+
+static void stop_background_scan_complete(struct hci_dev *hdev, u8 status)
+{
+	if (status)
+		BT_DBG("HCI request failed to stop background scanning: "
+		       "status 0x%2.2x", status);
+}
+
+int hci_untrigger_background_scan(struct hci_dev *hdev)
+{
+	struct hci_cp_le_set_scan_enable cp;
+	struct hci_request req;
+	int err;
+
+	/* If we have more triggers, we should keep scanning. */
+	if (atomic_read(&hdev->background_scan_cnt) > 1)
+		goto done;
+
+	if (!test_bit(HCI_LE_SCAN, &hdev->dev_flags))
+		goto done;
+
+	hci_req_init(&req, hdev);
+
+	memset(&cp, 0, sizeof(cp));
+	cp.enable = LE_SCAN_DISABLE;
+	hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
+
+	err = hci_req_run(&req, stop_background_scan_complete);
+	if (err)
+		return err;
+
+done:
+	atomic_dec(&hdev->background_scan_cnt);
+	return 0;
+}
-- 
1.8.4


^ permalink raw reply related

* [RFC 05/15] Bluetooth: Use connection parameters if any
From: Andre Guedes @ 2013-10-16 23:17 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1381965485-9159-1-git-send-email-andre.guedes@openbossa.org>

This patch changes hci_create_le_conn() so it uses the connection
parameters specified by the user. If no parameters were configured,
we use the default values.

Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
 net/bluetooth/hci_conn.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 4e72650..d64000e 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -548,6 +548,7 @@ static int hci_create_le_conn(struct hci_conn *conn)
 	struct hci_dev *hdev = conn->hdev;
 	struct hci_cp_le_create_conn cp;
 	struct hci_request req;
+	struct hci_conn_param *param;
 	int err;
 
 	hci_req_init(&req, hdev);
@@ -558,11 +559,18 @@ static int hci_create_le_conn(struct hci_conn *conn)
 	bacpy(&cp.peer_addr, &conn->dst);
 	cp.peer_addr_type = conn->dst_type;
 	cp.own_address_type = conn->src_type;
-	cp.conn_interval_min = __constant_cpu_to_le16(0x0028);
-	cp.conn_interval_max = __constant_cpu_to_le16(0x0038);
 	cp.supervision_timeout = __constant_cpu_to_le16(0x002a);
 	cp.min_ce_len = __constant_cpu_to_le16(0x0000);
 	cp.max_ce_len = __constant_cpu_to_le16(0x0000);
+	param = hci_find_conn_param(hdev, &conn->dst, conn->dst_type);
+	if (param) {
+		cp.conn_interval_min = cpu_to_le16(param->min_conn_interval);
+		cp.conn_interval_max = cpu_to_le16(param->max_conn_interval);
+		hci_conn_param_put(param);
+	} else {
+		cp.conn_interval_min = __constant_cpu_to_le16(0x0028);
+		cp.conn_interval_max = __constant_cpu_to_le16(0x0038);
+	}
 	hci_req_add(&req, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp);
 
 	err = hci_req_run(&req, create_le_conn_complete);
-- 
1.8.4


^ permalink raw reply related

* [RFC 04/15] Bluetooth: Make find_conn_param() helper non-local
From: Andre Guedes @ 2013-10-16 23:17 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1381965485-9159-1-git-send-email-andre.guedes@openbossa.org>

This patch makes the find_conn_param() helper non-local by adding the
hci_ prefix and declaring it in hci_core.h. This helper will be used
in hci_conn.c to get the connection parameters when establishing
connections.

Since hci_find_conn_param() returns a reference to the hci_conn_param
object, it was added a refcount to hci_conn_param to control its
lifetime. This way, we avoid bugs such as one thread deletes hci_conn_
param (e.g. thread running MGMT_OP_REMOVE_CONN_PARAM command) while
another thread holds a reference to that object (e.g thread carrying
out the connection establishment).	.

Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
 include/net/bluetooth/hci_core.h |  5 +++++
 net/bluetooth/hci_core.c         | 46 ++++++++++++++++++++++++++++++++++------
 2 files changed, 45 insertions(+), 6 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 98be273..1e67da5 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -371,6 +371,8 @@ struct hci_chan {
 };
 
 struct hci_conn_param {
+	struct kref refcount;
+
 	struct list_head list;
 
 	bdaddr_t addr;
@@ -751,6 +753,9 @@ int hci_blacklist_clear(struct hci_dev *hdev);
 int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
 int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
 
+struct hci_conn_param *hci_find_conn_param(struct hci_dev *hdev,
+					   bdaddr_t *addr, u8 addr_type);
+void hci_conn_param_put(struct hci_conn_param *param);
 int hci_add_conn_param(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type,
 		       u8 auto_connect, u16 min_conn_interval,
 		       u16 max_conn_interval);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index a4242ac..c9c3390 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2151,8 +2151,34 @@ int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
 	return mgmt_device_unblocked(hdev, bdaddr, type);
 }
 
-struct hci_conn_param *find_conn_param(struct hci_dev *hdev,
-				       bdaddr_t *addr, u8 addr_type)
+static void hci_conn_param_get(struct hci_conn_param *param)
+{
+	kref_get(&param->refcount);
+}
+
+static void release_hci_conn_param(struct kref *kref)
+{
+	struct hci_conn_param *param = container_of(kref,
+						    struct hci_conn_param,
+						    refcount);
+
+	kfree(param);
+}
+
+void hci_conn_param_put(struct hci_conn_param *param)
+{
+	kref_put(&param->refcount, release_hci_conn_param);
+}
+
+/*
+ * Lookup hci_conn_param in hdev->conn_param list.
+ *
+ * Return a reference to hci_conn_param object with refcount incremented.
+ * The caller should drop its reference by using hci_conn_param_put(). If
+ * hci_conn_param is not found, NULL is returned.
+ */
+struct hci_conn_param *hci_find_conn_param(struct hci_dev *hdev,
+					   bdaddr_t *addr, u8 addr_type)
 {
 	struct hci_conn_param *param;
 
@@ -2164,6 +2190,8 @@ struct hci_conn_param *find_conn_param(struct hci_dev *hdev,
 		if (param->addr_type != addr_type)
 			continue;
 
+		hci_conn_param_get(param);
+
 		rcu_read_unlock();
 		return param;
 	}
@@ -2178,14 +2206,18 @@ int hci_add_conn_param(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type,
 {
 	struct hci_conn_param *param;
 
-	param = find_conn_param(hdev, addr, addr_type);
-	if (param)
+	param = hci_find_conn_param(hdev, addr, addr_type);
+	if (param) {
+		hci_conn_param_put(param);
 		return -EEXIST;
+	}
 
 	param = kmalloc(sizeof(*param), GFP_KERNEL);
 	if (!param)
 		return -ENOMEM;
 
+	kref_init(&param->refcount);
+
 	bacpy(&param->addr, addr);
 	param->addr_type = addr_type;
 	param->auto_connect = auto_connect;
@@ -2208,20 +2240,22 @@ static void __remove_conn_param(struct hci_conn_param *param)
 	list_del_rcu(&param->list);
 	synchronize_rcu();
 
-	kfree(param);
+	hci_conn_param_put(param);
 }
 
 void hci_remove_conn_param(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type)
 {
 	struct hci_conn_param *param;
 
-	param = find_conn_param(hdev, addr, addr_type);
+	param = hci_find_conn_param(hdev, addr, addr_type);
 	if (!param)
 		return;
 
 	hci_dev_lock(hdev);
 	__remove_conn_param(param);
 	hci_dev_unlock(hdev);
+
+	hci_conn_param_put(param);
 }
 
 /*
-- 
1.8.4


^ permalink raw reply related

* [RFC 03/15] Bluetooth: Mgmt command for removing connection parameters
From: Andre Guedes @ 2013-10-16 23:17 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1381965485-9159-1-git-send-email-andre.guedes@openbossa.org>

This patch introduces the MGMT_OP_REMOVE_CONN_PARAM which removes from
the controller's list the connection parameters from a given device.

Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
 include/net/bluetooth/mgmt.h |  6 ++++++
 net/bluetooth/mgmt.c         | 29 +++++++++++++++++++++++++++++
 2 files changed, 35 insertions(+)

diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index ed689b5..a79100a 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -378,6 +378,12 @@ struct mgmt_cp_add_conn_param {
 } __packed;
 #define MGMT_ADD_CONN_PARAM_SIZE	(MGMT_ADDR_INFO_SIZE + 5)
 
+#define MGMT_OP_REMOVE_CONN_PARAM	0x002E
+struct mgmt_cp_remove_conn_param {
+	struct mgmt_addr_info addr;
+} __packed;
+#define MGMT_REMOVE_CONN_PARAM_SIZE	MGMT_ADDR_INFO_SIZE
+
 #define MGMT_EV_CMD_COMPLETE		0x0001
 struct mgmt_ev_cmd_complete {
 	__le16	opcode;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 5d1a2e8..c68aea5 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -80,6 +80,7 @@ static const u16 mgmt_commands[] = {
 	MGMT_OP_SET_STATIC_ADDRESS,
 	MGMT_OP_SET_SCAN_PARAMS,
 	MGMT_OP_ADD_CONN_PARAM,
+	MGMT_OP_REMOVE_CONN_PARAM,
 };
 
 static const u16 mgmt_events[] = {
@@ -4059,6 +4060,33 @@ static int add_conn_param(struct sock *sk, struct hci_dev *hdev, void *cp_data,
 			    NULL, 0);
 }
 
+static int remove_conn_param(struct sock *sk, struct hci_dev *hdev,
+			     void *cp_data, u16 len)
+{
+	struct mgmt_cp_remove_conn_param *cp = cp_data;
+	u8 status;
+	u8 addr_type;
+
+	if (cp->addr.type == BDADDR_BREDR)
+		return cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_CONN_PARAM,
+				    MGMT_STATUS_NOT_SUPPORTED, NULL, 0);
+
+	status = mgmt_le_support(hdev);
+	if (status)
+		return cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_CONN_PARAM,
+				    status, NULL, 0);
+
+	if (cp->addr.type == BDADDR_LE_PUBLIC)
+		addr_type = ADDR_LE_DEV_PUBLIC;
+	else
+		addr_type = ADDR_LE_DEV_RANDOM;
+
+	hci_remove_conn_param(hdev, &cp->addr.bdaddr, addr_type);
+
+	return cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_CONN_PARAM,
+			    MGMT_STATUS_SUCCESS, NULL, 0);
+}
+
 static const struct mgmt_handler {
 	int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
 		     u16 data_len);
@@ -4111,6 +4139,7 @@ static const struct mgmt_handler {
 	{ set_static_address,     false, MGMT_SET_STATIC_ADDRESS_SIZE },
 	{ set_scan_params,        false, MGMT_SET_SCAN_PARAMS_SIZE },
 	{ add_conn_param,         false, MGMT_ADD_CONN_PARAM_SIZE },
+	{ remove_conn_param,      false, MGMT_REMOVE_CONN_PARAM_SIZE },
 };
 
 
-- 
1.8.4


^ permalink raw reply related

* [RFC 02/15] Bluetooth: Mgmt command for adding connection parameters
From: Andre Guedes @ 2013-10-16 23:17 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1381965485-9159-1-git-send-email-andre.guedes@openbossa.org>

This patch introduces a new Mgmt command (MGMT_OP_ADD_CONN_PARAM) which
adds the connection parameters to controller's connection parameters
list. These parameters will be used by the kernel when it establishes a
connection with the given device.

This patch also moves the 'auto_connect' enum from hci_core.h to
bluetooth.h since the will accessed used by userspace in order to
send the MGMT_OP_ADD_CONN_PARAM command.

Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
 include/net/bluetooth/bluetooth.h |  6 ++++++
 include/net/bluetooth/hci_core.h  |  6 +-----
 include/net/bluetooth/mgmt.h      |  9 +++++++++
 net/bluetooth/mgmt.c              | 35 +++++++++++++++++++++++++++++++++++
 4 files changed, 51 insertions(+), 5 deletions(-)

diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index bf2ddff..8509520 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -354,4 +354,10 @@ void sco_exit(void);
 
 void bt_sock_reclassify_lock(struct sock *sk, int proto);
 
+enum {
+	BT_AUTO_CONN_DISABLED,
+	BT_AUTO_CONN_ALWAYS,
+	BT_AUTO_CONN_LINK_LOSS,
+};
+
 #endif /* __BLUETOOTH_H */
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 5052bf0..98be273 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -376,11 +376,7 @@ struct hci_conn_param {
 	bdaddr_t addr;
 	u8 addr_type;
 
-	enum {
-		HCI_AUTO_CONN_DISABLED,
-		HCI_AUTO_CONN_ALWAYS,
-		HCI_AUTO_CONN_LINK_LOSS,
-	} auto_connect;
+	u8 auto_connect;
 
 	u16 min_conn_interval;
 	u16 max_conn_interval;
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 518c5c8..ed689b5 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -369,6 +369,15 @@ struct mgmt_cp_set_scan_params {
 } __packed;
 #define MGMT_SET_SCAN_PARAMS_SIZE	4
 
+#define MGMT_OP_ADD_CONN_PARAM		0x002D
+struct mgmt_cp_add_conn_param {
+	struct mgmt_addr_info addr;
+	__u8 auto_connect;
+	__le16 min_conn_interval;
+	__le16 max_conn_interval;
+} __packed;
+#define MGMT_ADD_CONN_PARAM_SIZE	(MGMT_ADDR_INFO_SIZE + 5)
+
 #define MGMT_EV_CMD_COMPLETE		0x0001
 struct mgmt_ev_cmd_complete {
 	__le16	opcode;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index a727b47..5d1a2e8 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -79,6 +79,7 @@ static const u16 mgmt_commands[] = {
 	MGMT_OP_SET_BREDR,
 	MGMT_OP_SET_STATIC_ADDRESS,
 	MGMT_OP_SET_SCAN_PARAMS,
+	MGMT_OP_ADD_CONN_PARAM,
 };
 
 static const u16 mgmt_events[] = {
@@ -4025,6 +4026,39 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
 	return err;
 }
 
+static int add_conn_param(struct sock *sk, struct hci_dev *hdev, void *cp_data,
+			  u16 len)
+{
+	struct mgmt_cp_add_conn_param *cp = cp_data;
+	u8 status;
+	u8 addr_type;
+
+	if (cp->addr.type == BDADDR_BREDR)
+		return cmd_complete(sk, hdev->id, MGMT_OP_ADD_CONN_PARAM,
+				    MGMT_STATUS_NOT_SUPPORTED, NULL, 0);
+
+	status = mgmt_le_support(hdev);
+	if (status)
+		return cmd_complete(sk, hdev->id, MGMT_OP_ADD_CONN_PARAM,
+				    status, NULL, 0);
+
+	if (cp->addr.type == BDADDR_LE_PUBLIC)
+		addr_type = ADDR_LE_DEV_PUBLIC;
+	else
+		addr_type = ADDR_LE_DEV_RANDOM;
+
+	if (hci_add_conn_param(hdev, &cp->addr.bdaddr, addr_type,
+			       cp->auto_connect,
+			       __le16_to_cpu(cp->min_conn_interval),
+			       __le16_to_cpu(cp->max_conn_interval)))
+		status = MGMT_STATUS_FAILED;
+	else
+		status = MGMT_STATUS_SUCCESS;
+
+	return cmd_complete(sk, hdev->id, MGMT_OP_ADD_CONN_PARAM, status,
+			    NULL, 0);
+}
+
 static const struct mgmt_handler {
 	int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
 		     u16 data_len);
@@ -4076,6 +4110,7 @@ static const struct mgmt_handler {
 	{ set_bredr,              false, MGMT_SETTING_SIZE },
 	{ set_static_address,     false, MGMT_SET_STATIC_ADDRESS_SIZE },
 	{ set_scan_params,        false, MGMT_SET_SCAN_PARAMS_SIZE },
+	{ add_conn_param,         false, MGMT_ADD_CONN_PARAM_SIZE },
 };
 
 
-- 
1.8.4


^ permalink raw reply related

* [RFC 01/15] Bluetooth: Introduce connection parameters list
From: Andre Guedes @ 2013-10-16 23:17 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1381965485-9159-1-git-send-email-andre.guedes@openbossa.org>

This patch adds to hdev the connection parameters list (hdev->
conn_param). The elements from this list (struct hci_conn_param)
contains the connection parameters (for now, minimum and maximum
connection interval) that should be used for establishing
connection.

The struct hci_conn_param also defines the 'auto_connect' field
which will be used to implement the auto connection mechanism.

Moreover, this patch adds helper functions to manipulate hdev->conn_
param list. Some of these functions are also declared in hci_core.h
since they will be used outside hci_core.c in upcoming patches.

Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
 include/net/bluetooth/hci_core.h | 23 +++++++++++
 net/bluetooth/hci_core.c         | 88 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 111 insertions(+)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 07c2da4..5052bf0 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -266,6 +266,8 @@ struct hci_dev {
 
 	struct list_head	remote_oob_data;
 
+	struct list_head	conn_param;
+
 	struct hci_dev_stats	stat;
 
 	atomic_t		promisc;
@@ -368,6 +370,22 @@ struct hci_chan {
 	__u8		state;
 };
 
+struct hci_conn_param {
+	struct list_head list;
+
+	bdaddr_t addr;
+	u8 addr_type;
+
+	enum {
+		HCI_AUTO_CONN_DISABLED,
+		HCI_AUTO_CONN_ALWAYS,
+		HCI_AUTO_CONN_LINK_LOSS,
+	} auto_connect;
+
+	u16 min_conn_interval;
+	u16 max_conn_interval;
+};
+
 extern struct list_head hci_dev_list;
 extern struct list_head hci_cb_list;
 extern rwlock_t hci_dev_list_lock;
@@ -737,6 +755,11 @@ int hci_blacklist_clear(struct hci_dev *hdev);
 int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
 int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
 
+int hci_add_conn_param(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type,
+		       u8 auto_connect, u16 min_conn_interval,
+		       u16 max_conn_interval);
+void hci_remove_conn_param(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type);
+
 int hci_uuids_clear(struct hci_dev *hdev);
 
 int hci_link_keys_clear(struct hci_dev *hdev);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 73c8def..a4242ac 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2151,6 +2151,92 @@ int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
 	return mgmt_device_unblocked(hdev, bdaddr, type);
 }
 
+struct hci_conn_param *find_conn_param(struct hci_dev *hdev,
+				       bdaddr_t *addr, u8 addr_type)
+{
+	struct hci_conn_param *param;
+
+	rcu_read_lock();
+
+	list_for_each_entry(param, &hdev->conn_param, list) {
+		if (bacmp(&param->addr, addr))
+			continue;
+		if (param->addr_type != addr_type)
+			continue;
+
+		rcu_read_unlock();
+		return param;
+	}
+
+	rcu_read_unlock();
+	return NULL;
+}
+
+int hci_add_conn_param(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type,
+		       u8 auto_connect, u16 min_conn_interval,
+		       u16 max_conn_interval)
+{
+	struct hci_conn_param *param;
+
+	param = find_conn_param(hdev, addr, addr_type);
+	if (param)
+		return -EEXIST;
+
+	param = kmalloc(sizeof(*param), GFP_KERNEL);
+	if (!param)
+		return -ENOMEM;
+
+	bacpy(&param->addr, addr);
+	param->addr_type = addr_type;
+	param->auto_connect = auto_connect;
+	param->min_conn_interval = min_conn_interval;
+	param->max_conn_interval = max_conn_interval;
+
+	hci_dev_lock(hdev);
+	list_add_rcu(&param->list, &hdev->conn_param);
+	hci_dev_unlock(hdev);
+	return 0;
+}
+
+/*
+ * Remove from hdev->conn_param and free hci_conn_param.
+ *
+ * This function requires the caller holds hdev->lock.
+ */
+static void __remove_conn_param(struct hci_conn_param *param)
+{
+	list_del_rcu(&param->list);
+	synchronize_rcu();
+
+	kfree(param);
+}
+
+void hci_remove_conn_param(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type)
+{
+	struct hci_conn_param *param;
+
+	param = find_conn_param(hdev, addr, addr_type);
+	if (!param)
+		return;
+
+	hci_dev_lock(hdev);
+	__remove_conn_param(param);
+	hci_dev_unlock(hdev);
+}
+
+/*
+ * Remove all elements from hdev->conn_param list.
+ *
+ * This function requires the caller holds hdev->lock.
+ */
+static void __clear_conn_param(struct hci_dev *hdev)
+{
+	struct hci_conn_param *param, *tmp;
+
+	list_for_each_entry_safe(param, tmp, &hdev->conn_param, list)
+		__remove_conn_param(param);
+}
+
 static void inquiry_complete(struct hci_dev *hdev, u8 status)
 {
 	if (status) {
@@ -2259,6 +2345,7 @@ struct hci_dev *hci_alloc_dev(void)
 	INIT_LIST_HEAD(&hdev->link_keys);
 	INIT_LIST_HEAD(&hdev->long_term_keys);
 	INIT_LIST_HEAD(&hdev->remote_oob_data);
+	INIT_LIST_HEAD(&hdev->conn_param);
 	INIT_LIST_HEAD(&hdev->conn_hash.list);
 
 	INIT_WORK(&hdev->rx_work, hci_rx_work);
@@ -2437,6 +2524,7 @@ void hci_unregister_dev(struct hci_dev *hdev)
 	hci_link_keys_clear(hdev);
 	hci_smp_ltks_clear(hdev);
 	hci_remote_oob_data_clear(hdev);
+	__clear_conn_param(hdev);
 	hci_dev_unlock(hdev);
 
 	hci_dev_put(hdev);
-- 
1.8.4


^ permalink raw reply related


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