void on_nble_gap_connect_evt(const struct nble_gap_connect_evt *ev) { struct bt_conn *conn; BT_DBG("handle %u role %u", ev->conn_handle, ev->role_slave); conn = conn_get(&ev->peer_bda); if (!conn) { BT_ERR("Unable to get bt_conn object"); return; } conn->handle = ev->conn_handle; conn->role = ev->role_slave ? BT_CONN_ROLE_SLAVE : BT_CONN_ROLE_MASTER; conn->interval = ev->conn_values.interval; conn->latency = ev->conn_values.latency; conn->timeout = ev->conn_values.supervision_to; bt_addr_le_copy(&conn->dst, &ev->peer_bda); k_delayed_work_init(&conn->update_work, le_conn_update); conn->state = BT_CONN_CONNECTED; notify_connected(conn); /* * Core 4.2 Vol 3, Part C, 9.3.12.2 * The Peripheral device should not perform a Connection Parameter * Update procedure within 5 s after establishing a connection. */ k_delayed_work_submit(&conn->update_work, conn->role == BT_HCI_ROLE_MASTER ? K_NO_WAIT : CONN_UPDATE_TIMEOUT); }
struct bt_keys *bt_keys_get_addr(const bt_addr_le_t *addr) { struct bt_keys *keys; int i; BT_DBG("%s", bt_addr_le_str(addr)); for (i = 0; i < ARRAY_SIZE(key_pool); i++) { keys = &key_pool[i]; if (!bt_addr_le_cmp(&keys->addr, addr)) { return keys; } if (!bt_addr_le_cmp(&keys->addr, BT_ADDR_LE_ANY)) { bt_addr_le_copy(&keys->addr, addr); BT_DBG("created %p for %s", keys, bt_addr_le_str(addr)); return keys; } } BT_DBG("unable to create keys for %s", bt_addr_le_str(addr)); return NULL; }
static void clear_bonds(const bt_addr_le_t *addr) { struct nble_sm_clear_bonds_req params = { { 0 }, }; bt_addr_le_copy(¶ms.addr, addr); nble_sm_clear_bonds_req(¶ms); }
struct bt_conn *bt_conn_create_le(const bt_addr_le_t *peer, const struct bt_le_conn_param *param) { struct nble_gap_connect_req req; struct bt_conn *conn; BT_DBG(""); if (!bt_le_conn_params_valid(param->interval_min, param->interval_max, param->latency, param->timeout)) { return NULL; } conn = bt_conn_lookup_addr_le(peer); if (conn) { return conn; } conn = conn_new(); if (!conn) { BT_ERR("Unable to create new bt_conn object"); return NULL; } /* Update connection parameters */ bt_addr_le_copy(&conn->dst, peer); conn->latency = param->latency; conn->timeout = param->timeout; /* Construct parameters to NBLE */ bt_addr_le_copy(&req.bda, peer); req.conn_params.interval_min = param->interval_min; req.conn_params.interval_max = param->interval_max; req.conn_params.slave_latency = param->latency; req.conn_params.link_sup_to = param->timeout; req.scan_params.interval = BT_GAP_SCAN_FAST_INTERVAL; req.scan_params.window = BT_GAP_SCAN_FAST_WINDOW; conn->state = BT_CONN_CONNECT; nble_gap_connect_req(&req, conn); return conn; }
void on_nble_get_bda_rsp(const struct nble_get_bda_rsp *rsp) { bt_addr_le_copy(&nble.addr, &rsp->bda); BT_DBG("Local bdaddr: %s", bt_addr_le_str(&nble.addr)); nble_get_version_req(NULL); }
int bt_gatt_attr_write_ccc(struct bt_conn *conn, const struct bt_gatt_attr *attr, const void *buf, uint16_t len, uint16_t offset) { struct _bt_gatt_ccc *ccc = attr->user_data; const uint16_t *data = buf; bool bonded; size_t i; if (offset > sizeof(*data)) { return -EINVAL; } if (offset + len > sizeof(*data)) { return -EFBIG; } if (bt_keys_find_addr(&conn->le.dst)) bonded = true; else bonded = false; for (i = 0; i < ccc->cfg_len; i++) { /* Check for existing configuration */ if (!bt_addr_le_cmp(&ccc->cfg[i].peer, &conn->le.dst)) { break; } } if (i == ccc->cfg_len) { for (i = 0; i < ccc->cfg_len; i++) { /* Check for unused configuration */ if (!ccc->cfg[i].valid) { bt_addr_le_copy(&ccc->cfg[i].peer, &conn->le.dst); /* Only set valid if bonded */ ccc->cfg[i].valid = bonded; break; } } if (i == ccc->cfg_len) { BT_WARN("No space to store CCC cfg"); return -ENOMEM; } } ccc->cfg[i].value = sys_le16_to_cpu(*data); BT_DBG("handle 0x%04x value %u", attr->handle, ccc->cfg[i].value); /* Update cfg if don't match */ if (ccc->cfg[i].value != ccc->value) { gatt_ccc_changed(ccc); } return len; }
static void gatt_subscription_add(struct bt_conn *conn, struct bt_gatt_subscribe_params *params) { bt_addr_le_copy(¶ms->_peer, &conn->le.dst); /* Prepend subscription */ params->_next = subscriptions; subscriptions = params; }
static ssize_t storage_write(const bt_addr_le_t *addr, uint16_t key, const void *data, size_t length) { if (addr) { return -ENOENT; } if (key == BT_STORAGE_ID_ADDR && length == sizeof(id_addr)) { bt_addr_le_copy(&id_addr, data); return sizeof(id_addr); } return -EIO; }
static ssize_t storage_read(const bt_addr_le_t *addr, uint16_t key, void *data, size_t length) { if (addr) { return -ENOENT; } if (key == BT_STORAGE_ID_ADDR && length == sizeof(id_addr) && bt_addr_le_cmp(&id_addr, BT_ADDR_LE_ANY)) { bt_addr_le_copy(data, &id_addr); return sizeof(id_addr); } return -EIO; }
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; }
struct bt_conn *bt_conn_add_le(const bt_addr_le_t *peer) { struct bt_conn *conn = conn_new(); if (!conn) { return NULL; } bt_addr_le_copy(&conn->le.dst, peer); #if defined(CONFIG_BLUETOOTH_SMP) conn->sec_level = BT_SECURITY_LOW; conn->required_sec_level = BT_SECURITY_LOW; #endif /* CONFIG_BLUETOOTH_SMP */ conn->type = BT_CONN_TYPE_LE; conn->le.interval_min = BT_GAP_INIT_CONN_INT_MIN; conn->le.interval_max = BT_GAP_INIT_CONN_INT_MAX; return conn; }
void on_nble_gap_connect_evt(const struct nble_gap_connect_evt *ev) { struct bt_conn *conn; BT_DBG("handle %u role %u", ev->conn_handle, ev->role_slave); conn = conn_new(); if (!conn) { BT_ERR("Unable to create new bt_conn object"); return; } conn->handle = ev->conn_handle; conn->role = ev->role_slave; conn->interval = ev->conn_values.interval; conn->latency = ev->conn_values.latency; conn->timeout = ev->conn_values.supervision_to; bt_addr_le_copy(&conn->dst, &ev->peer_bda); conn->state = BT_CONN_CONNECTED; notify_connected(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 }