Example #1
1
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);
}
Example #3
0
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);
    }
}
Example #5
0
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();
}
Example #6
0
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;
}
Example #8
0
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;
}
Example #9
0
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;
}
Example #12
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;
}
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);
}
Example #14
0
File: gap.c Project: hudkmr/zephyr
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);
}
Example #15
0
File: gap.c Project: hudkmr/zephyr
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);
}
Example #16
0
File: gap.c Project: hudkmr/zephyr
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);
}
Example #17
0
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;
}