int bt_le_set_auto_conn(bt_addr_le_t *addr, const struct bt_le_conn_param *param) { struct bt_conn *conn; if (param && !bt_le_conn_params_valid(param->interval_min, param->interval_max, param->latency, param->timeout)) { return -EINVAL; } conn = bt_conn_lookup_addr_le(addr); if (!conn) { conn = bt_conn_add_le(addr); if (!conn) { return -ENOMEM; } } if (param) { bt_conn_set_param_le(conn, param); if (!atomic_test_and_set_bit(conn->flags, BT_CONN_AUTO_CONNECT)) { bt_conn_ref(conn); } } else { if (atomic_test_and_clear_bit(conn->flags, BT_CONN_AUTO_CONNECT)) { bt_conn_unref(conn); if (conn->state == BT_CONN_CONNECT_SCAN) { bt_conn_set_state(conn, BT_CONN_DISCONNECTED); } } } if (conn->state == BT_CONN_DISCONNECTED && atomic_test_bit(bt_dev.flags, BT_DEV_READY)) { if (param) { bt_conn_set_state(conn, BT_CONN_CONNECT_SCAN); } bt_le_scan_update(false); } bt_conn_unref(conn); return 0; }
struct bt_conn *bt_conn_create_le(const bt_addr_le_t *peer, const struct bt_le_conn_param *param) { struct bt_conn *conn; if (!bt_le_conn_params_valid(param->interval_min, param->interval_max, param->latency, param->timeout)) { return NULL; } if (atomic_test_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN)) { return NULL; } conn = bt_conn_lookup_addr_le(peer); if (conn) { switch (conn->state) { case BT_CONN_CONNECT_SCAN: bt_conn_set_param_le(conn, param); return conn; case BT_CONN_CONNECT: case BT_CONN_CONNECTED: return conn; default: bt_conn_unref(conn); return NULL; } } conn = bt_conn_add_le(peer); if (!conn) { return NULL; } bt_conn_set_param_le(conn, param); bt_conn_set_state(conn, BT_CONN_CONNECT_SCAN); bt_le_scan_update(true); return conn; }
void on_nble_gap_connect_evt(const struct nble_gap_connect_evt *evt) { struct bt_conn *conn; /* Make lookup to check if there's a connection object in CONNECT state * associated with passed peer LE address. */ conn = bt_conn_lookup_state_le(&evt->peer_bda, BT_CONN_CONNECT); #if 0 /* Nordic has no connection error */ if (evt->status) { if (!conn) { return; } conn->err = BT_HCI_ERR_UNACCEPT_CONN_PARAMS; bt_conn_set_state(conn, BT_CONN_DISCONNECTED); /* Drop the reference got by lookup call in CONNECT state. * We are now in DISCONNECTED state since no successful LE * link been made. */ bt_conn_unref(conn); return; } #endif /* * clear advertising even if we are not able to add connection object * to keep host in sync with controller state */ if (evt->role_slave == BT_CONN_ROLE_SLAVE) { atomic_clear_bit(bt_dev.flags, BT_DEV_ADVERTISING); } if (!conn) { conn = bt_conn_add_le(&evt->peer_bda); } if (!conn) { BT_DBG("Unable to add new conn for handle %u", evt->conn_handle); return; } conn->handle = evt->conn_handle; bt_addr_le_copy(&conn->le.dst, &evt->peer_bda); conn->le.interval = evt->conn_values.interval; conn->le.latency = evt->conn_values.latency; conn->le.timeout = evt->conn_values.supervision_to; conn->role = evt->role_slave; #if 0 src.type = BT_ADDR_LE_PUBLIC; memcpy(src.val, bt_dev.bdaddr.val, sizeof(bt_dev.bdaddr.val)); /* use connection address (instead of identity address) as initiator * or responder address */ if (conn->role == BT_HCI_ROLE_MASTER) { bt_addr_le_copy(&conn->le.init_addr, &src); bt_addr_le_copy(&conn->le.resp_addr, &evt->peer_addr); } else { bt_addr_le_copy(&conn->le.init_addr, &evt->peer_addr); bt_addr_le_copy(&conn->le.resp_addr, &src); } #endif bt_conn_set_state(conn, BT_CONN_CONNECTED); /* Note: Connection update removed because Windows interop and BT spec recommendations */ bt_conn_unref(conn); #if 0 bt_le_scan_update(false); #endif }