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; }
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); }
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; }
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 struct bt_conn *conn_get(const bt_addr_le_t *peer) { struct bt_conn *conn; if (peer) { conn = bt_conn_lookup_addr_le(peer); if (conn) { return conn; } } return conn_new(); }
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; }
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 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 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; }
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; }
bool BLECharacteristicImp::discoverAttributes(BLEDevice* device) { int err; bt_conn_t* conn; bt_gatt_discover_params_t* temp = NULL; const bt_uuid_t* service_uuid = bt_uuid(); if (service_uuid->type == BT_UUID_TYPE_16) { uint16_t uuid_tmp ;//= ((bt_uuid_16_t*)service_uuid)->val; memcpy(&uuid_tmp, &((bt_uuid_16_t*)service_uuid)->val, sizeof(uuid_tmp)); if (BT_UUID_GAP_VAL == uuid_tmp || BT_UUID_GATT_VAL == uuid_tmp) { return false; } } conn = bt_conn_lookup_addr_le(device->bt_le_address()); if (NULL == conn) { // Link lost pr_debug(LOG_MODULE_BLE, "Can't find connection\n"); return false; } temp = &_discover_params; temp->start_handle = _value_handle + 1; temp->end_handle = _value_handle + 20; // TODO: the max descriptor is not more than 20 temp->uuid = NULL; temp->type = BT_GATT_DISCOVER_DESCRIPTOR; temp->func = profile_discover_process; pr_debug(LOG_MODULE_BLE, "%s-%d-charc",__FUNCTION__, __LINE__); err = bt_gatt_discover(conn, temp); bt_conn_unref(conn); if (err) { pr_debug(LOG_MODULE_BLE, "Discover failed(err %d)\n", err); return false; } return true; }
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; }
bool BLECharacteristic::write(BLEPeripheralHelper &peripheral, const unsigned char value[], uint16_t length) { int retval = 0; bt_conn_t* conn = NULL; conn = bt_conn_lookup_addr_le(peripheral.bt_le_address()); if (NULL == conn) { return false; } // Send read request retval = bt_gatt_write_without_response(conn, peripheral.valueHandle(this), value, length, false); bt_conn_unref(conn); return (0 == retval); }
static void passkey_entry(const uint8_t *data, uint16_t len) { const struct gap_passkey_entry_cmd *cmd = (void *) data; 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; } bt_conn_auth_passkey_entry(conn, sys_le32_to_cpu(cmd->passkey)); bt_conn_unref(conn); status = BTP_STATUS_SUCCESS; rsp: tester_rsp(BTP_SERVICE_ID_GAP, GAP_PASSKEY_ENTRY, CONTROLLER_INDEX, status); }
static void disconnect(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_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN)) { status = BTP_STATUS_FAILED; } else { status = BTP_STATUS_SUCCESS; } bt_conn_unref(conn); rsp: tester_rsp(BTP_SERVICE_ID_GAP, GAP_DISCONNECT, CONTROLLER_INDEX, status); }
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); }
static int cmd_disconnect(int argc, char *argv[]) { struct bt_conn *conn; int err; if (default_conn && argc < 3) { conn = bt_conn_ref(default_conn); } else { bt_addr_le_t addr; 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("Not connected\n"); return 0; } err = bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); if (err) { printk("Disconnection failed (err %d)\n", err); } bt_conn_unref(conn); return 0; }
bool BLECharacteristic::read(BLEPeripheralHelper &peripheral) { int retval = 0; bt_conn_t* conn = NULL; if (_reading) { // Already in reading state return false; } _read_params.func = profile_read_rsp_process; _read_params.handle_count = 1; _read_params.single.handle = peripheral.valueHandle(this); _read_params.single.offset = 0; if (0 == _read_params.single.handle) { // Discover not complete return false; } conn = bt_conn_lookup_addr_le(peripheral.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; }