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; }
void on_nble_sm_pairing_request_evt(const struct nble_sm_pairing_request_evt *evt) { struct bt_conn *conn; struct bt_smp *smp; BT_DBG(""); conn = bt_conn_lookup_handle(evt->conn_handle); if (!conn) { BT_ERR("Unable to find conn for handle %u", evt->conn_handle); return; } smp = smp_chan_get(conn); if (!smp) { BT_ERR("No smp"); bt_conn_unref(conn); return; } atomic_set_bit(&smp->flags, SMP_FLAG_PAIRING); legacy_pairing_req(smp, evt->sec_param.remote_io); bt_conn_unref(conn); }
struct bt_conn *bt_conn_create_br(const bt_addr_t *peer, const struct bt_br_conn_param *param) { struct bt_hci_cp_connect *cp; struct bt_conn *conn; struct net_buf *buf; conn = bt_conn_lookup_addr_br(peer); if (conn) { switch (conn->state) { return conn; case BT_CONN_CONNECT: case BT_CONN_CONNECTED: return conn; default: bt_conn_unref(conn); return NULL; } } conn = bt_conn_add_br(peer); if (!conn) { return NULL; } buf = bt_hci_cmd_create(BT_HCI_OP_CONNECT, sizeof(*cp)); if (!buf) { bt_conn_unref(conn); return NULL; } cp = net_buf_add(buf, sizeof(*cp)); memset(cp, 0, sizeof(*cp)); memcpy(&cp->bdaddr, peer, sizeof(cp->bdaddr)); cp->packet_type = sys_cpu_to_le16(0xcc18); /* DM1 DH1 DM3 DH5 DM5 DH5 */ cp->pscan_rep_mode = 0x02; /* R2 */ cp->allow_role_switch = param->allow_role_switch ? 0x01 : 0x00; cp->clock_offset = 0x0000; /* TODO used cached clock offset */ if (bt_hci_cmd_send_sync(BT_HCI_OP_CONNECT, buf, NULL) < 0) { bt_conn_unref(conn); return NULL; } bt_conn_set_state(conn, BT_CONN_CONNECT); conn->role = BT_CONN_ROLE_MASTER; return conn; }
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(); } }
static int cmd_select(int argc, char *argv[]) { struct bt_conn *conn; bt_addr_le_t addr; int err; if (argc < 3) { return -EINVAL; } err = str2bt_addr_le(argv[1], argv[2], &addr); if (err) { printk("Invalid peer address (err %d)\n", err); return 0; } conn = bt_conn_lookup_addr_le(&addr); if (!conn) { printk("No matching connection found\n"); return 0; } if (default_conn) { bt_conn_unref(default_conn); } default_conn = conn; return 0; }
static int cmd_connect_le(int argc, char *argv[]) { int err; bt_addr_le_t addr; struct bt_conn *conn; if (argc < 3) { return -EINVAL; } err = str2bt_addr_le(argv[1], argv[2], &addr); if (err) { printk("Invalid peer address (err %d)\n", err); return 0; } conn = bt_conn_create_le(&addr, BT_LE_CONN_PARAM_DEFAULT); if (!conn) { printk("Connection failed\n"); } else { printk("Connection pending\n"); /* unref connection obj in advance as app user */ bt_conn_unref(conn); } return 0; }
void on_nble_sm_passkey_disp_evt(const struct nble_sm_passkey_disp_evt *ev) { struct bt_conn *conn; conn = bt_conn_lookup_handle(ev->conn_handle); if (!conn) { BT_ERR("Unable to find conn for handle %u", ev->conn_handle); return; } BT_DBG("conn %p passkey %u", conn, ev->passkey); /* TODO: Check shall we store io_caps globally */ if (get_io_capa() == BT_SMP_IO_DISPLAY_YESNO) { if (nble.auth && nble.auth->passkey_confirm) { nble.auth->passkey_confirm(conn, ev->passkey); } } else { if (nble.auth && nble.auth->passkey_display) { nble.auth->passkey_display(conn, ev->passkey); } } bt_conn_unref(conn); }
bool BLECharacteristicImp::write(const unsigned char value[], uint16_t length) { int retval = 0; bt_conn_t* conn = NULL; if (true == BLEUtils::isLocalBLE(_ble_device)) { // GATT server can't write return false; } conn = bt_conn_lookup_addr_le(_ble_device.bt_le_address()); if (NULL == conn) { return false; } // Send read request retval = bt_gatt_write_without_response(conn, _value_handle, value, length, false); bt_conn_unref(conn); return (0 == retval); }
void on_nble_gap_conn_update_evt(const struct nble_gap_conn_update_evt *evt) { struct bt_conn *conn; uint16_t handle, interval; handle = evt->conn_handle; interval = evt->conn_values.interval; /* BT_DBG("status %u, handle %u", evt->status, handle); */ conn = bt_conn_lookup_handle(handle); if (!conn) { /* BT_ERR("Unable to lookup conn for handle %u", handle); */ return; } /* if (!evt->status) { */ conn->le.interval = interval; conn->le.latency = evt->conn_values.latency; conn->le.timeout = evt->conn_values.supervision_to; notify_le_param_updated(conn); /* } */ bt_conn_unref(conn); }
static uint8_t notify_cb(const struct bt_gatt_attr *attr, void *user_data) { struct notify_data *data = user_data; struct _bt_gatt_ccc *ccc; size_t i; if (bt_uuid_cmp(attr->uuid, BT_UUID_GATT_CCC)) { /* Stop if we reach the next characteristic */ if (!bt_uuid_cmp(attr->uuid, BT_UUID_GATT_CHRC)) { return BT_GATT_ITER_STOP; } return BT_GATT_ITER_CONTINUE; } /* Check attribute user_data must be of type struct _bt_gatt_ccc */ if (attr->write != bt_gatt_attr_write_ccc) { return BT_GATT_ITER_CONTINUE; } ccc = attr->user_data; /* Notify all peers configured */ for (i = 0; i < ccc->cfg_len; i++) { struct bt_conn *conn; /* TODO: Handle indications */ if (ccc->value != BT_GATT_CCC_NOTIFY) { continue; } conn = bt_conn_lookup_addr_le(&ccc->cfg[i].peer); if (!conn || conn->state != BT_CONN_CONNECTED) { continue; } if (att_notify(conn, data->handle, data->data, data->len) < 0) { bt_conn_unref(conn); return BT_GATT_ITER_STOP; } bt_conn_unref(conn); } return BT_GATT_ITER_CONTINUE; }
static void disconnected(struct bt_conn *conn, uint8_t reason) { printk("Disconnected (reason %u)\n", reason); if (default_conn) { bt_conn_unref(default_conn); default_conn = NULL; } }
void on_nble_sm_security_request_evt(const struct nble_sm_security_request_evt *evt) { struct bt_conn *conn; struct bt_smp *smp; BT_DBG(""); conn = bt_conn_lookup_handle(evt->conn_handle); if (!conn) { BT_ERR("Unable to find conn for handle %u", evt->conn_handle); return; } smp = smp_chan_get(conn); if (!smp) { BT_ERR("No smp"); bt_conn_unref(conn); return; } BT_DBG("conn %p remote_io %u mitm %u", conn, evt->sec_param.remote_io, evt->sec_param.mitm); smp->method = legacy_get_pair_method(smp, evt->sec_param.remote_io); if (smp->method == JUST_WORKS && nble.auth && nble.auth->pairing_confirm) { atomic_set_bit(&smp->flags, SMP_FLAG_USER); nble.auth->pairing_confirm(smp->conn); goto done; } if (evt->sec_param.mitm) { bt_conn_security(conn, BT_SECURITY_HIGH); } else { bt_conn_security(conn, BT_SECURITY_MEDIUM); } done: atomic_set_bit(&smp->flags, SMP_FLAG_SEC_REQ); bt_conn_unref(conn); }
void BLEHelper::updateConnectionInterval() { bt_conn_t* conn = bt_conn_lookup_addr_le(&_address); int ret = 0; if (NULL != conn) { ret = bt_conn_le_param_update(conn, &_conn_params); pr_debug(LOG_MODULE_BLE, "%s-ret:%d",__FUNCTION__, ret); bt_conn_unref(conn); } }
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_unref(conn); }
void on_nble_gap_dir_adv_timeout_evt(const struct nble_gap_dir_adv_timeout_evt *p_evt) { struct bt_conn *conn = bt_conn_lookup_state_le(BT_ADDR_LE_ANY, BT_CONN_CONNECT); if (conn) { atomic_clear_bit(bt_dev.flags, BT_DEV_ADVERTISING); conn->err = p_evt->error; bt_conn_set_state(conn, BT_CONN_DISCONNECTED); bt_conn_unref(conn); } }
static void disconnected(struct bt_conn *conn, uint8_t reason) { char addr[BT_ADDR_LE_STR_LEN]; conn_addr_str(conn, addr, sizeof(addr)); printk("Disconnected: %s (reason %u)\n", addr, reason); if (default_conn == conn) { bt_conn_unref(default_conn); default_conn = NULL; } }
void on_nble_gap_disconnect_evt(const struct nble_gap_disconnect_evt *ev) { struct bt_conn *conn; conn = bt_conn_lookup_handle(ev->conn_handle); if (!conn) { BT_ERR("Unable to find conn for handle %u", ev->conn_handle); return; } BT_DBG("conn %p handle %u", conn, ev->conn_handle); conn->state = BT_CONN_DISCONNECTED; notify_disconnected(conn); /* Drop the reference given by lookup_handle() */ bt_conn_unref(conn); /* Drop the initial reference from conn_new() */ bt_conn_unref(conn); }
static void pair(const uint8_t *data, uint16_t len) { struct bt_conn *conn; uint8_t status; conn = bt_conn_lookup_addr_le((bt_addr_le_t *) data); if (!conn) { status = BTP_STATUS_FAILED; goto rsp; } if (bt_conn_security(conn, BT_SECURITY_MEDIUM)) { status = BTP_STATUS_FAILED; bt_conn_unref(conn); goto rsp; } bt_conn_unref(conn); status = BTP_STATUS_SUCCESS; rsp: tester_rsp(BTP_SERVICE_ID_GAP, GAP_PAIR, CONTROLLER_INDEX, status); }
void on_nble_sm_passkey_req_evt(const struct nble_sm_passkey_req_evt *ev) { struct bt_conn *conn; conn = bt_conn_lookup_handle(ev->conn_handle); if (!conn) { BT_ERR("Unable to find conn for handle %u", ev->conn_handle); return; } if (ev->key_type == NBLE_GAP_SM_PK_PASSKEY) { nble.auth->passkey_entry(conn); } bt_conn_unref(conn); }
void on_nble_gap_conn_update_evt(const struct nble_gap_conn_update_evt *ev) { struct bt_conn *conn; conn = bt_conn_lookup_handle(ev->conn_handle); if (!conn) { BT_ERR("Unable to find conn for handle %u", ev->conn_handle); return; } BT_DBG("conn %p handle %u interval %u latency %u to %u", conn, ev->conn_handle, ev->conn_values.interval, ev->conn_values.latency, ev->conn_values.supervision_to); bt_conn_unref(conn); }
bool BLECharacteristicImp::subscribe(void) { int retval = 0; bt_conn_t* conn = NULL; if (true == BLEUtils::isLocalBLE(_ble_device)) { // GATT server can't subscribe return false; } if (_gatt_chrc.properties & BT_GATT_CHRC_NOTIFY) { _sub_params.value |= BT_GATT_CCC_NOTIFY; } if (_gatt_chrc.properties & BT_GATT_CHRC_INDICATE) { _sub_params.value |= BT_GATT_CCC_INDICATE; } if (_sub_params.value == 0) { return false; } conn = bt_conn_lookup_addr_le(_ble_device.bt_le_address()); if (NULL == conn) { return false; } bt_addr_le_copy(&_sub_params._peer, bt_conn_get_dst(conn)); _sub_params.ccc_handle = _cccd_handle; _sub_params.value_handle = _value_handle; // Enable CCCD to allow peripheral send Notification/Indication retval = bt_gatt_subscribe(conn, &_sub_params); bt_conn_unref(conn); if (0 == retval) { _subscribed = true; } return _subscribed; }
static int bt_disconnect(u32_t mgmt_request, struct net_if *iface, void *data, size_t len) { struct bt_context *ctxt = net_if_get_device(iface)->driver_data; if (!ctxt->ipsp_chan.chan.conn) { NET_ERR("Not connected"); return -ENOTCONN; } /* Release connect reference in case of central/router role */ if (default_conn) { bt_conn_unref(default_conn); default_conn = NULL; } return bt_l2cap_chan_disconnect(&ctxt->ipsp_chan.chan); }
static void ipsp_disconnected(struct bt_l2cap_chan *chan) { struct bt_context *ctxt = CHAN_CTXT(chan); NET_DBG("Channel %p disconnected", chan); /* Set iface down */ net_if_down(ctxt->iface); #if defined(CONFIG_NET_L2_BLUETOOTH_MGMT) if (chan->conn != default_conn) { return; } bt_conn_unref(default_conn); default_conn = NULL; #endif }
static void connect(const uint8_t *data, uint16_t len) { struct bt_conn *conn; uint8_t status; conn = bt_conn_create_le((bt_addr_le_t *) data, BT_LE_CONN_PARAM_DEFAULT); if (!conn) { status = BTP_STATUS_FAILED; goto rsp; } bt_conn_unref(conn); status = BTP_STATUS_SUCCESS; rsp: tester_rsp(BTP_SERVICE_ID_GAP, GAP_CONNECT, CONTROLLER_INDEX, status); }
static uint8_t disconnected_cb(const struct bt_gatt_attr *attr, void *user_data) { struct bt_conn *conn = user_data; struct _bt_gatt_ccc *ccc; size_t i; /* Check attribute user_data must be of type struct _bt_gatt_ccc */ if (attr->write != bt_gatt_attr_write_ccc) { return BT_GATT_ITER_CONTINUE; } ccc = attr->user_data; /* If already disabled skip */ if (!ccc->value) { return BT_GATT_ITER_CONTINUE; } for (i = 0; i < ccc->cfg_len; i++) { /* Ignore configurations with disabled value */ if (!ccc->cfg[i].value) { continue; } if (bt_addr_le_cmp(&conn->le.dst, &ccc->cfg[i].peer)) { struct bt_conn *tmp; /* Skip if there is another peer connected */ tmp = bt_conn_lookup_addr_le(&ccc->cfg[i].peer); if (tmp && tmp->state == BT_CONN_CONNECTED) { bt_conn_unref(tmp); return BT_GATT_ITER_CONTINUE; } } } /* Reset value while disconnected */ memset(&ccc->value, 0, sizeof(ccc->value)); ccc->cfg_changed(ccc->value); BT_DBG("ccc %p reseted", ccc); return BT_GATT_ITER_CONTINUE; }
void on_nble_sm_status_evt(const struct nble_sm_status_evt *ev) { struct bt_conn *conn; struct bt_smp *smp; conn = bt_conn_lookup_handle(ev->conn_handle); if (!conn) { BT_ERR("Unable to find conn for handle %u", ev->conn_handle); return; } smp = smp_chan_get(conn); if (!smp) { BT_ERR("No smp for conn %p", conn); return; } BT_DBG("conn %p status %d evt_type %d sec_level %d enc_size %u", conn, ev->status, ev->evt_type, ev->enc_link_sec.sec_level, ev->enc_link_sec.enc_size); switch (ev->evt_type) { case NBLE_GAP_SM_EVT_BONDING_COMPLETE: BT_DBG("Bonding complete"); if (ev->status) { if (nble.auth && nble.auth->cancel) { nble.auth->cancel(conn); } } smp_reset(smp); break; case NBLE_GAP_SM_EVT_LINK_ENCRYPTED: BT_DBG("Link encrypted"); break; case NBLE_GAP_SM_EVT_LINK_SECURITY_CHANGE: BT_DBG("Security change"); break; default: BT_ERR("Unknown event %d", ev->evt_type); break; } bt_conn_unref(conn); }
static void disconnected(struct bt_conn *conn, u8_t reason) { #if defined(CONFIG_NET_DEBUG_L2_BLUETOOTH) char addr[BT_ADDR_LE_STR_LEN]; #endif if (conn != default_conn) { return; } #if defined(CONFIG_NET_DEBUG_L2_BLUETOOTH) bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); NET_DBG("Disconnected: %s (reason %u)\n", addr, reason); #endif bt_conn_unref(default_conn); default_conn = NULL; }
bool BLECharacteristicImp::read() { int retval = 0; bt_conn_t* conn = NULL; if (true == BLEUtils::isLocalBLE(_ble_device)) { // GATT server can't write return false; } if (_reading) { // Already in reading state return false; } _read_params.func = profile_read_rsp_process; _read_params.handle_count = 1; _read_params.single.handle = _value_handle; _read_params.single.offset = 0; if (0 == _read_params.single.handle) { // Discover not complete return false; } conn = bt_conn_lookup_addr_le(_ble_device.bt_le_address()); if (NULL == conn) { return false; } // Send read request retval = bt_gatt_read(conn, &_read_params); bt_conn_unref(conn); if (0 == retval) { _reading = true; } return _reading; }
static int bt_hci_connect_le_cancel(struct bt_conn *conn) { int err; if (conn->timeout) { fiber_delayed_start_cancel(conn->timeout); conn->timeout = NULL; /* Drop the reference took by timeout fiber */ bt_conn_unref(conn); } err = bt_hci_cmd_send(BT_HCI_OP_LE_CREATE_CONN_CANCEL, NULL); if (err) { return err; } return 0; }
bool BLECentralRole::connect(const bt_addr_le_t *addr, const bt_le_conn_param_t *param) { BLEPeripheralHelper* temp = NULL; BLEPeripheralHelper* unused = NULL; bool link_existed = false; bool retval = false; // Find free peripheral Items for (int i = 0; i < BLE_MAX_CONN_CFG; i++) { temp = _peripherial[i]; if (true == *temp) { if (*temp == *addr) { // Connect request has scheduled but connection don't established. // The central can see the ADV and no need to send connect request. link_existed = true; break; } } else { if (NULL == unused) { unused = temp; } } } if (!link_existed) { // Send connect request bt_conn_t* conn = bt_conn_create_le(addr, param); if (NULL != conn) { unused->setAddress(*addr); retval = true; bt_conn_unref(conn); } } return retval; }