Bluetooth: host: Reserve conn object for connecting with whitelist

Reserve a connection object when starting the auto-initiator using the
controller whitelist.

Signed-off-by: Joakim Andersson <joakim.andersson@nordicsemi.no>
This commit is contained in:
Joakim Andersson 2020-01-07 12:40:30 +01:00 committed by Johan Hedberg
commit e9eebf0c40
3 changed files with 43 additions and 9 deletions

View file

@ -117,6 +117,8 @@ static inline const char *state2str(bt_conn_state_t state)
return "connect-scan"; return "connect-scan";
case BT_CONN_CONNECT_DIR_ADV: case BT_CONN_CONNECT_DIR_ADV:
return "connect-dir-adv"; return "connect-dir-adv";
case BT_CONN_CONNECT_AUTO:
return "connect-auto";
case BT_CONN_CONNECT: case BT_CONN_CONNECT:
return "connect"; return "connect";
case BT_CONN_CONNECTED: case BT_CONN_CONNECTED:
@ -1682,7 +1684,11 @@ void bt_conn_set_state(struct bt_conn *conn, bt_conn_state_t state)
notify_connected(conn); notify_connected(conn);
bt_conn_unref(conn); bt_conn_unref(conn);
} else if (old_state == BT_CONN_CONNECT_SCAN) { } else if (old_state == BT_CONN_CONNECT_SCAN) {
/* this indicate LE Create Connection failed */ /* this indicate LE Create Connection with peer address
* has been stopped. This could either be triggered by
* the application through bt_conn_disconnect or by
* timeout set by CONFIG_BT_CREATE_CONN_TIMEOUT.
*/
if (conn->err) { if (conn->err) {
notify_connected(conn); notify_connected(conn);
} }
@ -1695,8 +1701,15 @@ void bt_conn_set_state(struct bt_conn *conn, bt_conn_state_t state)
} }
bt_conn_unref(conn); bt_conn_unref(conn);
} else if (old_state == BT_CONN_CONNECT_AUTO) {
/* this indicates LE Create Connection with filter
* policy has been stopped. This can only be triggered
* by the application, so don't notify.
*/
bt_conn_unref(conn);
} }
break;
case BT_CONN_CONNECT_AUTO:
break; break;
case BT_CONN_CONNECT_SCAN: case BT_CONN_CONNECT_SCAN:
break; break;
@ -2111,17 +2124,32 @@ int bt_conn_create_auto_le(const struct bt_le_conn_param *param)
return -EINVAL; return -EINVAL;
} }
conn = bt_conn_add_le(BT_ID_DEFAULT, BT_ADDR_LE_NONE);
if (!conn) {
return -ENOMEM;
}
bt_conn_set_state(conn, BT_CONN_CONNECT_AUTO);
err = bt_le_auto_conn(param); err = bt_le_auto_conn(param);
if (err) { if (err) {
BT_ERR("Failed to start whitelist scan"); BT_ERR("Failed to start whitelist scan");
bt_conn_set_state(conn, BT_CONN_DISCONNECTED);
bt_conn_unref(conn);
return err; return err;
} }
/* Since we don't give the application a reference to manage in
* this case, we need to release this reference here.
*/
bt_conn_unref(conn);
return 0; return 0;
} }
int bt_conn_create_auto_stop(void) int bt_conn_create_auto_stop(void)
{ {
struct bt_conn *conn;
int err; int err;
if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) { if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) {
@ -2132,6 +2160,12 @@ int bt_conn_create_auto_stop(void)
return -EINVAL; return -EINVAL;
} }
conn = bt_conn_lookup_state_le(BT_ADDR_LE_NONE, BT_CONN_CONNECT_AUTO);
if (conn) {
bt_conn_set_state(conn, BT_CONN_DISCONNECTED);
bt_conn_unref(conn);
}
err = bt_le_auto_conn_cancel(); err = bt_le_auto_conn_cancel();
if (err) { if (err) {
BT_ERR("Failed to stop initiator"); BT_ERR("Failed to stop initiator");

View file

@ -10,6 +10,7 @@
typedef enum __packed { typedef enum __packed {
BT_CONN_DISCONNECTED, BT_CONN_DISCONNECTED,
BT_CONN_CONNECT_SCAN, BT_CONN_CONNECT_SCAN,
BT_CONN_CONNECT_AUTO,
BT_CONN_CONNECT_DIR_ADV, BT_CONN_CONNECT_DIR_ADV,
BT_CONN_CONNECT, BT_CONN_CONNECT,
BT_CONN_CONNECTED, BT_CONN_CONNECTED,

View file

@ -1106,6 +1106,11 @@ static struct bt_conn *find_pending_connect(u8_t role, bt_addr_le_t *peer_addr)
*/ */
if (IS_ENABLED(CONFIG_BT_CENTRAL) && role == BT_HCI_ROLE_MASTER) { if (IS_ENABLED(CONFIG_BT_CENTRAL) && role == BT_HCI_ROLE_MASTER) {
conn = bt_conn_lookup_state_le(peer_addr, BT_CONN_CONNECT); conn = bt_conn_lookup_state_le(peer_addr, BT_CONN_CONNECT);
if (IS_ENABLED(CONFIG_BT_WHITELIST) && !conn) {
conn = bt_conn_lookup_state_le(BT_ADDR_LE_NONE,
BT_CONN_CONNECT_AUTO);
}
return conn; return conn;
} }
@ -1273,16 +1278,10 @@ static void enh_conn_complete(struct bt_hci_evt_le_enh_conn_complete *evt)
if (IS_ENABLED(CONFIG_BT_CENTRAL) && if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
IS_ENABLED(CONFIG_BT_WHITELIST) && IS_ENABLED(CONFIG_BT_WHITELIST) &&
evt->role == BT_HCI_ROLE_MASTER) { evt->role == BT_HCI_ROLE_MASTER) {
/* /* Clear auto conn even if we are not able to add connection
* Clear auto conn even if we are not able to add connection
* object to keep the host in sync with controller state. * object to keep the host in sync with controller state.
*/ */
atomic_clear_bit(bt_dev.flags, BT_DEV_AUTO_CONN); atomic_clear_bit(bt_dev.flags, BT_DEV_AUTO_CONN);
/* for whitelist initiator me may need to add new connection. */
if (!conn) {
conn = bt_conn_add_le(BT_ID_DEFAULT, &id_addr);
}
} }
if (!conn) { if (!conn) {