From f3232cb9994ca6bcf2ac09ff1e26e6dffba2fd4d Mon Sep 17 00:00:00 2001 From: Mariusz Skamra Date: Fri, 17 Jul 2015 13:11:53 +0200 Subject: [PATCH] Bluetooth: Add simple timeout for connection establishment Adds fiber which starts with some specified delay. If the fiber is not cancelled, bt_disconnect is called to cancel creation of connection. Change-Id: I06667d970ba3398f205f19f1d2e76ab6c283f274 Signed-off-by: Mariusz Skamra --- net/bluetooth/Kconfig | 1 + net/bluetooth/conn.c | 13 +++++++++++-- net/bluetooth/conn_internal.h | 10 ++++++++-- net/bluetooth/hci_core.c | 31 ++++++++++++++++++++++++++++++- 4 files changed, 50 insertions(+), 5 deletions(-) diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig index e9e43566bc6..a6ffbde3f1e 100644 --- a/net/bluetooth/Kconfig +++ b/net/bluetooth/Kconfig @@ -34,6 +34,7 @@ config BLUETOOTH bool prompt "Bluetooth LE support [EXPERIMENTAL]" default n + select NANO_TIMEOUTS help This option enables Bluetooth Low Energy support. diff --git a/net/bluetooth/conn.c b/net/bluetooth/conn.c index 4f0dc0c927e..c247c854a7d 100644 --- a/net/bluetooth/conn.c +++ b/net/bluetooth/conn.c @@ -318,8 +318,8 @@ void bt_conn_set_state(struct bt_conn *conn, bt_conn_state_t state) switch (conn->state){ case BT_CONN_CONNECTED: nano_fifo_init(&conn->tx_queue); - fiber_start(conn->tx_stack, sizeof(conn->tx_stack), - conn_tx_fiber, (int)bt_conn_get(conn), 0, 7, 0); + fiber_start(conn->stack, sizeof(conn->stack), conn_tx_fiber, + (int)bt_conn_get(conn), 0, 7, 0); break; case BT_CONN_DISCONNECTED: /* Send dummy buffer to wake up and stop the tx fiber @@ -505,6 +505,15 @@ static int bt_hci_connect_le_cancel(struct bt_conn *conn) { int err; + if (conn->timeout) { + fiber_fiber_delayed_start_cancel(conn->timeout); + + conn->timeout = NULL; + + /* Drop the reference took by timeout fiber */ + bt_conn_put(conn); + } + err = bt_hci_cmd_send(BT_HCI_OP_LE_CREATE_CONN_CANCEL, NULL); if (err) { return err; diff --git a/net/bluetooth/conn_internal.h b/net/bluetooth/conn_internal.h index 77956ed33eb..5b19027331a 100644 --- a/net/bluetooth/conn_internal.h +++ b/net/bluetooth/conn_internal.h @@ -82,8 +82,14 @@ struct bt_conn { bt_conn_state_t state; - /* TX fiber stack */ - BT_STACK(tx_stack, 256); + /* Handle allowing to cancel timeout fiber */ + void *timeout; + + /* Stack for Tx fiber and timeout fiber. + * Since this fibers don't overlap, one stack can be used by both of + * them. + */ + BT_STACK(stack, 256); }; /* Process incoming data for a connection */ diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 05c53ef3970..cf3d9e6161c 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -58,6 +58,8 @@ #define ACL_IN_MAX 7 #define ACL_OUT_MAX 7 +#define BT_CREATE_CONN_TIMEOUT (3 * sys_clock_ticks_per_sec) + /* Stacks for the fibers */ static BT_STACK_NOINIT(rx_fiber_stack, 1024); static BT_STACK_NOINIT(rx_prio_fiber_stack, 256); @@ -329,7 +331,7 @@ static void analyze_stacks(struct bt_conn *conn, struct bt_conn **ref) sizeof(rx_prio_fiber_stack), stack_growth); analyze_stack("cmd tx stack", cmd_tx_fiber_stack, sizeof(cmd_tx_fiber_stack), stack_growth); - analyze_stack("conn tx stack", conn->tx_stack, sizeof(conn->tx_stack), + analyze_stack("conn tx stack", conn->stack, sizeof(conn->stack), stack_growth); } #else @@ -739,6 +741,15 @@ static void le_conn_complete(struct bt_buf *buf) conn = bt_conn_lookup_state(&evt->peer_addr, BT_CONN_CONNECT); } + if (conn && conn->timeout) { + fiber_fiber_delayed_start_cancel(conn->timeout); + + conn->timeout = NULL; + + /* Drop the reference took by timeout fiber */ + bt_conn_put(conn); + } + if (evt->status) { if (!conn) { return; @@ -783,6 +794,17 @@ static void le_conn_complete(struct bt_buf *buf) bt_le_scan_update(); } +static void timeout_fiber(int arg1, int arg2) +{ + struct bt_conn *conn = (struct bt_conn *)arg1; + ARG_UNUSED(arg2); + + conn->timeout = NULL; + + bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); + bt_conn_put(conn); +} + static void check_pending_conn(const bt_addr_le_t *addr, uint8_t evtype, struct bt_keys *keys) { @@ -813,6 +835,13 @@ static void check_pending_conn(const bt_addr_le_t *addr, uint8_t evtype, bt_conn_set_state(conn, BT_CONN_CONNECT); + /* Add LE Create Connection timeout */ + conn->timeout = fiber_fiber_delayed_start(conn->stack, + sizeof(conn->stack), + timeout_fiber, + (int)bt_conn_get(conn), 0, 7, + 0, BT_CREATE_CONN_TIMEOUT); + done: bt_conn_put(conn); }