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; }
int bt_conn_disconnect(struct bt_conn *conn, uint8_t reason) { #if defined(CONFIG_BLUETOOTH_CENTRAL) /* Disconnection is initiated by us, so auto connection shall * be disabled. Otherwise the passive scan would be enabled * and we could send LE Create Connection as soon as the remote * starts advertising. */ if (conn->type == BT_CONN_TYPE_LE) { bt_le_set_auto_conn(&conn->le.dst, NULL); } #endif switch (conn->state) { case BT_CONN_CONNECT_SCAN: bt_conn_set_state(conn, BT_CONN_DISCONNECTED); bt_le_scan_update(false); return 0; case BT_CONN_CONNECT: #if defined(CONFIG_BLUETOOTH_BREDR) if (conn->type == BT_CONN_TYPE_BR) { return bt_hci_connect_br_cancel(conn); } #endif /* CONFIG_BLUETOOTH_BREDR */ return bt_hci_connect_le_cancel(conn); case BT_CONN_CONNECTED: return bt_hci_disconnect(conn, reason); case BT_CONN_DISCONNECT: return 0; case BT_CONN_DISCONNECTED: default: return -ENOTCONN; } }
static int bt_init(void) { #if NOT_USED_FOR_NOW struct bt_driver *drv = bt_dev.drv; #endif int err = 0; #if NOT_USED_FOR_NOW err = drv->open(); if (err) { BT_ERR("HCI driver open failed (%d)", err); return err; } err = hci_init(); #endif if (!err) { err = bt_conn_init(); } scan_dev_found_cb = NULL; if (!err) { atomic_set_bit(bt_dev.flags, BT_DEV_READY); #if 0 bt_le_scan_update(false); #endif } return err; }
void on_nble_gap_disconnect_evt(const struct nble_gap_disconnect_evt *evt) { struct bt_conn *conn; #if 0 /* Nordic has no disconnection error */ if (evt->status) { return; } #endif conn = bt_conn_lookup_handle(evt->conn_handle); if (!conn) { BT_DBG("Unable to look up conn with handle %u", evt->conn_handle); return; } #if 0 /* Check stacks usage (no-ops if not enabled) */ stack_analyze("rx stack", rx_fiber_stack, sizeof(rx_fiber_stack)); stack_analyze("cmd rx stack", rx_prio_fiber_stack, sizeof(rx_prio_fiber_stack)); stack_analyze("cmd tx stack", cmd_tx_fiber_stack, sizeof(cmd_tx_fiber_stack)); stack_analyze("conn tx stack", conn->stack, sizeof(conn->stack)); #endif conn->err = evt->hci_reason; bt_conn_set_state(conn, BT_CONN_DISCONNECTED); conn->handle = 0; #if 0 /* Only LE supported */ if (conn->type != BT_CONN_TYPE_LE) { bt_conn_unref(conn); return; } /* TODO enabled when autoconn is supported */ if (atomic_test_bit(conn->flags, BT_CONN_AUTO_CONNECT)) { bt_conn_set_state(conn, BT_CONN_CONNECT_SCAN); bt_le_scan_update(false); } #endif bt_conn_unref(conn); if (atomic_test_bit(bt_dev.flags, BT_DEV_KEEP_ADVERTISING)) { set_advertise_enable(); } }
int bt_le_scan_stop(void) { #if NOT_USED_FOR_NOW /* Return if active scanning is already disabled */ if (!atomic_test_and_clear_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN)) { return -EALREADY; } #endif scan_dev_found_cb = NULL; #if NOT_USED_FOR_NOW return bt_le_scan_update(false); #else return bt_hci_stop_scanning(); #endif }
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 }