2014-08-04 10:34:13

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH v4 0/6] android/gatt: Make usage of kernel auto connect feat.

Following patches add support to BfA to use kernel auto connect list
when mgmt interface is 1.7 or highier.

Tested on PC with latest kernel.

v2: Fix in Patch 5/6. Forgot one if check
v3: Rebase + whitespace fix
v4: Handle Johan comment

Note: For android new backports are needed. Will be done early next week.

Lukasz Rymanowski (6):
android/bluetooth: Add flag for kernel connection control
android/bluetooth: Add API to add device to auto connect list
android/bluetooth: Add API to remove device from auto connect list
android/gatt: Refactor trigger connection function.
android/gatt: Use kernel auto connect feature if possible
android/bluetooth: Clear auto connect list on startup

android/bluetooth.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++++
android/bluetooth.h | 6 ++++
android/gatt.c | 70 ++++++++++++++++++++++++++++--------
3 files changed, 162 insertions(+), 15 deletions(-)

--
1.8.4



2014-08-04 11:30:49

by Johan Hedberg

[permalink] [raw]
Subject: Re: [PATCH v4 0/6] android/gatt: Make usage of kernel auto connect feat.

Hi Lukasz,

On Mon, Aug 04, 2014, Lukasz Rymanowski wrote:
> Following patches add support to BfA to use kernel auto connect list
> when mgmt interface is 1.7 or highier.
>
> Tested on PC with latest kernel.
>
> v2: Fix in Patch 5/6. Forgot one if check
> v3: Rebase + whitespace fix
> v4: Handle Johan comment
>
> Note: For android new backports are needed. Will be done early next week.
>
> Lukasz Rymanowski (6):
> android/bluetooth: Add flag for kernel connection control
> android/bluetooth: Add API to add device to auto connect list
> android/bluetooth: Add API to remove device from auto connect list
> android/gatt: Refactor trigger connection function.
> android/gatt: Use kernel auto connect feature if possible
> android/bluetooth: Clear auto connect list on startup
>
> android/bluetooth.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++++
> android/bluetooth.h | 6 ++++
> android/gatt.c | 70 ++++++++++++++++++++++++++++--------
> 3 files changed, 162 insertions(+), 15 deletions(-)

All patches have been applied. Thanks.

Johan

2014-08-04 10:34:18

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH v4 5/6] android/gatt: Use kernel auto connect feature if possible

---
android/gatt.c | 31 ++++++++++++++++++++++++++++++-
1 file changed, 30 insertions(+), 1 deletion(-)

diff --git a/android/gatt.c b/android/gatt.c
index 448bcb8..89748d2 100644
--- a/android/gatt.c
+++ b/android/gatt.c
@@ -1383,6 +1383,8 @@ static void connect_cb(GIOChannel *io, GError *gerr, gpointer user_data)

device_set_state(dev, DEVICE_CONNECTED);

+ bt_auto_connect_remove(&dev->bdaddr);
+
/* Send exchange mtu request as we assume being client and server */
/* TODO: Dont exchange mtu if no client apps */
send_exchange_mtu_request(dev);
@@ -1529,6 +1531,10 @@ static void le_device_found_handler(const bdaddr_t *addr, uint8_t addr_type,
sizeof(*ev) + ev->len, ev);

connect:
+ /* We use auto connect feature from kernel if possible */
+ if (bt_kernel_conn_control())
+ return;
+
dev = find_device_by_addr(addr);
if (!dev) {
if (!bonded)
@@ -1749,6 +1755,19 @@ static int connect_bredr(struct gatt_device *dev)
return 0;
}

+static bool auto_connect(struct gatt_device *dev)
+{
+ bool err;
+
+ err = bt_auto_connect_add(&dev->bdaddr);
+ if (!err)
+ return false;
+
+ device_set_state(dev, DEVICE_CONNECT_INIT);
+
+ return true;
+}
+
static bool trigger_connection(struct app_connection *connection)
{
bool ret;
@@ -1763,6 +1782,13 @@ static bool trigger_connection(struct app_connection *connection)
BDADDR_BREDR)
return connect_bredr(connection->device) == 0;

+ /*
+ * For LE devices use auto connect feature if possible
+ * Note: Connection state is handled inside auto_connect() func
+ */
+ if (bt_kernel_conn_control())
+ return auto_connect(connection->device);
+
/* Trigger discovery if not already started */
if (!scanning) {
if (!bt_le_discovery_start()) {
@@ -1771,6 +1797,7 @@ static bool trigger_connection(struct app_connection *connection)
break;
}
}
+
ret = true;
device_set_state(connection->device, DEVICE_CONNECT_INIT);
break;
@@ -6091,7 +6118,9 @@ static void connect_confirm(GIOChannel *io, void *user_data)

dev->bdaddr_type = dst_type;
} else {
- if (dev->state != DEVICE_DISCONNECTED) {
+ if ((dev->state != DEVICE_DISCONNECTED) &&
+ !(dev->state == DEVICE_CONNECT_INIT &&
+ bt_kernel_conn_control())) {
char addr[18];

ba2str(&dst, addr);
--
1.8.4


2014-08-04 10:34:17

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH v4 4/6] android/gatt: Refactor trigger connection function.

Refactor code so it is clear what action we take in different connection
states.
---
android/gatt.c | 39 +++++++++++++++++++++++++--------------
1 file changed, 25 insertions(+), 14 deletions(-)

diff --git a/android/gatt.c b/android/gatt.c
index 11d7a2c..448bcb8 100644
--- a/android/gatt.c
+++ b/android/gatt.c
@@ -1751,31 +1751,42 @@ static int connect_bredr(struct gatt_device *dev)

static bool trigger_connection(struct app_connection *connection)
{
+ bool ret;
+
switch (connection->device->state) {
case DEVICE_DISCONNECTED:
+ /*
+ * If device was last seen over BR/EDR connect over it.
+ * Note: Connection state is handled in connect_bredr() func
+ */
+ if (bt_device_last_seen_bearer(&connection->device->bdaddr) ==
+ BDADDR_BREDR)
+ return connect_bredr(connection->device) == 0;
+
+ /* Trigger discovery if not already started */
+ if (!scanning) {
+ if (!bt_le_discovery_start()) {
+ error("gatt: Could not start scan");
+ ret = false;
+ break;
+ }
+ }
+ ret = true;
device_set_state(connection->device, DEVICE_CONNECT_INIT);
break;
case DEVICE_CONNECTED:
send_app_connect_notify(connection, GATT_SUCCESS);
+ ret = true;
break;
+ case DEVICE_CONNECT_READY:
+ case DEVICE_CONNECT_INIT:
default:
+ /* In those cases connection is already triggered. */
+ ret = true;
break;
}

- /* If device was last seen over BR/EDR connect over it */
- if (bt_device_last_seen_bearer(&connection->device->bdaddr) ==
- BDADDR_BREDR)
- return connect_bredr(connection->device) == 0;
-
- /* after state change trigger discovering */
- if (!scanning && (connection->device->state == DEVICE_CONNECT_INIT))
- if (!bt_le_discovery_start()) {
- error("gatt: Could not start scan");
-
- return false;
- }
-
- return true;
+ return ret;
}

static uint8_t unregister_app(int client_if)
--
1.8.4


2014-08-04 10:34:19

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH v4 6/6] android/bluetooth: Clear auto connect list on startup

In android we add devices to auto connect list when application trigger
connect. We need to make sure that when bluetooth is turn on there is
no devices in auto connect list in the kernel.
---
android/bluetooth.c | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)

diff --git a/android/bluetooth.c b/android/bluetooth.c
index 34690b7..38ee9a9 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -3129,6 +3129,34 @@ static void add_mps_record(void)
}
}

+static void clear_auto_connect_list_complete(uint8_t status,
+ uint16_t length,
+ const void *param,
+ void *user_data)
+{
+ if (status != MGMT_STATUS_SUCCESS)
+ error("Failed to clear auto connect list: %s (0x%02x)",
+ mgmt_errstr(status), status);
+}
+
+static void clear_auto_connect_list(void)
+{
+ struct mgmt_cp_remove_device cp;
+
+ if (!kernel_conn_control)
+ return;
+
+ memset(&cp, 0, sizeof(cp));
+
+ if (mgmt_send(mgmt_if, MGMT_OP_REMOVE_DEVICE, adapter.index,
+ sizeof(cp), &cp,
+ clear_auto_connect_list_complete,
+ NULL, NULL) > 0)
+ return;
+
+ error("Could not clear auto connect list");
+}
+
static void read_info_complete(uint8_t status, uint16_t length,
const void *param, void *user_data)
{
@@ -3186,6 +3214,7 @@ static void read_info_complete(uint8_t status, uint16_t length,
register_mgmt_handlers();

clear_uuids();
+ clear_auto_connect_list();

set_io_capability();
set_device_id();
--
1.8.4


2014-08-04 10:34:16

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH v4 3/6] android/bluetooth: Add API to remove device from auto connect list

---
android/bluetooth.c | 28 ++++++++++++++++++++++++++++
android/bluetooth.h | 2 ++
2 files changed, 30 insertions(+)

diff --git a/android/bluetooth.c b/android/bluetooth.c
index a4a77c8..34690b7 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -1527,6 +1527,34 @@ bool bt_auto_connect_add(const bdaddr_t *addr)
return false;
}

+void bt_auto_connect_remove(const bdaddr_t *addr)
+{
+ struct mgmt_cp_remove_device cp;
+ struct device *dev;
+
+ if (!kernel_conn_control)
+ return;
+
+ dev = find_device(addr);
+ if (!dev)
+ return;
+
+ if (dev->bdaddr_type == BDADDR_BREDR) {
+ DBG("auto-connection feature is not available for BR/EDR");
+ return;
+ }
+
+ memset(&cp, 0, sizeof(cp));
+ bacpy(&cp.addr.bdaddr, addr);
+ cp.addr.type = dev->bdaddr_type;
+
+ if (mgmt_send(mgmt_if, MGMT_OP_REMOVE_DEVICE, adapter.index,
+ sizeof(cp), &cp, NULL, NULL, NULL) > 0)
+ return;
+
+ error("Failed to remove device");
+}
+
static bool rssi_above_threshold(int old, int new)
{
/* only 8 dBm or more */
diff --git a/android/bluetooth.h b/android/bluetooth.h
index 4a7063d..ac7f3ad 100644
--- a/android/bluetooth.h
+++ b/android/bluetooth.h
@@ -83,3 +83,5 @@ const bdaddr_t *bt_get_id_addr(const bdaddr_t *addr, uint8_t *type);
bool bt_kernel_conn_control(void);

bool bt_auto_connect_add(const bdaddr_t *addr);
+
+void bt_auto_connect_remove(const bdaddr_t *addr);
--
1.8.4


2014-08-04 10:34:14

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH v4 1/6] android/bluetooth: Add flag for kernel connection control

This patch set option kernel connection control to TRUE if mgmt interface
is 1.7 or higier. Kernel connect control means that things like
background scan, auto connect or white list are supported by kernel and
can be used by daemon.
---
android/bluetooth.c | 13 +++++++++++++
android/bluetooth.h | 2 ++
2 files changed, 15 insertions(+)

diff --git a/android/bluetooth.c b/android/bluetooth.c
index cd1772a..aaba585 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -221,6 +221,8 @@ static GSList *browse_reqs;

static struct ipc *hal_ipc = NULL;

+static bool kernel_conn_control = false;
+
static void get_device_android_addr(struct device *dev, uint8_t *addr)
{
/*
@@ -1489,6 +1491,11 @@ bool bt_device_set_uuids(const bdaddr_t *addr, GSList *uuids)
return true;
}

+bool bt_kernel_conn_control(void)
+{
+ return kernel_conn_control;
+}
+
static bool rssi_above_threshold(int old, int new)
{
/* only 8 dBm or more */
@@ -3268,6 +3275,12 @@ static void read_version_complete(uint8_t status, uint16_t length,
goto failed;
}

+ /* Starting from mgmt 1.7, kernel can handle connection control */
+ if (MGMT_VERSION(mgmt_version, mgmt_revision) >= MGMT_VERSION(1, 7)) {
+ info("Kernel connection control will be used");
+ kernel_conn_control = true;
+ }
+
mgmt_register(mgmt_if, MGMT_EV_INDEX_ADDED, MGMT_INDEX_NONE,
mgmt_index_added_event, cb, NULL);
mgmt_register(mgmt_if, MGMT_EV_INDEX_REMOVED, MGMT_INDEX_NONE,
diff --git a/android/bluetooth.h b/android/bluetooth.h
index e00634c..adad6c4 100644
--- a/android/bluetooth.h
+++ b/android/bluetooth.h
@@ -79,3 +79,5 @@ void bt_store_gatt_ccc(const bdaddr_t *addr, uint16_t value);
uint16_t bt_get_gatt_ccc(const bdaddr_t *addr);

const bdaddr_t *bt_get_id_addr(const bdaddr_t *addr, uint8_t *type);
+
+bool bt_kernel_conn_control(void);
--
1.8.4


2014-08-04 10:34:15

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH v4 2/6] android/bluetooth: Add API to add device to auto connect list

---
android/bluetooth.c | 31 +++++++++++++++++++++++++++++++
android/bluetooth.h | 2 ++
2 files changed, 33 insertions(+)

diff --git a/android/bluetooth.c b/android/bluetooth.c
index aaba585..a4a77c8 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -1496,6 +1496,37 @@ bool bt_kernel_conn_control(void)
return kernel_conn_control;
}

+bool bt_auto_connect_add(const bdaddr_t *addr)
+{
+ struct mgmt_cp_add_device cp;
+ struct device *dev;
+
+ if (!kernel_conn_control)
+ return false;
+
+ dev = find_device(addr);
+ if (!dev)
+ return false;
+
+ if (dev->bdaddr_type == BDADDR_BREDR) {
+ DBG("auto-connection feature is not available for BR/EDR");
+ return false;
+ }
+
+ memset(&cp, 0, sizeof(cp));
+ bacpy(&cp.addr.bdaddr, addr);
+ cp.addr.type = dev->bdaddr_type;
+ cp.action = 0x02;
+
+ if (mgmt_send(mgmt_if, MGMT_OP_ADD_DEVICE, adapter.index, sizeof(cp),
+ &cp, NULL, NULL, NULL) > 0)
+ return true;
+
+ error("Failed to add device");
+
+ return false;
+}
+
static bool rssi_above_threshold(int old, int new)
{
/* only 8 dBm or more */
diff --git a/android/bluetooth.h b/android/bluetooth.h
index adad6c4..4a7063d 100644
--- a/android/bluetooth.h
+++ b/android/bluetooth.h
@@ -81,3 +81,5 @@ uint16_t bt_get_gatt_ccc(const bdaddr_t *addr);
const bdaddr_t *bt_get_id_addr(const bdaddr_t *addr, uint8_t *type);

bool bt_kernel_conn_control(void);
+
+bool bt_auto_connect_add(const bdaddr_t *addr);
--
1.8.4