2015-04-14 14:38:13 +03:00
|
|
|
/* hci_core.c - HCI core Bluetooth handling */
|
|
|
|
|
|
|
|
/*
|
2017-03-15 11:19:27 +01:00
|
|
|
* Copyright (c) 2017 Nordic Semiconductor ASA
|
2016-06-10 12:10:18 +03:00
|
|
|
* Copyright (c) 2015-2016 Intel Corporation
|
2015-04-14 14:38:13 +03:00
|
|
|
*
|
2017-01-18 17:01:01 -08:00
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
2015-04-14 14:38:13 +03:00
|
|
|
*/
|
|
|
|
|
2016-10-21 12:04:56 +02:00
|
|
|
#include <zephyr.h>
|
2015-04-14 15:04:46 +03:00
|
|
|
#include <string.h>
|
2015-05-08 20:53:39 +02:00
|
|
|
#include <stdio.h>
|
2015-04-14 15:04:46 +03:00
|
|
|
#include <errno.h>
|
2015-09-15 10:08:04 +02:00
|
|
|
#include <atomic.h>
|
2015-05-21 15:25:14 +03:00
|
|
|
#include <misc/util.h>
|
2017-03-17 08:02:57 +02:00
|
|
|
#include <misc/slist.h>
|
2015-04-14 15:04:46 +03:00
|
|
|
#include <misc/byteorder.h>
|
2016-03-16 09:53:11 +02:00
|
|
|
#include <misc/stack.h>
|
2017-02-07 10:53:40 +01:00
|
|
|
#include <misc/__assert.h>
|
2017-01-30 11:24:48 +01:00
|
|
|
#include <soc.h>
|
2015-04-14 15:04:46 +03:00
|
|
|
|
2015-04-14 14:38:13 +03:00
|
|
|
#include <bluetooth/bluetooth.h>
|
2016-01-14 15:02:54 +02:00
|
|
|
#include <bluetooth/conn.h>
|
2017-05-04 14:09:10 +03:00
|
|
|
#include <bluetooth/l2cap.h>
|
2015-05-25 09:13:33 +03:00
|
|
|
#include <bluetooth/hci.h>
|
2016-10-27 16:55:01 +03:00
|
|
|
#include <bluetooth/hci_driver.h>
|
2016-04-01 21:44:38 +03:00
|
|
|
#include <bluetooth/storage.h>
|
2015-04-14 14:38:13 +03:00
|
|
|
|
2017-05-10 16:27:16 +02:00
|
|
|
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BLUETOOTH_DEBUG_HCI_CORE)
|
|
|
|
#include "common/log.h"
|
|
|
|
|
|
|
|
#include "common/rpa.h"
|
2015-05-30 18:05:26 +07:00
|
|
|
#include "keys.h"
|
2016-04-20 17:54:07 +03:00
|
|
|
#include "monitor.h"
|
2015-11-06 17:04:22 +02:00
|
|
|
#include "hci_core.h"
|
2016-05-24 17:15:03 +02:00
|
|
|
#include "hci_ecc.h"
|
2016-06-30 20:05:36 +03:00
|
|
|
#include "ecc.h"
|
2015-11-06 17:04:22 +02:00
|
|
|
|
2015-06-15 11:05:35 +03:00
|
|
|
#include "conn_internal.h"
|
2015-10-05 13:53:03 +03:00
|
|
|
#include "l2cap_internal.h"
|
2015-10-28 16:02:17 +01:00
|
|
|
#include "smp.h"
|
|
|
|
|
2017-03-15 11:19:27 +01:00
|
|
|
#if defined(CONFIG_BLUETOOTH_HOST_CRYPTO)
|
|
|
|
#include "crypto.h"
|
|
|
|
#endif
|
|
|
|
|
2016-05-23 16:17:20 +03:00
|
|
|
/* Peripheral timeout to initialize Connection Parameter Update procedure */
|
2016-11-13 19:18:39 +02:00
|
|
|
#define CONN_UPDATE_TIMEOUT K_SECONDS(5)
|
|
|
|
#define RPA_TIMEOUT K_SECONDS(CONFIG_BLUETOOTH_RPA_TIMEOUT)
|
2016-05-23 16:17:20 +03:00
|
|
|
|
2017-03-20 22:09:20 -07:00
|
|
|
#define HCI_CMD_TIMEOUT K_SECONDS(10)
|
|
|
|
|
2016-11-10 22:01:50 +02:00
|
|
|
/* Stacks for the threads */
|
2016-12-21 21:09:27 +02:00
|
|
|
#if !defined(CONFIG_BLUETOOTH_RECV_IS_RX_THREAD)
|
2017-05-09 12:00:09 -07:00
|
|
|
static struct k_thread rx_thread_data;
|
2016-11-10 22:01:50 +02:00
|
|
|
static BT_STACK_NOINIT(rx_thread_stack, CONFIG_BLUETOOTH_RX_STACK_SIZE);
|
2016-12-21 21:09:27 +02:00
|
|
|
#endif
|
2017-05-09 12:00:09 -07:00
|
|
|
static struct k_thread tx_thread_data;
|
2017-02-02 14:39:28 +02:00
|
|
|
static BT_STACK_NOINIT(tx_thread_stack, CONFIG_BLUETOOTH_HCI_TX_STACK_SIZE);
|
2015-04-14 15:32:32 +03:00
|
|
|
|
2016-12-21 21:09:27 +02:00
|
|
|
static void init_work(struct k_work *work);
|
|
|
|
|
2016-12-15 09:56:11 +02:00
|
|
|
struct bt_dev bt_dev = {
|
2016-12-21 21:09:27 +02:00
|
|
|
.init = K_WORK_INITIALIZER(init_work),
|
2016-12-15 09:56:11 +02:00
|
|
|
/* Give cmd_sem allowing to send first HCI_Reset cmd, the only
|
|
|
|
* exception is if the controller requests to wait for an
|
|
|
|
* initial Command Complete for NOP.
|
|
|
|
*/
|
|
|
|
#if !defined(CONFIG_BLUETOOTH_WAIT_NOP)
|
|
|
|
.ncmd_sem = K_SEM_INITIALIZER(bt_dev.ncmd_sem, 1, 1),
|
|
|
|
#else
|
|
|
|
.ncmd_sem = K_SEM_INITIALIZER(bt_dev.ncmd_sem, 0, 1),
|
|
|
|
#endif
|
|
|
|
.cmd_tx_queue = K_FIFO_INITIALIZER(bt_dev.cmd_tx_queue),
|
2016-12-21 21:09:27 +02:00
|
|
|
#if !defined(CONFIG_BLUETOOTH_RECV_IS_RX_THREAD)
|
2016-12-15 09:56:11 +02:00
|
|
|
.rx_queue = K_FIFO_INITIALIZER(bt_dev.rx_queue),
|
2016-12-21 21:09:27 +02:00
|
|
|
#endif
|
2016-12-15 09:56:11 +02:00
|
|
|
};
|
2015-04-14 15:32:32 +03:00
|
|
|
|
2016-12-21 21:09:27 +02:00
|
|
|
static bt_ready_cb_t ready_cb;
|
|
|
|
|
2016-04-05 10:14:32 +03:00
|
|
|
const struct bt_storage *bt_storage;
|
2016-04-01 21:44:38 +03:00
|
|
|
|
2015-06-02 17:28:00 +02:00
|
|
|
static bt_le_scan_cb_t *scan_dev_found_cb;
|
2015-06-02 21:12:17 +02:00
|
|
|
|
2017-04-20 12:00:29 -05:00
|
|
|
static u8_t pub_key[64];
|
2016-06-30 20:05:36 +03:00
|
|
|
static struct bt_pub_key_cb *pub_key_cb;
|
|
|
|
static bt_dh_key_cb_t dh_key_cb;
|
|
|
|
|
2016-03-10 11:58:56 +01:00
|
|
|
#if defined(CONFIG_BLUETOOTH_BREDR)
|
|
|
|
static bt_br_discovery_cb_t *discovery_cb;
|
|
|
|
struct bt_br_discovery_result *discovery_results;
|
|
|
|
static size_t discovery_results_size;
|
|
|
|
static size_t discovery_results_count;
|
|
|
|
#endif /* CONFIG_BLUETOOTH_BREDR */
|
|
|
|
|
2015-10-29 17:05:30 +02:00
|
|
|
struct cmd_data {
|
2016-04-09 11:29:50 +03:00
|
|
|
/** BT_BUF_CMD */
|
2017-04-20 12:00:29 -05:00
|
|
|
u8_t type;
|
2016-04-09 11:29:50 +03:00
|
|
|
|
2017-02-01 17:37:14 +02:00
|
|
|
/** HCI status of the command completion */
|
2017-04-20 12:00:29 -05:00
|
|
|
u8_t status;
|
2017-02-01 17:37:14 +02:00
|
|
|
|
2015-10-28 21:14:31 +02:00
|
|
|
/** The command OpCode that the buffer contains */
|
2017-04-20 12:00:29 -05:00
|
|
|
u16_t opcode;
|
2015-10-28 21:14:31 +02:00
|
|
|
|
2017-02-01 17:37:14 +02:00
|
|
|
/** Used by bt_hci_cmd_send_sync. */
|
|
|
|
struct k_sem *sync;
|
2015-10-28 21:14:31 +02:00
|
|
|
};
|
|
|
|
|
2015-10-29 17:05:30 +02:00
|
|
|
struct acl_data {
|
2016-04-09 11:29:50 +03:00
|
|
|
/** BT_BUF_ACL_IN */
|
2017-04-20 12:00:29 -05:00
|
|
|
u8_t type;
|
2016-04-09 11:29:50 +03:00
|
|
|
|
2015-10-28 21:14:31 +02:00
|
|
|
/** ACL connection handle */
|
2017-04-20 12:00:29 -05:00
|
|
|
u16_t handle;
|
2015-10-28 21:14:31 +02:00
|
|
|
};
|
|
|
|
|
2015-10-29 17:05:30 +02:00
|
|
|
#define cmd(buf) ((struct cmd_data *)net_buf_user_data(buf))
|
|
|
|
#define acl(buf) ((struct acl_data *)net_buf_user_data(buf))
|
2015-10-28 20:39:45 +02:00
|
|
|
|
2017-02-01 17:37:14 +02:00
|
|
|
/* HCI command buffers. Derive the needed size from BT_BUF_RX_SIZE since
|
|
|
|
* the same buffer is also used for the response.
|
|
|
|
*/
|
|
|
|
#define CMD_BUF_SIZE BT_BUF_RX_SIZE
|
2016-10-18 23:24:51 +03:00
|
|
|
NET_BUF_POOL_DEFINE(hci_cmd_pool, CONFIG_BLUETOOTH_HCI_CMD_COUNT,
|
|
|
|
CMD_BUF_SIZE, sizeof(struct cmd_data), NULL);
|
2015-10-28 15:14:46 +02:00
|
|
|
|
2016-12-21 17:49:39 +02:00
|
|
|
NET_BUF_POOL_DEFINE(hci_rx_pool, CONFIG_BLUETOOTH_RX_BUF_COUNT,
|
|
|
|
BT_BUF_RX_SIZE, BT_BUF_USER_DATA_MIN, NULL);
|
|
|
|
|
2017-05-04 16:09:53 +02:00
|
|
|
#if defined(CONFIG_BLUETOOTH_HCI_ACL_FLOW_CONTROL)
|
2017-05-04 14:09:10 +03:00
|
|
|
static void report_completed_packet(struct net_buf *buf)
|
|
|
|
{
|
|
|
|
|
|
|
|
struct bt_hci_cp_host_num_completed_packets *cp;
|
|
|
|
u16_t handle = acl(buf)->handle;
|
|
|
|
struct bt_hci_handle_count *hc;
|
|
|
|
|
|
|
|
net_buf_destroy(buf);
|
|
|
|
|
|
|
|
/* Do nothing if controller to host flow control is not supported */
|
|
|
|
if (!(bt_dev.supported_commands[10] & 0x20)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
BT_DBG("Reporting completed packet for handle %u", handle);
|
|
|
|
|
|
|
|
buf = bt_hci_cmd_create(BT_HCI_OP_HOST_NUM_COMPLETED_PACKETS,
|
|
|
|
sizeof(*cp) + sizeof(*hc));
|
|
|
|
if (!buf) {
|
|
|
|
BT_ERR("Unable to allocate new HCI command");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
cp = net_buf_add(buf, sizeof(*cp));
|
|
|
|
cp->num_handles = sys_cpu_to_le16(1);
|
|
|
|
|
|
|
|
hc = net_buf_add(buf, sizeof(*hc));
|
|
|
|
hc->handle = sys_cpu_to_le16(handle);
|
|
|
|
hc->count = sys_cpu_to_le16(1);
|
|
|
|
|
|
|
|
bt_hci_cmd_send(BT_HCI_OP_HOST_NUM_COMPLETED_PACKETS, buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
#define ACL_IN_SIZE BT_L2CAP_BUF_SIZE(CONFIG_BLUETOOTH_L2CAP_RX_MTU)
|
|
|
|
NET_BUF_POOL_DEFINE(acl_in_pool, CONFIG_BLUETOOTH_ACL_RX_COUNT, ACL_IN_SIZE,
|
|
|
|
BT_BUF_USER_DATA_MIN, report_completed_packet);
|
2017-05-04 16:09:53 +02:00
|
|
|
#endif /* CONFIG_BLUETOOTH_HCI_ACL_FLOW_CONTROL */
|
2017-05-04 14:09:10 +03:00
|
|
|
|
2017-04-20 12:00:29 -05:00
|
|
|
struct net_buf *bt_hci_cmd_create(u16_t opcode, u8_t param_len)
|
2015-04-14 15:41:55 +03:00
|
|
|
{
|
|
|
|
struct bt_hci_cmd_hdr *hdr;
|
2015-10-28 10:34:15 +02:00
|
|
|
struct net_buf *buf;
|
2015-04-14 15:41:55 +03:00
|
|
|
|
2016-03-14 12:35:39 +02:00
|
|
|
BT_DBG("opcode 0x%04x param_len %u", opcode, param_len);
|
2015-04-14 15:41:55 +03:00
|
|
|
|
2016-10-18 23:24:51 +03:00
|
|
|
buf = net_buf_alloc(&hci_cmd_pool, K_FOREVER);
|
2017-02-07 10:53:40 +01:00
|
|
|
__ASSERT_NO_MSG(buf);
|
2015-04-14 15:41:55 +03:00
|
|
|
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_DBG("buf %p", buf);
|
2015-04-14 15:41:55 +03:00
|
|
|
|
2017-02-01 12:59:11 +02:00
|
|
|
net_buf_reserve(buf, CONFIG_BLUETOOTH_HCI_RESERVE);
|
2016-10-18 23:24:51 +03:00
|
|
|
|
2016-04-09 11:29:50 +03:00
|
|
|
cmd(buf)->type = BT_BUF_CMD;
|
2015-10-29 17:05:30 +02:00
|
|
|
cmd(buf)->opcode = opcode;
|
|
|
|
cmd(buf)->sync = NULL;
|
2015-04-14 15:41:55 +03:00
|
|
|
|
2015-10-28 10:34:15 +02:00
|
|
|
hdr = net_buf_add(buf, sizeof(*hdr));
|
2015-04-14 15:41:55 +03:00
|
|
|
hdr->opcode = sys_cpu_to_le16(opcode);
|
|
|
|
hdr->param_len = param_len;
|
|
|
|
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
2017-04-20 12:00:29 -05:00
|
|
|
int bt_hci_cmd_send(u16_t opcode, struct net_buf *buf)
|
2015-04-14 15:41:55 +03:00
|
|
|
{
|
|
|
|
if (!buf) {
|
|
|
|
buf = bt_hci_cmd_create(opcode, 0);
|
2015-05-05 10:50:14 +03:00
|
|
|
if (!buf) {
|
2015-04-14 15:41:55 +03:00
|
|
|
return -ENOBUFS;
|
2015-05-05 10:50:14 +03:00
|
|
|
}
|
2015-04-14 15:41:55 +03:00
|
|
|
}
|
|
|
|
|
2016-03-14 12:35:39 +02:00
|
|
|
BT_DBG("opcode 0x%04x len %u", opcode, buf->len);
|
2015-04-14 15:41:55 +03:00
|
|
|
|
2015-04-28 15:22:17 +03:00
|
|
|
/* Host Number of Completed Packets can ignore the ncmd value
|
|
|
|
* and does not generate any cmd complete/status events.
|
|
|
|
*/
|
|
|
|
if (opcode == BT_HCI_OP_HOST_NUM_COMPLETED_PACKETS) {
|
2015-09-15 17:57:00 +03:00
|
|
|
int err;
|
|
|
|
|
2016-04-20 14:46:48 +03:00
|
|
|
err = bt_send(buf);
|
2015-09-15 17:57:00 +03:00
|
|
|
if (err) {
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_ERR("Unable to send to driver (err %d)", err);
|
2015-11-04 21:18:03 +02:00
|
|
|
net_buf_unref(buf);
|
2015-09-15 17:57:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return err;
|
2015-04-28 15:22:17 +03:00
|
|
|
}
|
|
|
|
|
2016-06-05 17:36:46 +03:00
|
|
|
net_buf_put(&bt_dev.cmd_tx_queue, buf);
|
2015-04-14 15:41:55 +03:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-04-20 12:00:29 -05:00
|
|
|
int bt_hci_cmd_send_sync(u16_t opcode, struct net_buf *buf,
|
2015-10-28 10:34:15 +02:00
|
|
|
struct net_buf **rsp)
|
2015-04-14 15:44:48 +03:00
|
|
|
{
|
2016-10-27 11:32:30 +02:00
|
|
|
struct k_sem sync_sem;
|
2015-04-30 12:01:48 +03:00
|
|
|
int err;
|
2015-04-14 15:44:48 +03:00
|
|
|
|
|
|
|
if (!buf) {
|
|
|
|
buf = bt_hci_cmd_create(opcode, 0);
|
2015-05-05 10:50:14 +03:00
|
|
|
if (!buf) {
|
2015-04-14 15:44:48 +03:00
|
|
|
return -ENOBUFS;
|
2015-05-05 10:50:14 +03:00
|
|
|
}
|
2015-04-14 15:44:48 +03:00
|
|
|
}
|
|
|
|
|
2017-02-01 17:37:14 +02:00
|
|
|
BT_DBG("buf %p opcode 0x%04x len %u", buf, opcode, buf->len);
|
2015-04-14 15:44:48 +03:00
|
|
|
|
2016-10-27 11:32:30 +02:00
|
|
|
k_sem_init(&sync_sem, 0, 1);
|
2015-10-29 17:05:30 +02:00
|
|
|
cmd(buf)->sync = &sync_sem;
|
2015-04-14 15:44:48 +03:00
|
|
|
|
2017-02-01 17:37:14 +02:00
|
|
|
/* Make sure the buffer stays around until the command completes */
|
|
|
|
net_buf_ref(buf);
|
|
|
|
|
2016-06-05 17:36:46 +03:00
|
|
|
net_buf_put(&bt_dev.cmd_tx_queue, buf);
|
2015-04-14 15:44:48 +03:00
|
|
|
|
2017-03-20 22:09:20 -07:00
|
|
|
err = k_sem_take(&sync_sem, HCI_CMD_TIMEOUT);
|
|
|
|
__ASSERT(err == 0, "k_sem_take failed with err %d", err);
|
2015-04-14 15:44:48 +03:00
|
|
|
|
2017-02-01 17:37:14 +02:00
|
|
|
BT_DBG("opcode 0x%04x status 0x%02x", opcode, cmd(buf)->status);
|
|
|
|
|
|
|
|
if (cmd(buf)->status) {
|
2015-04-30 12:01:48 +03:00
|
|
|
err = -EIO;
|
2017-02-01 17:37:14 +02:00
|
|
|
net_buf_unref(buf);
|
2015-05-05 10:50:14 +03:00
|
|
|
} else {
|
2015-04-30 12:01:48 +03:00
|
|
|
err = 0;
|
2017-02-01 17:37:14 +02:00
|
|
|
if (rsp) {
|
|
|
|
*rsp = buf;
|
|
|
|
} else {
|
|
|
|
net_buf_unref(buf);
|
|
|
|
}
|
2015-05-05 10:50:14 +03:00
|
|
|
}
|
2015-04-30 12:01:48 +03:00
|
|
|
|
|
|
|
return err;
|
2015-04-14 15:44:48 +03:00
|
|
|
}
|
|
|
|
|
2015-10-01 17:50:19 +02:00
|
|
|
static int bt_hci_stop_scanning(void)
|
|
|
|
{
|
2015-10-28 10:34:15 +02:00
|
|
|
struct net_buf *buf, *rsp;
|
2015-10-01 17:50:19 +02:00
|
|
|
struct bt_hci_cp_le_set_scan_enable *scan_enable;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (!atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING)) {
|
|
|
|
return -EALREADY;
|
|
|
|
}
|
|
|
|
|
|
|
|
buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_SCAN_ENABLE,
|
|
|
|
sizeof(*scan_enable));
|
|
|
|
if (!buf) {
|
|
|
|
return -ENOBUFS;
|
|
|
|
}
|
|
|
|
|
2015-10-28 10:34:15 +02:00
|
|
|
scan_enable = net_buf_add(buf, sizeof(*scan_enable));
|
2015-11-30 13:15:04 +02:00
|
|
|
memset(scan_enable, 0, sizeof(*scan_enable));
|
2015-12-04 13:22:18 +02:00
|
|
|
scan_enable->filter_dup = BT_HCI_LE_SCAN_FILTER_DUP_DISABLE;
|
|
|
|
scan_enable->enable = BT_HCI_LE_SCAN_DISABLE;
|
2015-10-01 17:50:19 +02:00
|
|
|
|
|
|
|
err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_SCAN_ENABLE, buf, &rsp);
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Update scan state in case of success (0) status */
|
|
|
|
err = rsp->data[0];
|
|
|
|
if (!err) {
|
|
|
|
atomic_clear_bit(bt_dev.flags, BT_DEV_SCANNING);
|
2016-07-14 15:30:38 +02:00
|
|
|
atomic_clear_bit(bt_dev.flags, BT_DEV_ACTIVE_SCAN);
|
2015-10-01 17:50:19 +02:00
|
|
|
}
|
|
|
|
|
2015-10-28 10:34:15 +02:00
|
|
|
net_buf_unref(rsp);
|
2015-10-01 17:50:19 +02:00
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2015-10-01 18:21:40 +02:00
|
|
|
static const bt_addr_le_t *find_id_addr(const bt_addr_le_t *addr)
|
|
|
|
{
|
2017-01-17 14:28:01 +02:00
|
|
|
if (IS_ENABLED(CONFIG_BLUETOOTH_SMP)) {
|
|
|
|
struct bt_keys *keys;
|
2015-10-01 18:21:40 +02:00
|
|
|
|
2017-01-17 14:28:01 +02:00
|
|
|
keys = bt_keys_find_irk(addr);
|
|
|
|
if (keys) {
|
|
|
|
BT_DBG("Identity %s matched RPA %s",
|
|
|
|
bt_addr_le_str(&keys->addr),
|
|
|
|
bt_addr_le_str(addr));
|
|
|
|
return &keys->addr;
|
|
|
|
}
|
2015-10-01 18:21:40 +02:00
|
|
|
}
|
2017-01-17 14:28:01 +02:00
|
|
|
|
2015-10-01 18:21:40 +02:00
|
|
|
return addr;
|
|
|
|
}
|
|
|
|
|
2016-08-27 11:11:30 +02:00
|
|
|
static int set_advertise_enable(bool enable)
|
2016-02-17 09:43:04 +01:00
|
|
|
{
|
|
|
|
struct net_buf *buf;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADV_ENABLE, 1);
|
|
|
|
if (!buf) {
|
|
|
|
return -ENOBUFS;
|
|
|
|
}
|
|
|
|
|
2016-08-27 11:11:30 +02:00
|
|
|
if (enable) {
|
|
|
|
net_buf_add_u8(buf, BT_HCI_LE_ADV_ENABLE);
|
|
|
|
} else {
|
|
|
|
net_buf_add_u8(buf, BT_HCI_LE_ADV_DISABLE);
|
2016-02-17 09:43:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_ADV_ENABLE, buf, NULL);
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2016-08-27 11:11:30 +02:00
|
|
|
if (enable) {
|
|
|
|
atomic_set_bit(bt_dev.flags, BT_DEV_ADVERTISING);
|
|
|
|
} else {
|
|
|
|
atomic_clear_bit(bt_dev.flags, BT_DEV_ADVERTISING);
|
|
|
|
}
|
|
|
|
|
2016-02-17 09:43:04 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-04-04 12:55:11 +03:00
|
|
|
static int set_random_address(const bt_addr_t *addr)
|
|
|
|
{
|
|
|
|
struct net_buf *buf;
|
2016-04-21 15:39:24 +02:00
|
|
|
int err;
|
2016-04-04 12:55:11 +03:00
|
|
|
|
2016-06-06 05:49:06 +02:00
|
|
|
BT_DBG("%s", bt_addr_str(addr));
|
|
|
|
|
2016-04-04 20:56:45 +03:00
|
|
|
/* Do nothing if we already have the right address */
|
|
|
|
if (!bt_addr_cmp(addr, &bt_dev.random_addr.a)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-04-04 12:55:11 +03:00
|
|
|
buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_RANDOM_ADDRESS, sizeof(*addr));
|
|
|
|
if (!buf) {
|
|
|
|
return -ENOBUFS;
|
|
|
|
}
|
|
|
|
|
2016-12-27 11:52:47 +02:00
|
|
|
net_buf_add_mem(buf, addr, sizeof(*addr));
|
2016-04-04 12:55:11 +03:00
|
|
|
|
2016-04-21 15:39:24 +02:00
|
|
|
err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_RANDOM_ADDRESS, buf, NULL);
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
bt_addr_copy(&bt_dev.random_addr.a, addr);
|
|
|
|
bt_dev.random_addr.type = BT_ADDR_LE_RANDOM;
|
|
|
|
return 0;
|
2016-04-04 12:55:11 +03:00
|
|
|
}
|
|
|
|
|
2016-07-19 11:55:21 +02:00
|
|
|
#if defined(CONFIG_BLUETOOTH_PRIVACY)
|
|
|
|
/* this function sets new RPA only if current one is no longer valid */
|
2017-01-17 14:28:01 +02:00
|
|
|
static int le_set_private_addr(void)
|
2016-07-19 11:55:21 +02:00
|
|
|
{
|
|
|
|
bt_addr_t rpa;
|
|
|
|
int err;
|
|
|
|
|
2016-09-13 13:49:53 +03:00
|
|
|
/* check if RPA is valid */
|
|
|
|
if (atomic_test_bit(bt_dev.flags, BT_DEV_RPA_VALID)) {
|
2016-07-19 11:55:21 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-05-10 16:27:16 +02:00
|
|
|
err = bt_rpa_create(bt_dev.irk, &rpa);
|
2016-07-19 11:55:21 +02:00
|
|
|
if (!err) {
|
|
|
|
err = set_random_address(&rpa);
|
2016-09-13 13:49:53 +03:00
|
|
|
if (!err) {
|
|
|
|
atomic_set_bit(bt_dev.flags, BT_DEV_RPA_VALID);
|
|
|
|
}
|
2016-07-19 11:55:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* restart timer even if failed to set new RPA */
|
2016-11-10 14:20:02 +02:00
|
|
|
k_delayed_work_submit(&bt_dev.rpa_update, RPA_TIMEOUT);
|
2016-07-19 11:55:21 +02:00
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2016-11-10 14:20:02 +02:00
|
|
|
static void rpa_timeout(struct k_work *work)
|
2016-07-19 11:55:21 +02:00
|
|
|
{
|
|
|
|
BT_DBG("");
|
|
|
|
|
2016-09-13 13:49:53 +03:00
|
|
|
/* Invalidate RPA */
|
|
|
|
atomic_clear_bit(bt_dev.flags, BT_DEV_RPA_VALID);
|
|
|
|
|
2016-07-19 11:55:21 +02:00
|
|
|
/*
|
|
|
|
* we need to update rpa only if advertising is ongoing, with
|
|
|
|
* BT_DEV_KEEP_ADVERTISING flag is handled in disconnected event
|
|
|
|
*/
|
|
|
|
if (atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING)) {
|
|
|
|
/* make sure new address is used */
|
2016-08-27 11:11:30 +02:00
|
|
|
set_advertise_enable(false);
|
2017-01-17 14:28:01 +02:00
|
|
|
le_set_private_addr();
|
2016-08-27 11:11:30 +02:00
|
|
|
set_advertise_enable(true);
|
2016-07-19 11:55:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (atomic_test_bit(bt_dev.flags, BT_DEV_ACTIVE_SCAN)) {
|
|
|
|
/* TODO do we need to toggle scan? */
|
2017-01-17 14:28:01 +02:00
|
|
|
le_set_private_addr();
|
2016-07-19 11:55:21 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
2017-01-17 14:28:01 +02:00
|
|
|
static int le_set_private_addr(void)
|
2016-07-19 11:55:21 +02:00
|
|
|
{
|
|
|
|
bt_addr_t nrpa;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = bt_rand(nrpa.val, sizeof(nrpa.val));
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
nrpa.val[5] &= 0x3f;
|
|
|
|
|
|
|
|
return set_random_address(&nrpa);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2015-09-07 18:25:59 +02:00
|
|
|
#if defined(CONFIG_BLUETOOTH_CONN)
|
2015-10-28 10:34:15 +02:00
|
|
|
static void hci_acl(struct net_buf *buf)
|
2015-04-14 15:41:55 +03:00
|
|
|
{
|
2015-04-14 15:44:48 +03:00
|
|
|
struct bt_hci_acl_hdr *hdr = (void *)buf->data;
|
2017-04-20 12:00:29 -05:00
|
|
|
u16_t handle, len = sys_le16_to_cpu(hdr->len);
|
2015-04-28 10:39:50 +03:00
|
|
|
struct bt_conn *conn;
|
2017-04-20 12:00:29 -05:00
|
|
|
u8_t flags;
|
2015-04-14 15:44:48 +03:00
|
|
|
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_DBG("buf %p", buf);
|
2015-05-20 13:14:37 +03:00
|
|
|
|
2015-04-14 15:44:48 +03:00
|
|
|
handle = sys_le16_to_cpu(hdr->handle);
|
2015-11-03 13:42:44 +02:00
|
|
|
flags = bt_acl_flags(handle);
|
2015-10-28 10:20:43 +02:00
|
|
|
|
2015-10-29 17:05:30 +02:00
|
|
|
acl(buf)->handle = bt_acl_handle(handle);
|
2015-04-14 15:44:48 +03:00
|
|
|
|
2015-10-28 10:34:15 +02:00
|
|
|
net_buf_pull(buf, sizeof(*hdr));
|
2015-04-14 15:44:48 +03:00
|
|
|
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_DBG("handle %u len %u flags %u", acl(buf)->handle, len, flags);
|
2015-04-14 15:44:48 +03:00
|
|
|
|
|
|
|
if (buf->len != len) {
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_ERR("ACL data length mismatch (%u != %u)", buf->len, len);
|
2015-10-28 10:34:15 +02:00
|
|
|
net_buf_unref(buf);
|
2015-04-14 15:44:48 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-10-29 17:05:30 +02:00
|
|
|
conn = bt_conn_lookup_handle(acl(buf)->handle);
|
2015-07-08 11:00:26 +03:00
|
|
|
if (!conn) {
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_ERR("Unable to find conn for handle %u", acl(buf)->handle);
|
2015-10-28 10:34:15 +02:00
|
|
|
net_buf_unref(buf);
|
2015-04-28 10:39:50 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
bt_conn_recv(conn, buf, flags);
|
2015-10-23 12:45:33 +03:00
|
|
|
bt_conn_unref(conn);
|
2015-04-14 15:41:55 +03:00
|
|
|
}
|
|
|
|
|
2015-10-28 10:34:15 +02:00
|
|
|
static void hci_num_completed_packets(struct net_buf *buf)
|
2015-04-18 11:56:00 +03:00
|
|
|
{
|
|
|
|
struct bt_hci_evt_num_completed_packets *evt = (void *)buf->data;
|
2017-04-20 12:00:29 -05:00
|
|
|
u16_t i, num_handles = sys_le16_to_cpu(evt->num_handles);
|
2015-04-18 11:56:00 +03:00
|
|
|
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_DBG("num_handles %u", num_handles);
|
2015-04-18 11:56:00 +03:00
|
|
|
|
|
|
|
for (i = 0; i < num_handles; i++) {
|
2017-04-20 12:00:29 -05:00
|
|
|
u16_t handle, count;
|
2015-09-15 17:19:45 +03:00
|
|
|
struct bt_conn *conn;
|
2017-02-01 14:57:07 +02:00
|
|
|
unsigned int key;
|
2015-04-18 11:56:00 +03:00
|
|
|
|
|
|
|
handle = sys_le16_to_cpu(evt->h[i].handle);
|
|
|
|
count = sys_le16_to_cpu(evt->h[i].count);
|
|
|
|
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_DBG("handle %u count %u", handle, count);
|
2015-04-18 11:56:00 +03:00
|
|
|
|
2016-11-10 22:45:08 +02:00
|
|
|
key = irq_lock();
|
|
|
|
|
2015-09-15 17:19:45 +03:00
|
|
|
conn = bt_conn_lookup_handle(handle);
|
2015-09-17 11:22:00 +03:00
|
|
|
if (!conn) {
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_ERR("No connection for handle %u", handle);
|
2016-11-10 22:45:08 +02:00
|
|
|
irq_unlock(key);
|
2015-09-17 11:22:00 +03:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2016-11-10 22:45:08 +02:00
|
|
|
irq_unlock(key);
|
|
|
|
|
2015-09-15 17:19:45 +03:00
|
|
|
while (count--) {
|
2017-03-17 08:02:57 +02:00
|
|
|
sys_snode_t *node;
|
|
|
|
|
|
|
|
key = irq_lock();
|
|
|
|
node = sys_slist_get(&conn->tx_pending);
|
|
|
|
irq_unlock(key);
|
|
|
|
|
|
|
|
if (!node) {
|
|
|
|
BT_ERR("packets count mismatch");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
k_fifo_put(&conn->tx_notify, node);
|
2016-10-27 11:32:30 +02:00
|
|
|
k_sem_give(bt_conn_get_pkts(conn));
|
2015-09-15 17:19:45 +03:00
|
|
|
}
|
2015-11-19 12:01:58 +01:00
|
|
|
|
|
|
|
bt_conn_unref(conn);
|
2015-04-18 11:56:00 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-05 15:32:58 +02:00
|
|
|
static int hci_le_create_conn(const struct bt_conn *conn)
|
2015-06-01 09:22:36 +07:00
|
|
|
{
|
2015-10-28 10:34:15 +02:00
|
|
|
struct net_buf *buf;
|
2015-10-01 17:50:19 +02:00
|
|
|
struct bt_hci_cp_le_create_conn *cp;
|
2015-06-01 09:22:36 +07:00
|
|
|
|
2015-10-01 17:50:19 +02:00
|
|
|
buf = bt_hci_cmd_create(BT_HCI_OP_LE_CREATE_CONN, sizeof(*cp));
|
|
|
|
if (!buf) {
|
|
|
|
return -ENOBUFS;
|
|
|
|
}
|
2015-06-01 09:22:36 +07:00
|
|
|
|
2015-10-28 10:34:15 +02:00
|
|
|
cp = net_buf_add(buf, sizeof(*cp));
|
2015-11-30 13:15:04 +02:00
|
|
|
memset(cp, 0, sizeof(*cp));
|
2015-11-30 13:12:39 +02:00
|
|
|
|
|
|
|
/* Interval == window for continuous scanning */
|
2015-12-04 13:35:55 +02:00
|
|
|
cp->scan_interval = sys_cpu_to_le16(BT_GAP_SCAN_FAST_INTERVAL);
|
2015-11-30 13:12:39 +02:00
|
|
|
cp->scan_window = cp->scan_interval;
|
|
|
|
|
2015-12-05 15:32:58 +02:00
|
|
|
bt_addr_le_copy(&cp->peer_addr, &conn->le.resp_addr);
|
2016-04-02 09:42:08 +03:00
|
|
|
cp->own_addr_type = conn->le.init_addr.type;
|
2015-12-05 15:32:58 +02:00
|
|
|
cp->conn_interval_min = sys_cpu_to_le16(conn->le.interval_min);
|
|
|
|
cp->conn_interval_max = sys_cpu_to_le16(conn->le.interval_max);
|
2015-12-05 21:39:44 +02:00
|
|
|
cp->conn_latency = sys_cpu_to_le16(conn->le.latency);
|
|
|
|
cp->supervision_timeout = sys_cpu_to_le16(conn->le.timeout);
|
2015-10-01 17:50:19 +02:00
|
|
|
|
|
|
|
return bt_hci_cmd_send_sync(BT_HCI_OP_LE_CREATE_CONN, buf, NULL);
|
|
|
|
}
|
|
|
|
|
2015-10-28 10:34:15 +02:00
|
|
|
static void hci_disconn_complete(struct net_buf *buf)
|
2015-10-01 17:50:19 +02:00
|
|
|
{
|
|
|
|
struct bt_hci_evt_disconn_complete *evt = (void *)buf->data;
|
2017-04-20 12:00:29 -05:00
|
|
|
u16_t handle = sys_le16_to_cpu(evt->handle);
|
2015-10-01 17:50:19 +02:00
|
|
|
struct bt_conn *conn;
|
|
|
|
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_DBG("status %u handle %u reason %u", evt->status, handle,
|
2015-10-01 17:50:19 +02:00
|
|
|
evt->reason);
|
2015-06-01 09:22:36 +07:00
|
|
|
|
|
|
|
if (evt->status) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
conn = bt_conn_lookup_handle(handle);
|
2015-07-08 11:00:26 +03:00
|
|
|
if (!conn) {
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_ERR("Unable to look up conn with handle %u", handle);
|
2016-06-01 13:23:50 +02:00
|
|
|
goto advertise;
|
2015-06-01 09:22:36 +07:00
|
|
|
}
|
|
|
|
|
2016-01-14 11:17:32 +02:00
|
|
|
conn->err = evt->reason;
|
|
|
|
|
2015-10-01 17:50:19 +02:00
|
|
|
/* Check stacks usage (no-ops if not enabled) */
|
2016-12-21 21:09:27 +02:00
|
|
|
#if !defined(CONFIG_BLUETOOTH_RECV_IS_RX_THREAD)
|
2016-11-10 22:01:50 +02:00
|
|
|
stack_analyze("rx stack", rx_thread_stack, sizeof(rx_thread_stack));
|
2016-12-21 21:09:27 +02:00
|
|
|
#endif
|
2017-02-02 14:39:28 +02:00
|
|
|
stack_analyze("tx stack", tx_thread_stack,
|
|
|
|
sizeof(tx_thread_stack));
|
2015-06-01 09:22:36 +07:00
|
|
|
|
2015-10-01 17:50:19 +02:00
|
|
|
bt_conn_set_state(conn, BT_CONN_DISCONNECTED);
|
|
|
|
conn->handle = 0;
|
2015-06-01 00:20:14 +07:00
|
|
|
|
2015-12-04 13:02:51 +01:00
|
|
|
if (conn->type != BT_CONN_TYPE_LE) {
|
2016-03-04 14:50:29 +01:00
|
|
|
#if defined(CONFIG_BLUETOOTH_BREDR)
|
2017-02-15 15:18:13 +05:30
|
|
|
if (conn->type == BT_CONN_TYPE_SCO) {
|
|
|
|
bt_sco_cleanup(conn);
|
|
|
|
return;
|
|
|
|
}
|
2016-03-04 14:50:29 +01:00
|
|
|
/*
|
|
|
|
* If only for one connection session bond was set, clear keys
|
|
|
|
* database row for this connection.
|
|
|
|
*/
|
|
|
|
if (conn->type == BT_CONN_TYPE_BR &&
|
|
|
|
atomic_test_and_clear_bit(conn->flags, BT_CONN_BR_NOBOND)) {
|
2016-08-08 16:40:30 +02:00
|
|
|
bt_keys_link_key_clear(conn->br.link_key);
|
2016-03-04 14:50:29 +01:00
|
|
|
}
|
|
|
|
#endif
|
2015-12-04 13:02:51 +01:00
|
|
|
bt_conn_unref(conn);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-10-01 17:50:19 +02:00
|
|
|
if (atomic_test_bit(conn->flags, BT_CONN_AUTO_CONNECT)) {
|
|
|
|
bt_conn_set_state(conn, BT_CONN_CONNECT_SCAN);
|
2015-12-03 22:51:16 +02:00
|
|
|
bt_le_scan_update(false);
|
2015-07-13 12:43:02 +02:00
|
|
|
}
|
|
|
|
|
2015-10-23 12:45:33 +03:00
|
|
|
bt_conn_unref(conn);
|
2015-07-13 12:39:42 +02:00
|
|
|
|
2016-06-01 13:23:50 +02:00
|
|
|
advertise:
|
2016-08-27 11:11:30 +02:00
|
|
|
if (atomic_test_bit(bt_dev.flags, BT_DEV_KEEP_ADVERTISING) &&
|
|
|
|
!atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING)) {
|
2017-01-17 14:28:01 +02:00
|
|
|
if (IS_ENABLED(CONFIG_BLUETOOTH_PRIVACY)) {
|
|
|
|
le_set_private_addr();
|
|
|
|
}
|
|
|
|
|
2016-08-27 11:11:30 +02:00
|
|
|
set_advertise_enable(true);
|
2015-07-13 12:39:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-27 17:28:59 +03:00
|
|
|
static int hci_le_read_remote_features(struct bt_conn *conn)
|
|
|
|
{
|
|
|
|
struct bt_hci_cp_le_read_remote_features *cp;
|
2015-10-28 10:34:15 +02:00
|
|
|
struct net_buf *buf;
|
2015-07-27 17:28:59 +03:00
|
|
|
|
|
|
|
buf = bt_hci_cmd_create(BT_HCI_OP_LE_READ_REMOTE_FEATURES,
|
|
|
|
sizeof(*cp));
|
|
|
|
if (!buf) {
|
|
|
|
return -ENOBUFS;
|
|
|
|
}
|
|
|
|
|
2015-10-28 10:34:15 +02:00
|
|
|
cp = net_buf_add(buf, sizeof(*cp));
|
2015-07-27 17:28:59 +03:00
|
|
|
cp->handle = sys_cpu_to_le16(conn->handle);
|
|
|
|
bt_hci_cmd_send(BT_HCI_OP_LE_READ_REMOTE_FEATURES, buf);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-05-15 23:18:08 +02:00
|
|
|
static int hci_le_set_data_len(struct bt_conn *conn)
|
|
|
|
{
|
|
|
|
struct bt_hci_rp_le_read_max_data_len *rp;
|
|
|
|
struct bt_hci_cp_le_set_data_len *cp;
|
|
|
|
struct net_buf *buf, *rsp;
|
|
|
|
u16_t tx_octets, tx_time;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_READ_MAX_DATA_LEN, NULL, &rsp);
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
rp = (void *)rsp->data;
|
|
|
|
tx_octets = sys_le16_to_cpu(rp->max_tx_octets);
|
|
|
|
tx_time = sys_le16_to_cpu(rp->max_tx_time);
|
|
|
|
net_buf_unref(rsp);
|
|
|
|
|
|
|
|
buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_DATA_LEN, sizeof(*cp));
|
|
|
|
if (!buf) {
|
|
|
|
return -ENOBUFS;
|
|
|
|
}
|
|
|
|
|
|
|
|
cp = net_buf_add(buf, sizeof(*cp));
|
|
|
|
cp->handle = sys_cpu_to_le16(conn->handle);
|
|
|
|
cp->tx_octets = sys_cpu_to_le16(tx_octets);
|
|
|
|
cp->tx_time = sys_cpu_to_le16(tx_time);
|
|
|
|
err = bt_hci_cmd_send(BT_HCI_OP_LE_SET_DATA_LEN, buf);
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-05-06 07:10:50 +02:00
|
|
|
static int hci_le_set_phy(struct bt_conn *conn)
|
|
|
|
{
|
|
|
|
struct bt_hci_cp_le_set_phy *cp;
|
|
|
|
struct net_buf *buf;
|
|
|
|
|
|
|
|
buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_PHY, sizeof(*cp));
|
|
|
|
if (!buf) {
|
|
|
|
return -ENOBUFS;
|
|
|
|
}
|
|
|
|
|
|
|
|
cp = net_buf_add(buf, sizeof(*cp));
|
|
|
|
cp->handle = sys_cpu_to_le16(conn->handle);
|
|
|
|
cp->all_phys = 0;
|
|
|
|
cp->tx_phys = BT_HCI_LE_PHY_PREFER_2M;
|
|
|
|
cp->rx_phys = BT_HCI_LE_PHY_PREFER_2M;
|
|
|
|
cp->phy_opts = BT_HCI_LE_PHY_CODED_ANY;
|
|
|
|
bt_hci_cmd_send(BT_HCI_OP_LE_SET_PHY, buf);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-05-23 16:17:20 +03:00
|
|
|
static void update_conn_param(struct bt_conn *conn)
|
2015-08-10 21:53:45 +02:00
|
|
|
{
|
2016-05-23 16:17:20 +03:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2016-11-10 14:20:02 +02:00
|
|
|
k_delayed_work_submit(&conn->le.update_work,
|
|
|
|
conn->role == BT_HCI_ROLE_MASTER ? K_NO_WAIT :
|
2016-05-23 16:17:20 +03:00
|
|
|
CONN_UPDATE_TIMEOUT);
|
2015-08-10 21:53:45 +02:00
|
|
|
}
|
|
|
|
|
2015-10-28 10:34:15 +02:00
|
|
|
static void le_conn_complete(struct net_buf *buf)
|
2015-04-18 18:44:38 +03:00
|
|
|
{
|
|
|
|
struct bt_hci_evt_le_conn_complete *evt = (void *)buf->data;
|
2017-04-20 12:00:29 -05:00
|
|
|
u16_t handle = sys_le16_to_cpu(evt->handle);
|
2015-10-01 18:21:40 +02:00
|
|
|
const bt_addr_le_t *id_addr;
|
2015-04-28 10:39:50 +03:00
|
|
|
struct bt_conn *conn;
|
2015-07-27 17:28:59 +03:00
|
|
|
int err;
|
2015-04-18 18:44:38 +03:00
|
|
|
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_DBG("status %u handle %u role %u %s", evt->status, handle,
|
2015-05-25 22:11:28 +03:00
|
|
|
evt->role, bt_addr_le_str(&evt->peer_addr));
|
2015-05-21 20:59:23 +03:00
|
|
|
|
|
|
|
if (evt->status) {
|
2016-06-08 05:56:30 +02:00
|
|
|
/*
|
|
|
|
* if there was an error we are only interested in pending
|
|
|
|
* connection so there is no need to check ID address as
|
|
|
|
* only one connection can be in that state
|
|
|
|
*
|
|
|
|
* Depending on error code address might not be valid anyway.
|
|
|
|
*/
|
|
|
|
conn = bt_conn_lookup_state_le(NULL, BT_CONN_CONNECT);
|
2015-06-30 10:23:09 +03:00
|
|
|
if (!conn) {
|
2015-06-23 14:38:24 +02:00
|
|
|
return;
|
|
|
|
}
|
2015-07-08 11:00:13 +03:00
|
|
|
|
2016-01-14 11:17:32 +02:00
|
|
|
conn->err = evt->status;
|
|
|
|
|
2015-06-23 14:38:24 +02:00
|
|
|
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.
|
|
|
|
*/
|
2015-10-23 12:45:33 +03:00
|
|
|
bt_conn_unref(conn);
|
2015-06-23 14:38:24 +02:00
|
|
|
|
2015-05-21 20:59:23 +03:00
|
|
|
return;
|
|
|
|
}
|
2015-04-28 10:39:50 +03:00
|
|
|
|
2016-06-08 05:56:30 +02:00
|
|
|
id_addr = find_id_addr(&evt->peer_addr);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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(id_addr, BT_CONN_CONNECT);
|
|
|
|
|
2016-02-17 09:43:04 +01:00
|
|
|
if (evt->role == BT_CONN_ROLE_SLAVE) {
|
2016-05-05 12:01:16 +02:00
|
|
|
/*
|
|
|
|
* clear advertising even if we are not able to add connection
|
|
|
|
* object to keep host in sync with controller state
|
|
|
|
*/
|
2016-02-17 09:43:04 +01:00
|
|
|
atomic_clear_bit(bt_dev.flags, BT_DEV_ADVERTISING);
|
|
|
|
|
2016-05-05 12:01:16 +02:00
|
|
|
/* only for slave we may need to add new connection */
|
|
|
|
if (!conn) {
|
|
|
|
conn = bt_conn_add_le(id_addr);
|
|
|
|
}
|
2015-06-23 14:38:24 +02:00
|
|
|
}
|
|
|
|
|
2015-04-28 10:39:50 +03:00
|
|
|
if (!conn) {
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_ERR("Unable to add new conn for handle %u", handle);
|
2015-04-28 10:39:50 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-06-23 11:56:50 +02:00
|
|
|
conn->handle = handle;
|
2015-11-03 12:19:01 +01:00
|
|
|
bt_addr_le_copy(&conn->le.dst, id_addr);
|
2015-12-05 15:32:58 +02:00
|
|
|
conn->le.interval = sys_le16_to_cpu(evt->interval);
|
2015-12-05 21:39:44 +02:00
|
|
|
conn->le.latency = sys_le16_to_cpu(evt->latency);
|
|
|
|
conn->le.timeout = sys_le16_to_cpu(evt->supv_timeout);
|
2015-09-02 10:47:35 +02:00
|
|
|
conn->role = evt->role;
|
2015-06-23 14:38:24 +02:00
|
|
|
|
2016-05-05 12:03:44 +02:00
|
|
|
/*
|
|
|
|
* Use connection address (instead of identity address) as initiator
|
|
|
|
* or responder address. Only slave needs to be updated. For master all
|
|
|
|
* was set during outgoing connection creation.
|
2015-10-01 18:21:40 +02:00
|
|
|
*/
|
2016-05-05 12:03:44 +02:00
|
|
|
if (conn->role == BT_HCI_ROLE_SLAVE) {
|
2015-11-03 12:19:01 +01:00
|
|
|
bt_addr_le_copy(&conn->le.init_addr, &evt->peer_addr);
|
2016-04-29 11:02:55 +02:00
|
|
|
|
2016-08-27 11:11:30 +02:00
|
|
|
/* TODO Handle the probability that random address could have
|
|
|
|
* been updated by rpa_timeout or numerous other places it is
|
|
|
|
* called in this file before le_conn_complete is processed
|
|
|
|
* here.
|
|
|
|
*/
|
2017-01-17 14:28:01 +02:00
|
|
|
if (IS_ENABLED(CONFIG_BLUETOOTH_PRIVACY)) {
|
|
|
|
bt_addr_le_copy(&conn->le.resp_addr,
|
|
|
|
&bt_dev.random_addr);
|
|
|
|
} else {
|
|
|
|
bt_addr_le_copy(&conn->le.resp_addr, &bt_dev.id_addr);
|
|
|
|
}
|
2016-08-27 11:11:30 +02:00
|
|
|
|
|
|
|
/* if the controller supports, lets advertise for another
|
|
|
|
* slave connection.
|
|
|
|
* check for connectable advertising state is sufficient as
|
|
|
|
* this is how this le connection complete for slave occurred.
|
|
|
|
*/
|
|
|
|
if (atomic_test_bit(bt_dev.flags, BT_DEV_KEEP_ADVERTISING) &&
|
|
|
|
BT_LE_STATES_SLAVE_CONN_ADV(bt_dev.le.states)) {
|
2017-01-17 14:28:01 +02:00
|
|
|
if (IS_ENABLED(CONFIG_BLUETOOTH_PRIVACY)) {
|
|
|
|
le_set_private_addr();
|
|
|
|
}
|
|
|
|
|
2016-08-27 11:11:30 +02:00
|
|
|
set_advertise_enable(true);
|
|
|
|
}
|
|
|
|
|
2015-09-01 17:30:58 +02:00
|
|
|
}
|
|
|
|
|
2015-06-23 11:56:50 +02:00
|
|
|
bt_conn_set_state(conn, BT_CONN_CONNECTED);
|
|
|
|
|
2015-12-15 15:35:05 +01:00
|
|
|
/*
|
|
|
|
* it is possible that connection was disconnected directly from
|
|
|
|
* connected callback so we must check state before doing connection
|
|
|
|
* parameters update
|
|
|
|
*/
|
|
|
|
if (conn->state != BT_CONN_CONNECTED) {
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2015-07-27 17:28:59 +03:00
|
|
|
if ((evt->role == BT_HCI_ROLE_MASTER) ||
|
2016-08-28 16:01:28 +03:00
|
|
|
BT_FEAT_LE_SLAVE_FEATURE_XCHG(bt_dev.le.features)) {
|
2015-07-27 17:28:59 +03:00
|
|
|
err = hci_le_read_remote_features(conn);
|
|
|
|
if (!err) {
|
|
|
|
goto done;
|
|
|
|
}
|
2015-06-23 11:56:50 +02:00
|
|
|
}
|
2015-05-21 19:03:17 +03:00
|
|
|
|
2017-05-19 05:01:43 +02:00
|
|
|
if (BT_FEAT_LE_PHY_2M(bt_dev.le.features)) {
|
2017-05-06 07:10:50 +02:00
|
|
|
err = hci_le_set_phy(conn);
|
|
|
|
if (!err) {
|
2017-05-19 05:01:43 +02:00
|
|
|
atomic_set_bit(conn->flags, BT_CONN_AUTO_PHY_UPDATE);
|
2017-05-06 07:10:50 +02:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-15 23:18:08 +02:00
|
|
|
if (BT_FEAT_LE_DLE(bt_dev.le.features)) {
|
|
|
|
err = hci_le_set_data_len(conn);
|
|
|
|
if (!err) {
|
|
|
|
atomic_set_bit(conn->flags, BT_CONN_AUTO_DATA_LEN);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-02 12:48:42 +01:00
|
|
|
update_conn_param(conn);
|
2015-07-27 17:28:59 +03:00
|
|
|
|
|
|
|
done:
|
2015-10-23 12:45:33 +03:00
|
|
|
bt_conn_unref(conn);
|
2015-12-03 22:51:16 +02:00
|
|
|
bt_le_scan_update(false);
|
2015-07-02 11:53:54 +02:00
|
|
|
}
|
|
|
|
|
2015-10-28 10:34:15 +02:00
|
|
|
static void le_remote_feat_complete(struct net_buf *buf)
|
2015-07-28 13:02:43 +03:00
|
|
|
{
|
2017-04-27 15:22:53 +02:00
|
|
|
struct bt_hci_evt_le_remote_feat_complete *evt = (void *)buf->data;
|
2017-04-20 12:00:29 -05:00
|
|
|
u16_t handle = sys_le16_to_cpu(evt->handle);
|
2015-07-28 13:02:43 +03:00
|
|
|
struct bt_conn *conn;
|
|
|
|
|
|
|
|
conn = bt_conn_lookup_handle(handle);
|
|
|
|
if (!conn) {
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_ERR("Unable to lookup conn for handle %u", handle);
|
2015-07-28 13:02:43 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!evt->status) {
|
2015-11-03 12:19:01 +01:00
|
|
|
memcpy(conn->le.features, evt->features,
|
|
|
|
sizeof(conn->le.features));
|
2015-07-28 13:02:43 +03:00
|
|
|
}
|
|
|
|
|
2017-05-19 05:01:43 +02:00
|
|
|
if (BT_FEAT_LE_PHY_2M(bt_dev.le.features) &&
|
|
|
|
BT_FEAT_LE_PHY_2M(conn->le.features)) {
|
2017-05-06 07:10:50 +02:00
|
|
|
int err;
|
|
|
|
|
|
|
|
err = hci_le_set_phy(conn);
|
|
|
|
if (!err) {
|
2017-05-19 05:01:43 +02:00
|
|
|
atomic_set_bit(conn->flags, BT_CONN_AUTO_PHY_UPDATE);
|
2017-05-06 07:10:50 +02:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-15 23:18:08 +02:00
|
|
|
if (BT_FEAT_LE_DLE(bt_dev.le.features) &&
|
|
|
|
BT_FEAT_LE_DLE(conn->le.features)) {
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = hci_le_set_data_len(conn);
|
|
|
|
if (!err) {
|
|
|
|
atomic_set_bit(conn->flags, BT_CONN_AUTO_DATA_LEN);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
update_conn_param(conn);
|
|
|
|
|
|
|
|
done:
|
|
|
|
bt_conn_unref(conn);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void le_data_len_change(struct net_buf *buf)
|
|
|
|
{
|
|
|
|
struct bt_hci_evt_le_data_len_change *evt = (void *)buf->data;
|
|
|
|
u16_t max_tx_octets = sys_le16_to_cpu(evt->max_tx_octets);
|
|
|
|
u16_t max_rx_octets = sys_le16_to_cpu(evt->max_rx_octets);
|
|
|
|
u16_t max_tx_time = sys_le16_to_cpu(evt->max_tx_time);
|
|
|
|
u16_t max_rx_time = sys_le16_to_cpu(evt->max_rx_time);
|
|
|
|
u16_t handle = sys_le16_to_cpu(evt->handle);
|
|
|
|
struct bt_conn *conn;
|
|
|
|
|
|
|
|
conn = bt_conn_lookup_handle(handle);
|
|
|
|
if (!conn) {
|
|
|
|
BT_ERR("Unable to lookup conn for handle %u", handle);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
BT_DBG("max. tx: %u (%uus), max. rx: %u (%uus)", max_tx_octets,
|
|
|
|
max_tx_time, max_rx_octets, max_rx_time);
|
|
|
|
|
|
|
|
if (!atomic_test_and_clear_bit(conn->flags, BT_CONN_AUTO_DATA_LEN)) {
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2017-05-06 07:10:50 +02:00
|
|
|
update_conn_param(conn);
|
2017-05-15 23:18:08 +02:00
|
|
|
|
2017-05-06 07:10:50 +02:00
|
|
|
done:
|
|
|
|
bt_conn_unref(conn);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void le_phy_update_complete(struct net_buf *buf)
|
|
|
|
{
|
|
|
|
struct bt_hci_evt_le_phy_update_complete *evt = (void *)buf->data;
|
|
|
|
u16_t handle = sys_le16_to_cpu(evt->handle);
|
|
|
|
struct bt_conn *conn;
|
|
|
|
|
|
|
|
conn = bt_conn_lookup_handle(handle);
|
|
|
|
if (!conn) {
|
|
|
|
BT_ERR("Unable to lookup conn for handle %u", handle);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-05-13 06:02:24 +02:00
|
|
|
BT_DBG("PHY updated: status: 0x%x, tx: %u, rx: %u",
|
|
|
|
evt->status, evt->tx_phy, evt->rx_phy);
|
2017-05-06 07:10:50 +02:00
|
|
|
|
2017-05-19 05:01:43 +02:00
|
|
|
if (!atomic_test_and_clear_bit(conn->flags, BT_CONN_AUTO_PHY_UPDATE)) {
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2017-05-15 23:18:08 +02:00
|
|
|
if (BT_FEAT_LE_DLE(bt_dev.le.features) &&
|
|
|
|
BT_FEAT_LE_DLE(conn->le.features)) {
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = hci_le_set_data_len(conn);
|
|
|
|
if (!err) {
|
|
|
|
atomic_set_bit(conn->flags, BT_CONN_AUTO_DATA_LEN);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-02 12:48:42 +01:00
|
|
|
update_conn_param(conn);
|
2015-07-27 17:28:59 +03:00
|
|
|
|
2017-05-19 05:01:43 +02:00
|
|
|
done:
|
2015-10-23 12:45:33 +03:00
|
|
|
bt_conn_unref(conn);
|
2015-07-28 13:02:43 +03:00
|
|
|
}
|
|
|
|
|
2017-01-13 13:20:22 +02:00
|
|
|
bool bt_le_conn_params_valid(const struct bt_le_conn_param *param)
|
2016-12-13 09:28:35 +02:00
|
|
|
{
|
2017-01-14 19:44:16 +01:00
|
|
|
/* All limits according to BT Core spec 5.0 [Vol 2, Part E, 7.8.12] */
|
|
|
|
|
2017-01-13 13:20:22 +02:00
|
|
|
if (param->interval_min > param->interval_max ||
|
|
|
|
param->interval_min < 6 || param->interval_max > 3200) {
|
2016-12-13 09:28:35 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-01-14 19:44:16 +01:00
|
|
|
if (param->latency > 499) {
|
2016-12-13 09:28:35 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-01-14 19:44:16 +01:00
|
|
|
if (param->timeout < 10 || param->timeout > 3200 ||
|
|
|
|
((4 * param->timeout) <=
|
|
|
|
((1 + param->latency) * param->interval_max))) {
|
2016-12-13 09:28:35 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-04-20 12:00:29 -05:00
|
|
|
static int le_conn_param_neg_reply(u16_t handle, u8_t reason)
|
2015-08-10 22:23:05 +02:00
|
|
|
{
|
|
|
|
struct bt_hci_cp_le_conn_param_req_neg_reply *cp;
|
2015-10-28 10:34:15 +02:00
|
|
|
struct net_buf *buf;
|
2015-08-10 22:23:05 +02:00
|
|
|
|
|
|
|
buf = bt_hci_cmd_create(BT_HCI_OP_LE_CONN_PARAM_REQ_NEG_REPLY,
|
|
|
|
sizeof(*cp));
|
|
|
|
if (!buf) {
|
|
|
|
return -ENOBUFS;
|
|
|
|
}
|
|
|
|
|
2015-10-28 10:34:15 +02:00
|
|
|
cp = net_buf_add(buf, sizeof(*cp));
|
2015-08-10 22:23:05 +02:00
|
|
|
cp->handle = sys_cpu_to_le16(handle);
|
|
|
|
cp->reason = sys_cpu_to_le16(reason);
|
|
|
|
|
|
|
|
return bt_hci_cmd_send(BT_HCI_OP_LE_CONN_PARAM_REQ_NEG_REPLY, buf);
|
|
|
|
}
|
|
|
|
|
2017-04-20 12:00:29 -05:00
|
|
|
static int le_conn_param_req_reply(u16_t handle,
|
2017-01-13 13:20:22 +02:00
|
|
|
const struct bt_le_conn_param *param)
|
2015-08-10 22:23:05 +02:00
|
|
|
{
|
|
|
|
struct bt_hci_cp_le_conn_param_req_reply *cp;
|
2015-10-28 10:34:15 +02:00
|
|
|
struct net_buf *buf;
|
2015-08-10 22:23:05 +02:00
|
|
|
|
|
|
|
buf = bt_hci_cmd_create(BT_HCI_OP_LE_CONN_PARAM_REQ_REPLY, sizeof(*cp));
|
|
|
|
if (!buf) {
|
|
|
|
return -ENOBUFS;
|
|
|
|
}
|
|
|
|
|
2015-10-28 10:34:15 +02:00
|
|
|
cp = net_buf_add(buf, sizeof(*cp));
|
2015-11-30 13:15:04 +02:00
|
|
|
memset(cp, 0, sizeof(*cp));
|
2015-08-10 22:23:05 +02:00
|
|
|
|
|
|
|
cp->handle = sys_cpu_to_le16(handle);
|
2017-01-13 13:20:22 +02:00
|
|
|
cp->interval_min = sys_cpu_to_le16(param->interval_min);
|
|
|
|
cp->interval_max = sys_cpu_to_le16(param->interval_max);
|
|
|
|
cp->latency = sys_cpu_to_le16(param->latency);
|
|
|
|
cp->timeout = sys_cpu_to_le16(param->timeout);
|
2015-08-10 22:23:05 +02:00
|
|
|
|
2015-10-01 17:50:19 +02:00
|
|
|
return bt_hci_cmd_send(BT_HCI_OP_LE_CONN_PARAM_REQ_REPLY, buf);
|
|
|
|
}
|
|
|
|
|
2015-10-28 10:34:15 +02:00
|
|
|
static int le_conn_param_req(struct net_buf *buf)
|
2015-10-01 17:50:19 +02:00
|
|
|
{
|
|
|
|
struct bt_hci_evt_le_conn_param_req *evt = (void *)buf->data;
|
2017-01-13 13:20:22 +02:00
|
|
|
struct bt_le_conn_param param;
|
2015-10-01 17:50:19 +02:00
|
|
|
struct bt_conn *conn;
|
2017-04-20 12:00:29 -05:00
|
|
|
u16_t handle;
|
2017-01-16 13:26:53 +02:00
|
|
|
int err;
|
2015-10-01 17:50:19 +02:00
|
|
|
|
|
|
|
handle = sys_le16_to_cpu(evt->handle);
|
2017-01-13 13:20:22 +02:00
|
|
|
param.interval_min = sys_le16_to_cpu(evt->interval_min);
|
|
|
|
param.interval_max = sys_le16_to_cpu(evt->interval_max);
|
|
|
|
param.latency = sys_le16_to_cpu(evt->latency);
|
|
|
|
param.timeout = sys_le16_to_cpu(evt->timeout);
|
2015-10-01 17:50:19 +02:00
|
|
|
|
|
|
|
conn = bt_conn_lookup_handle(handle);
|
|
|
|
if (!conn) {
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_ERR("Unable to lookup conn for handle %u", handle);
|
2015-10-01 17:50:19 +02:00
|
|
|
return le_conn_param_neg_reply(handle,
|
|
|
|
BT_HCI_ERR_UNKNOWN_CONN_ID);
|
|
|
|
}
|
|
|
|
|
2017-01-16 13:26:53 +02:00
|
|
|
if (!le_param_req(conn, ¶m)) {
|
|
|
|
err = le_conn_param_neg_reply(handle,
|
2017-04-11 08:39:58 +02:00
|
|
|
BT_HCI_ERR_INVALID_LL_PARAM);
|
2017-01-16 13:26:53 +02:00
|
|
|
} else {
|
|
|
|
err = le_conn_param_req_reply(handle, ¶m);
|
2015-10-01 17:50:19 +02:00
|
|
|
}
|
|
|
|
|
2017-01-16 13:26:53 +02:00
|
|
|
bt_conn_unref(conn);
|
|
|
|
return err;
|
2015-10-01 17:50:19 +02:00
|
|
|
}
|
|
|
|
|
2015-10-28 10:34:15 +02:00
|
|
|
static void le_conn_update_complete(struct net_buf *buf)
|
2015-10-01 17:50:19 +02:00
|
|
|
{
|
|
|
|
struct bt_hci_evt_le_conn_update_complete *evt = (void *)buf->data;
|
|
|
|
struct bt_conn *conn;
|
2017-04-20 12:00:29 -05:00
|
|
|
u16_t handle;
|
2015-10-01 17:50:19 +02:00
|
|
|
|
|
|
|
handle = sys_le16_to_cpu(evt->handle);
|
|
|
|
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_DBG("status %u, handle %u", evt->status, handle);
|
2015-10-01 17:50:19 +02:00
|
|
|
|
|
|
|
conn = bt_conn_lookup_handle(handle);
|
|
|
|
if (!conn) {
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_ERR("Unable to lookup conn for handle %u", handle);
|
2015-10-01 17:50:19 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!evt->status) {
|
2016-02-02 12:48:42 +01:00
|
|
|
conn->le.interval = sys_le16_to_cpu(evt->interval);
|
|
|
|
conn->le.latency = sys_le16_to_cpu(evt->latency);
|
|
|
|
conn->le.timeout = sys_le16_to_cpu(evt->supv_timeout);
|
|
|
|
notify_le_param_updated(conn);
|
2015-10-01 17:50:19 +02:00
|
|
|
}
|
|
|
|
|
2015-10-23 12:45:33 +03:00
|
|
|
bt_conn_unref(conn);
|
2015-10-01 17:50:19 +02:00
|
|
|
}
|
|
|
|
|
2015-10-02 10:10:39 +02:00
|
|
|
static void check_pending_conn(const bt_addr_le_t *id_addr,
|
2017-04-20 12:00:29 -05:00
|
|
|
const bt_addr_le_t *addr, u8_t evtype)
|
2015-10-01 17:50:19 +02:00
|
|
|
{
|
|
|
|
struct bt_conn *conn;
|
|
|
|
|
2015-12-03 19:45:46 +02:00
|
|
|
/* No connections are allowed during explicit scanning */
|
|
|
|
if (atomic_test_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-10-01 17:50:19 +02:00
|
|
|
/* Return if event is not connectable */
|
|
|
|
if (evtype != BT_LE_ADV_IND && evtype != BT_LE_ADV_DIRECT_IND) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-12-07 10:45:41 +02:00
|
|
|
conn = bt_conn_lookup_state_le(id_addr, BT_CONN_CONNECT_SCAN);
|
2015-10-01 17:50:19 +02:00
|
|
|
if (!conn) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bt_hci_stop_scanning()) {
|
2016-05-04 17:13:16 +02:00
|
|
|
goto failed;
|
2015-10-01 17:50:19 +02:00
|
|
|
}
|
|
|
|
|
2017-01-17 14:28:01 +02:00
|
|
|
if (IS_ENABLED(CONFIG_BLUETOOTH_PRIVACY)) {
|
|
|
|
if (le_set_private_addr()) {
|
|
|
|
goto failed;
|
|
|
|
}
|
2016-05-04 17:18:50 +02:00
|
|
|
|
2017-01-17 14:28:01 +02:00
|
|
|
bt_addr_le_copy(&conn->le.init_addr, &bt_dev.random_addr);
|
|
|
|
} else {
|
|
|
|
/* If Static Random address is used as Identity address we
|
|
|
|
* need to restore it before creating connection. Otherwise
|
|
|
|
* NRPA used for active scan could be used for connection.
|
|
|
|
*/
|
|
|
|
if (atomic_test_bit(bt_dev.flags, BT_DEV_ID_STATIC_RANDOM)) {
|
|
|
|
set_random_address(&bt_dev.id_addr.a);
|
|
|
|
}
|
2016-05-09 11:41:14 +02:00
|
|
|
|
2017-01-17 14:28:01 +02:00
|
|
|
bt_addr_le_copy(&conn->le.init_addr, &bt_dev.id_addr);
|
|
|
|
}
|
2016-04-04 12:55:11 +03:00
|
|
|
|
|
|
|
bt_addr_le_copy(&conn->le.resp_addr, addr);
|
2015-12-05 15:32:58 +02:00
|
|
|
|
|
|
|
if (hci_le_create_conn(conn)) {
|
2016-05-04 17:13:16 +02:00
|
|
|
goto failed;
|
2015-10-01 17:50:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bt_conn_set_state(conn, BT_CONN_CONNECT);
|
2016-05-04 17:13:16 +02:00
|
|
|
bt_conn_unref(conn);
|
|
|
|
return;
|
2015-10-01 17:50:19 +02:00
|
|
|
|
2016-05-04 17:13:16 +02:00
|
|
|
failed:
|
|
|
|
conn->err = BT_HCI_ERR_UNSPECIFIED;
|
|
|
|
bt_conn_set_state(conn, BT_CONN_DISCONNECTED);
|
2015-10-23 12:45:33 +03:00
|
|
|
bt_conn_unref(conn);
|
2016-05-04 17:13:16 +02:00
|
|
|
bt_le_scan_update(false);
|
2015-10-01 17:50:19 +02:00
|
|
|
}
|
2017-05-04 14:09:10 +03:00
|
|
|
|
2017-05-04 16:09:53 +02:00
|
|
|
#if defined(CONFIG_BLUETOOTH_HCI_ACL_FLOW_CONTROL)
|
2017-05-04 14:09:10 +03:00
|
|
|
static int set_flow_control(void)
|
|
|
|
{
|
|
|
|
struct bt_hci_cp_host_buffer_size *hbs;
|
|
|
|
struct net_buf *buf;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
/* Check if host flow control is actually supported */
|
|
|
|
if (!(bt_dev.supported_commands[10] & 0x20)) {
|
|
|
|
BT_WARN("Controller to host flow control not supported");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
buf = bt_hci_cmd_create(BT_HCI_OP_HOST_BUFFER_SIZE,
|
|
|
|
sizeof(*hbs));
|
|
|
|
if (!buf) {
|
|
|
|
return -ENOBUFS;
|
|
|
|
}
|
|
|
|
|
|
|
|
hbs = net_buf_add(buf, sizeof(*hbs));
|
|
|
|
memset(hbs, 0, sizeof(*hbs));
|
|
|
|
hbs->acl_mtu = sys_cpu_to_le16(CONFIG_BLUETOOTH_L2CAP_RX_MTU +
|
|
|
|
sizeof(struct bt_l2cap_hdr));
|
|
|
|
hbs->acl_pkts = sys_cpu_to_le16(CONFIG_BLUETOOTH_ACL_RX_COUNT);
|
|
|
|
|
|
|
|
err = bt_hci_cmd_send_sync(BT_HCI_OP_HOST_BUFFER_SIZE, buf, NULL);
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
buf = bt_hci_cmd_create(BT_HCI_OP_SET_CTL_TO_HOST_FLOW, 1);
|
|
|
|
if (!buf) {
|
|
|
|
return -ENOBUFS;
|
|
|
|
}
|
|
|
|
|
|
|
|
net_buf_add_u8(buf, BT_HCI_CTL_TO_HOST_FLOW_ENABLE);
|
|
|
|
return bt_hci_cmd_send_sync(BT_HCI_OP_SET_CTL_TO_HOST_FLOW, buf, NULL);
|
|
|
|
}
|
2017-05-04 16:09:53 +02:00
|
|
|
#endif /* CONFIG_BLUETOOTH_HCI_ACL_FLOW_CONTROL */
|
2016-12-21 17:49:39 +02:00
|
|
|
#endif /* CONFIG_BLUETOOTH_CONN */
|
2015-10-01 17:50:19 +02:00
|
|
|
|
2016-01-21 09:31:09 +01:00
|
|
|
#if defined(CONFIG_BLUETOOTH_BREDR)
|
2016-04-27 12:39:44 +02:00
|
|
|
static void reset_pairing(struct bt_conn *conn)
|
|
|
|
{
|
|
|
|
atomic_clear_bit(conn->flags, BT_CONN_BR_PAIRING);
|
|
|
|
atomic_clear_bit(conn->flags, BT_CONN_BR_PAIRING_INITIATOR);
|
|
|
|
atomic_clear_bit(conn->flags, BT_CONN_BR_LEGACY_SECURE);
|
|
|
|
|
|
|
|
/* Reset required security level to current operational */
|
|
|
|
conn->required_sec_level = conn->sec_level;
|
|
|
|
}
|
|
|
|
|
2017-04-20 12:00:29 -05:00
|
|
|
static int reject_conn(const bt_addr_t *bdaddr, u8_t reason)
|
2016-01-21 09:31:09 +01:00
|
|
|
{
|
|
|
|
struct bt_hci_cp_reject_conn_req *cp;
|
|
|
|
struct net_buf *buf;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
buf = bt_hci_cmd_create(BT_HCI_OP_REJECT_CONN_REQ, sizeof(*cp));
|
|
|
|
if (!buf) {
|
|
|
|
return -ENOBUFS;
|
|
|
|
}
|
|
|
|
|
|
|
|
cp = net_buf_add(buf, sizeof(*cp));
|
|
|
|
bt_addr_copy(&cp->bdaddr, bdaddr);
|
|
|
|
cp->reason = reason;
|
|
|
|
|
|
|
|
err = bt_hci_cmd_send_sync(BT_HCI_OP_REJECT_CONN_REQ, buf, NULL);
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
Bluetooth: HFP HF: SCO: Accept eSCO conn request
1. Accept the incoming Synchronous connection request and establish
a new sco connection object.
2. Enable sco conn complete in event_mask
> HCI Event: Connect Request (0x04) plen 10 [hci0] 126.198264
Address: 48:9D:24:1F:4D:1D (BlackBerry RTS)
Class: 0x7a020c
Major class: Phone (cellular, cordless, payphone, modem)
Minor class: Smart phone
Networking (LAN, Ad hoc)
Capturing (Scanner, Microphone)
Object Transfer (v-Inbox, v-Folder)
Audio (Speaker, Microphone, Headset)
Telephony (Cordless telephony, Modem, Headset)
Link type: eSCO (0x02)
< HCI Command: Accept Synchronous Co.. (0x01|0x0029) plen 21
Address: 48:9D:24:1F:4D:1D (BlackBerry RTS)
Transmit bandwidth: 8000
Receive bandwidth: 8000
Max latency: 7
Setting: 0x0060
Input Coding: Linear
Input Data Format: 2's complement
Input Sample Size: 16-bit
# of bits padding at MSB: 0
Air Coding Format: CVSD
Retransmission effort: Optimize for power consumption (0x01)
Packet type: 0x0006
HV2 may be used
HV3 may be used
> HCI Event: Command Status (0x0f) plen 4 [hci0] 126.205171
Accept Synchronous Connection Request (0x01|0x0029) ncmd 1
Status: Success (0x00)
Change-Id: I71597aef94e945a9c07be1960994ad20c1b44bb3
Signed-off-by: Sathish Narasimman <sathish.narasimman@intel.com>
2017-02-15 14:29:11 +05:30
|
|
|
static int accept_sco_conn(const bt_addr_t *bdaddr, struct bt_conn *sco_conn)
|
|
|
|
{
|
|
|
|
struct bt_hci_cp_accept_sync_conn_req *cp;
|
|
|
|
struct net_buf *buf;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
buf = bt_hci_cmd_create(BT_HCI_OP_ACCEPT_SYNC_CONN_REQ, sizeof(*cp));
|
|
|
|
if (!buf) {
|
|
|
|
return -ENOBUFS;
|
|
|
|
}
|
|
|
|
|
|
|
|
cp = net_buf_add(buf, sizeof(*cp));
|
|
|
|
bt_addr_copy(&cp->bdaddr, bdaddr);
|
|
|
|
cp->pkt_type = sco_conn->sco.pkt_type;
|
|
|
|
cp->tx_bandwidth = 0x00001f40;
|
|
|
|
cp->rx_bandwidth = 0x00001f40;
|
|
|
|
cp->max_latency = 0x0007;
|
|
|
|
cp->retrans_effort = 0x01;
|
|
|
|
cp->content_format = BT_VOICE_CVSD_16BIT;
|
|
|
|
|
|
|
|
err = bt_hci_cmd_send_sync(BT_HCI_OP_ACCEPT_SYNC_CONN_REQ, buf, NULL);
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-01-21 09:31:09 +01:00
|
|
|
static int accept_conn(const bt_addr_t *bdaddr)
|
|
|
|
{
|
|
|
|
struct bt_hci_cp_accept_conn_req *cp;
|
|
|
|
struct net_buf *buf;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
buf = bt_hci_cmd_create(BT_HCI_OP_ACCEPT_CONN_REQ, sizeof(*cp));
|
|
|
|
if (!buf) {
|
|
|
|
return -ENOBUFS;
|
|
|
|
}
|
|
|
|
|
|
|
|
cp = net_buf_add(buf, sizeof(*cp));
|
|
|
|
bt_addr_copy(&cp->bdaddr, bdaddr);
|
|
|
|
cp->role = BT_HCI_ROLE_SLAVE;
|
|
|
|
|
|
|
|
err = bt_hci_cmd_send_sync(BT_HCI_OP_ACCEPT_CONN_REQ, buf, NULL);
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
Bluetooth: HFP HF: SCO: Accept eSCO conn request
1. Accept the incoming Synchronous connection request and establish
a new sco connection object.
2. Enable sco conn complete in event_mask
> HCI Event: Connect Request (0x04) plen 10 [hci0] 126.198264
Address: 48:9D:24:1F:4D:1D (BlackBerry RTS)
Class: 0x7a020c
Major class: Phone (cellular, cordless, payphone, modem)
Minor class: Smart phone
Networking (LAN, Ad hoc)
Capturing (Scanner, Microphone)
Object Transfer (v-Inbox, v-Folder)
Audio (Speaker, Microphone, Headset)
Telephony (Cordless telephony, Modem, Headset)
Link type: eSCO (0x02)
< HCI Command: Accept Synchronous Co.. (0x01|0x0029) plen 21
Address: 48:9D:24:1F:4D:1D (BlackBerry RTS)
Transmit bandwidth: 8000
Receive bandwidth: 8000
Max latency: 7
Setting: 0x0060
Input Coding: Linear
Input Data Format: 2's complement
Input Sample Size: 16-bit
# of bits padding at MSB: 0
Air Coding Format: CVSD
Retransmission effort: Optimize for power consumption (0x01)
Packet type: 0x0006
HV2 may be used
HV3 may be used
> HCI Event: Command Status (0x0f) plen 4 [hci0] 126.205171
Accept Synchronous Connection Request (0x01|0x0029) ncmd 1
Status: Success (0x00)
Change-Id: I71597aef94e945a9c07be1960994ad20c1b44bb3
Signed-off-by: Sathish Narasimman <sathish.narasimman@intel.com>
2017-02-15 14:29:11 +05:30
|
|
|
static void bt_esco_conn_req(struct bt_hci_evt_conn_request *evt)
|
|
|
|
{
|
|
|
|
struct bt_conn *sco_conn;
|
|
|
|
|
|
|
|
sco_conn = bt_conn_add_sco(&evt->bdaddr, evt->link_type);
|
|
|
|
if (!sco_conn) {
|
|
|
|
reject_conn(&evt->bdaddr, BT_HCI_ERR_INSUFFICIENT_RESOURCES);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-02-15 15:18:13 +05:30
|
|
|
if (accept_sco_conn(&evt->bdaddr, sco_conn)) {
|
|
|
|
BT_ERR("Error accepting connection from %s",
|
|
|
|
bt_addr_str(&evt->bdaddr));
|
|
|
|
reject_conn(&evt->bdaddr, BT_HCI_ERR_UNSPECIFIED);
|
|
|
|
bt_sco_cleanup(sco_conn);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
Bluetooth: HFP HF: SCO: Accept eSCO conn request
1. Accept the incoming Synchronous connection request and establish
a new sco connection object.
2. Enable sco conn complete in event_mask
> HCI Event: Connect Request (0x04) plen 10 [hci0] 126.198264
Address: 48:9D:24:1F:4D:1D (BlackBerry RTS)
Class: 0x7a020c
Major class: Phone (cellular, cordless, payphone, modem)
Minor class: Smart phone
Networking (LAN, Ad hoc)
Capturing (Scanner, Microphone)
Object Transfer (v-Inbox, v-Folder)
Audio (Speaker, Microphone, Headset)
Telephony (Cordless telephony, Modem, Headset)
Link type: eSCO (0x02)
< HCI Command: Accept Synchronous Co.. (0x01|0x0029) plen 21
Address: 48:9D:24:1F:4D:1D (BlackBerry RTS)
Transmit bandwidth: 8000
Receive bandwidth: 8000
Max latency: 7
Setting: 0x0060
Input Coding: Linear
Input Data Format: 2's complement
Input Sample Size: 16-bit
# of bits padding at MSB: 0
Air Coding Format: CVSD
Retransmission effort: Optimize for power consumption (0x01)
Packet type: 0x0006
HV2 may be used
HV3 may be used
> HCI Event: Command Status (0x0f) plen 4 [hci0] 126.205171
Accept Synchronous Connection Request (0x01|0x0029) ncmd 1
Status: Success (0x00)
Change-Id: I71597aef94e945a9c07be1960994ad20c1b44bb3
Signed-off-by: Sathish Narasimman <sathish.narasimman@intel.com>
2017-02-15 14:29:11 +05:30
|
|
|
sco_conn->role = BT_HCI_ROLE_SLAVE;
|
|
|
|
bt_conn_set_state(sco_conn, BT_CONN_CONNECT);
|
|
|
|
bt_conn_unref(sco_conn);
|
|
|
|
}
|
|
|
|
|
2016-01-21 09:31:09 +01:00
|
|
|
static void conn_req(struct net_buf *buf)
|
|
|
|
{
|
|
|
|
struct bt_hci_evt_conn_request *evt = (void *)buf->data;
|
|
|
|
struct bt_conn *conn;
|
|
|
|
|
|
|
|
BT_DBG("conn req from %s, type 0x%02x", bt_addr_str(&evt->bdaddr),
|
|
|
|
evt->link_type);
|
|
|
|
|
|
|
|
if (evt->link_type != BT_HCI_ACL) {
|
Bluetooth: HFP HF: SCO: Accept eSCO conn request
1. Accept the incoming Synchronous connection request and establish
a new sco connection object.
2. Enable sco conn complete in event_mask
> HCI Event: Connect Request (0x04) plen 10 [hci0] 126.198264
Address: 48:9D:24:1F:4D:1D (BlackBerry RTS)
Class: 0x7a020c
Major class: Phone (cellular, cordless, payphone, modem)
Minor class: Smart phone
Networking (LAN, Ad hoc)
Capturing (Scanner, Microphone)
Object Transfer (v-Inbox, v-Folder)
Audio (Speaker, Microphone, Headset)
Telephony (Cordless telephony, Modem, Headset)
Link type: eSCO (0x02)
< HCI Command: Accept Synchronous Co.. (0x01|0x0029) plen 21
Address: 48:9D:24:1F:4D:1D (BlackBerry RTS)
Transmit bandwidth: 8000
Receive bandwidth: 8000
Max latency: 7
Setting: 0x0060
Input Coding: Linear
Input Data Format: 2's complement
Input Sample Size: 16-bit
# of bits padding at MSB: 0
Air Coding Format: CVSD
Retransmission effort: Optimize for power consumption (0x01)
Packet type: 0x0006
HV2 may be used
HV3 may be used
> HCI Event: Command Status (0x0f) plen 4 [hci0] 126.205171
Accept Synchronous Connection Request (0x01|0x0029) ncmd 1
Status: Success (0x00)
Change-Id: I71597aef94e945a9c07be1960994ad20c1b44bb3
Signed-off-by: Sathish Narasimman <sathish.narasimman@intel.com>
2017-02-15 14:29:11 +05:30
|
|
|
bt_esco_conn_req(evt);
|
2016-01-21 09:31:09 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
conn = bt_conn_add_br(&evt->bdaddr);
|
|
|
|
if (!conn) {
|
|
|
|
reject_conn(&evt->bdaddr, BT_HCI_ERR_INSUFFICIENT_RESOURCES);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
accept_conn(&evt->bdaddr);
|
|
|
|
conn->role = BT_HCI_ROLE_SLAVE;
|
|
|
|
bt_conn_set_state(conn, BT_CONN_CONNECT);
|
|
|
|
bt_conn_unref(conn);
|
|
|
|
}
|
|
|
|
|
2016-01-21 09:42:05 +01:00
|
|
|
static void update_sec_level_br(struct bt_conn *conn)
|
|
|
|
{
|
|
|
|
if (!conn->encrypt) {
|
|
|
|
conn->sec_level = BT_SECURITY_LOW;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-08-08 16:40:30 +02:00
|
|
|
if (conn->br.link_key) {
|
|
|
|
if (atomic_test_bit(conn->br.link_key->flags,
|
|
|
|
BT_LINK_KEY_AUTHENTICATED)) {
|
2016-08-12 14:11:57 +02:00
|
|
|
if (conn->encrypt == 0x02) {
|
|
|
|
conn->sec_level = BT_SECURITY_FIPS;
|
|
|
|
} else {
|
|
|
|
conn->sec_level = BT_SECURITY_HIGH;
|
|
|
|
}
|
2016-08-08 16:40:30 +02:00
|
|
|
} else {
|
|
|
|
conn->sec_level = BT_SECURITY_MEDIUM;
|
2016-01-21 09:42:05 +01:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
BT_WARN("No BR/EDR link key found");
|
|
|
|
conn->sec_level = BT_SECURITY_MEDIUM;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (conn->required_sec_level > conn->sec_level) {
|
|
|
|
BT_ERR("Failed to set required security level");
|
|
|
|
bt_conn_disconnect(conn, BT_HCI_ERR_AUTHENTICATION_FAIL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-15 15:08:25 +05:30
|
|
|
static void synchronous_conn_complete(struct net_buf *buf)
|
|
|
|
{
|
|
|
|
struct bt_hci_evt_sync_conn_complete *evt = (void *)buf->data;
|
|
|
|
struct bt_conn *sco_conn;
|
2017-04-20 12:00:29 -05:00
|
|
|
u16_t handle = sys_le16_to_cpu(evt->handle);
|
2017-02-15 15:08:25 +05:30
|
|
|
|
|
|
|
BT_DBG("status 0x%02x, handle %u, type 0x%02x", evt->status, handle,
|
|
|
|
evt->link_type);
|
|
|
|
|
|
|
|
sco_conn = bt_conn_lookup_addr_sco(&evt->bdaddr);
|
|
|
|
if (!sco_conn) {
|
|
|
|
BT_ERR("Unable to find conn for %s", bt_addr_str(&evt->bdaddr));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (evt->status) {
|
|
|
|
sco_conn->err = evt->status;
|
|
|
|
bt_conn_set_state(sco_conn, BT_CONN_DISCONNECTED);
|
|
|
|
bt_conn_unref(sco_conn);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
sco_conn->handle = handle;
|
|
|
|
bt_conn_set_state(sco_conn, BT_CONN_CONNECTED);
|
|
|
|
bt_conn_unref(sco_conn);
|
|
|
|
}
|
|
|
|
|
2016-01-21 09:31:09 +01:00
|
|
|
static void conn_complete(struct net_buf *buf)
|
|
|
|
{
|
|
|
|
struct bt_hci_evt_conn_complete *evt = (void *)buf->data;
|
|
|
|
struct bt_conn *conn;
|
2016-06-17 21:27:41 +02:00
|
|
|
struct bt_hci_cp_read_remote_features *cp;
|
2017-04-20 12:00:29 -05:00
|
|
|
u16_t handle = sys_le16_to_cpu(evt->handle);
|
2016-01-21 09:31:09 +01:00
|
|
|
|
|
|
|
BT_DBG("status 0x%02x, handle %u, type 0x%02x", evt->status, handle,
|
|
|
|
evt->link_type);
|
|
|
|
|
|
|
|
conn = bt_conn_lookup_addr_br(&evt->bdaddr);
|
|
|
|
if (!conn) {
|
|
|
|
BT_ERR("Unable to find conn for %s", bt_addr_str(&evt->bdaddr));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (evt->status) {
|
|
|
|
conn->err = evt->status;
|
|
|
|
bt_conn_set_state(conn, BT_CONN_DISCONNECTED);
|
|
|
|
bt_conn_unref(conn);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
conn->handle = handle;
|
2016-01-21 09:42:05 +01:00
|
|
|
conn->encrypt = evt->encr_enabled;
|
|
|
|
update_sec_level_br(conn);
|
2016-01-21 09:31:09 +01:00
|
|
|
bt_conn_set_state(conn, BT_CONN_CONNECTED);
|
|
|
|
bt_conn_unref(conn);
|
2016-06-17 21:27:41 +02:00
|
|
|
|
|
|
|
buf = bt_hci_cmd_create(BT_HCI_OP_READ_REMOTE_FEATURES, sizeof(*cp));
|
|
|
|
if (!buf) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
cp = net_buf_add(buf, sizeof(*cp));
|
|
|
|
cp->handle = evt->handle;
|
|
|
|
|
|
|
|
bt_hci_cmd_send_sync(BT_HCI_OP_READ_REMOTE_FEATURES, buf, NULL);
|
2016-01-21 09:31:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void pin_code_req(struct net_buf *buf)
|
|
|
|
{
|
|
|
|
struct bt_hci_evt_pin_code_req *evt = (void *)buf->data;
|
|
|
|
struct bt_conn *conn;
|
|
|
|
|
|
|
|
BT_DBG("");
|
|
|
|
|
|
|
|
conn = bt_conn_lookup_addr_br(&evt->bdaddr);
|
|
|
|
if (!conn) {
|
|
|
|
BT_ERR("Can't find conn for %s", bt_addr_str(&evt->bdaddr));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
bt_conn_pin_code_req(conn);
|
|
|
|
bt_conn_unref(conn);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void link_key_notify(struct net_buf *buf)
|
|
|
|
{
|
2017-04-27 15:22:53 +02:00
|
|
|
struct bt_hci_evt_link_key_notify *evt = (void *)buf->data;
|
2016-01-21 09:31:09 +01:00
|
|
|
struct bt_conn *conn;
|
|
|
|
|
|
|
|
conn = bt_conn_lookup_addr_br(&evt->bdaddr);
|
|
|
|
if (!conn) {
|
|
|
|
BT_ERR("Can't find conn for %s", bt_addr_str(&evt->bdaddr));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
BT_DBG("%s, link type 0x%02x", bt_addr_str(&evt->bdaddr), evt->key_type);
|
|
|
|
|
2016-08-08 16:40:30 +02:00
|
|
|
if (!conn->br.link_key) {
|
|
|
|
conn->br.link_key = bt_keys_get_link_key(&evt->bdaddr);
|
2016-01-21 09:31:09 +01:00
|
|
|
}
|
2016-08-08 16:40:30 +02:00
|
|
|
if (!conn->br.link_key) {
|
2016-01-21 09:31:09 +01:00
|
|
|
BT_ERR("Can't update keys for %s", bt_addr_str(&evt->bdaddr));
|
|
|
|
bt_conn_unref(conn);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-08-24 10:51:31 +02:00
|
|
|
/* clear any old Link Key flags */
|
|
|
|
atomic_set(conn->br.link_key->flags, 0);
|
|
|
|
|
2016-03-22 18:58:56 +01:00
|
|
|
switch (evt->key_type) {
|
|
|
|
case BT_LK_COMBINATION:
|
2016-01-21 09:31:09 +01:00
|
|
|
/*
|
|
|
|
* Setting Combination Link Key as AUTHENTICATED means it was
|
|
|
|
* successfully generated by 16 digits wide PIN code.
|
|
|
|
*/
|
|
|
|
if (atomic_test_and_clear_bit(conn->flags,
|
|
|
|
BT_CONN_BR_LEGACY_SECURE)) {
|
2016-08-08 16:40:30 +02:00
|
|
|
atomic_set_bit(conn->br.link_key->flags,
|
|
|
|
BT_LINK_KEY_AUTHENTICATED);
|
2016-01-21 09:31:09 +01:00
|
|
|
}
|
2016-08-08 16:40:30 +02:00
|
|
|
memcpy(conn->br.link_key->val, evt->link_key, 16);
|
2016-03-22 18:58:56 +01:00
|
|
|
break;
|
|
|
|
case BT_LK_AUTH_COMBINATION_P192:
|
2016-08-24 10:51:31 +02:00
|
|
|
atomic_set_bit(conn->br.link_key->flags,
|
|
|
|
BT_LINK_KEY_AUTHENTICATED);
|
|
|
|
/* fall through */
|
|
|
|
case BT_LK_UNAUTH_COMBINATION_P192:
|
|
|
|
/* Mark no-bond so that link-key is removed on disconnection */
|
|
|
|
if (bt_conn_ssp_get_auth(conn) < BT_HCI_DEDICATED_BONDING) {
|
2016-03-22 18:58:56 +01:00
|
|
|
atomic_set_bit(conn->flags, BT_CONN_BR_NOBOND);
|
|
|
|
}
|
2016-08-24 10:51:31 +02:00
|
|
|
|
2016-08-24 10:55:59 +02:00
|
|
|
memcpy(conn->br.link_key->val, evt->link_key, 16);
|
|
|
|
break;
|
|
|
|
case BT_LK_AUTH_COMBINATION_P256:
|
|
|
|
atomic_set_bit(conn->br.link_key->flags,
|
|
|
|
BT_LINK_KEY_AUTHENTICATED);
|
|
|
|
/* fall through */
|
|
|
|
case BT_LK_UNAUTH_COMBINATION_P256:
|
|
|
|
atomic_set_bit(conn->br.link_key->flags, BT_LINK_KEY_SC);
|
|
|
|
|
|
|
|
/* Mark no-bond so that link-key is removed on disconnection */
|
|
|
|
if (bt_conn_ssp_get_auth(conn) < BT_HCI_DEDICATED_BONDING) {
|
|
|
|
atomic_set_bit(conn->flags, BT_CONN_BR_NOBOND);
|
|
|
|
}
|
|
|
|
|
2016-08-24 10:51:31 +02:00
|
|
|
memcpy(conn->br.link_key->val, evt->link_key, 16);
|
2016-03-22 18:58:56 +01:00
|
|
|
break;
|
|
|
|
default:
|
2016-08-24 10:51:31 +02:00
|
|
|
BT_WARN("Unsupported Link Key type %u", evt->key_type);
|
|
|
|
memset(conn->br.link_key->val, 0,
|
|
|
|
sizeof(conn->br.link_key->val));
|
2016-03-22 18:58:56 +01:00
|
|
|
break;
|
2016-01-21 09:31:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bt_conn_unref(conn);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void link_key_neg_reply(const bt_addr_t *bdaddr)
|
|
|
|
{
|
|
|
|
struct bt_hci_cp_link_key_neg_reply *cp;
|
|
|
|
struct net_buf *buf;
|
|
|
|
|
|
|
|
BT_DBG("");
|
|
|
|
|
|
|
|
buf = bt_hci_cmd_create(BT_HCI_OP_LINK_KEY_NEG_REPLY, sizeof(*cp));
|
|
|
|
if (!buf) {
|
|
|
|
BT_ERR("Out of command buffers");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
cp = net_buf_add(buf, sizeof(*cp));
|
|
|
|
bt_addr_copy(&cp->bdaddr, bdaddr);
|
|
|
|
bt_hci_cmd_send_sync(BT_HCI_OP_LINK_KEY_NEG_REPLY, buf, NULL);
|
|
|
|
}
|
|
|
|
|
2017-04-20 12:00:29 -05:00
|
|
|
static void link_key_reply(const bt_addr_t *bdaddr, const u8_t *lk)
|
2016-01-21 09:31:09 +01:00
|
|
|
{
|
|
|
|
struct bt_hci_cp_link_key_reply *cp;
|
|
|
|
struct net_buf *buf;
|
|
|
|
|
|
|
|
BT_DBG("");
|
|
|
|
|
|
|
|
buf = bt_hci_cmd_create(BT_HCI_OP_LINK_KEY_REPLY, sizeof(*cp));
|
|
|
|
if (!buf) {
|
|
|
|
BT_ERR("Out of command buffers");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
cp = net_buf_add(buf, sizeof(*cp));
|
|
|
|
bt_addr_copy(&cp->bdaddr, bdaddr);
|
|
|
|
memcpy(cp->link_key, lk, 16);
|
|
|
|
bt_hci_cmd_send_sync(BT_HCI_OP_LINK_KEY_REPLY, buf, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void link_key_req(struct net_buf *buf)
|
|
|
|
{
|
|
|
|
struct bt_hci_evt_link_key_req *evt = (void *)buf->data;
|
2016-03-03 11:15:49 +01:00
|
|
|
struct bt_conn *conn;
|
2016-01-21 09:31:09 +01:00
|
|
|
|
|
|
|
BT_DBG("%s", bt_addr_str(&evt->bdaddr));
|
|
|
|
|
2016-03-03 11:15:49 +01:00
|
|
|
conn = bt_conn_lookup_addr_br(&evt->bdaddr);
|
|
|
|
if (!conn) {
|
|
|
|
BT_ERR("Can't find conn for %s", bt_addr_str(&evt->bdaddr));
|
2016-01-21 09:31:09 +01:00
|
|
|
link_key_neg_reply(&evt->bdaddr);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-08-08 16:40:30 +02:00
|
|
|
if (!conn->br.link_key) {
|
|
|
|
conn->br.link_key = bt_keys_find_link_key(&evt->bdaddr);
|
2016-03-03 11:15:49 +01:00
|
|
|
}
|
|
|
|
|
2016-08-08 16:40:30 +02:00
|
|
|
if (!conn->br.link_key) {
|
2016-03-03 11:15:49 +01:00
|
|
|
link_key_neg_reply(&evt->bdaddr);
|
|
|
|
bt_conn_unref(conn);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-03-18 14:13:23 +01:00
|
|
|
/*
|
|
|
|
* Enforce regenerate by controller stronger link key since found one
|
|
|
|
* in database not covers requested security level.
|
|
|
|
*/
|
2016-08-08 16:40:30 +02:00
|
|
|
if (!atomic_test_bit(conn->br.link_key->flags,
|
|
|
|
BT_LINK_KEY_AUTHENTICATED) &&
|
2016-03-18 14:13:23 +01:00
|
|
|
conn->required_sec_level > BT_SECURITY_MEDIUM) {
|
|
|
|
link_key_neg_reply(&evt->bdaddr);
|
|
|
|
bt_conn_unref(conn);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-08-08 16:40:30 +02:00
|
|
|
link_key_reply(&evt->bdaddr, conn->br.link_key->val);
|
2016-03-03 11:15:49 +01:00
|
|
|
bt_conn_unref(conn);
|
2016-01-21 09:31:09 +01:00
|
|
|
}
|
2016-01-29 12:29:11 +01:00
|
|
|
|
2017-04-20 12:00:29 -05:00
|
|
|
static void io_capa_neg_reply(const bt_addr_t *bdaddr, const u8_t reason)
|
2016-03-14 15:19:23 +01:00
|
|
|
{
|
|
|
|
struct bt_hci_cp_io_capability_neg_reply *cp;
|
|
|
|
struct net_buf *resp_buf;
|
|
|
|
|
|
|
|
resp_buf = bt_hci_cmd_create(BT_HCI_OP_IO_CAPABILITY_NEG_REPLY,
|
|
|
|
sizeof(*cp));
|
|
|
|
if (!resp_buf) {
|
|
|
|
BT_ERR("Out of command buffers");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
cp = net_buf_add(resp_buf, sizeof(*cp));
|
|
|
|
bt_addr_copy(&cp->bdaddr, bdaddr);
|
|
|
|
cp->reason = reason;
|
|
|
|
bt_hci_cmd_send_sync(BT_HCI_OP_IO_CAPABILITY_NEG_REPLY, resp_buf, NULL);
|
|
|
|
}
|
|
|
|
|
2016-01-29 12:29:11 +01:00
|
|
|
static void io_capa_resp(struct net_buf *buf)
|
|
|
|
{
|
|
|
|
struct bt_hci_evt_io_capa_resp *evt = (void *)buf->data;
|
|
|
|
struct bt_conn *conn;
|
|
|
|
|
|
|
|
BT_DBG("remote %s, IOcapa 0x%02x, auth 0x%02x",
|
|
|
|
bt_addr_str(&evt->bdaddr), evt->capability, evt->authentication);
|
|
|
|
|
2016-03-14 15:19:23 +01:00
|
|
|
if (evt->authentication > BT_HCI_GENERAL_BONDING_MITM) {
|
|
|
|
BT_ERR("Invalid remote authentication requirements");
|
|
|
|
io_capa_neg_reply(&evt->bdaddr,
|
2017-04-11 08:39:58 +02:00
|
|
|
BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL);
|
2016-03-14 15:19:23 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (evt->capability > BT_IO_NO_INPUT_OUTPUT) {
|
|
|
|
BT_ERR("Invalid remote io capability requirements");
|
|
|
|
io_capa_neg_reply(&evt->bdaddr,
|
2017-04-11 08:39:58 +02:00
|
|
|
BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL);
|
2016-03-14 15:19:23 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-01-29 12:29:11 +01:00
|
|
|
conn = bt_conn_lookup_addr_br(&evt->bdaddr);
|
|
|
|
if (!conn) {
|
|
|
|
BT_ERR("Unable to find conn for %s", bt_addr_str(&evt->bdaddr));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
conn->br.remote_io_capa = evt->capability;
|
|
|
|
conn->br.remote_auth = evt->authentication;
|
2016-01-29 16:12:55 +01:00
|
|
|
atomic_set_bit(conn->flags, BT_CONN_BR_PAIRING);
|
2016-01-29 12:29:11 +01:00
|
|
|
bt_conn_unref(conn);
|
|
|
|
}
|
2016-01-29 13:08:59 +01:00
|
|
|
|
|
|
|
static void io_capa_req(struct net_buf *buf)
|
|
|
|
{
|
|
|
|
struct bt_hci_evt_io_capa_req *evt = (void *)buf->data;
|
|
|
|
struct net_buf *resp_buf;
|
2016-01-29 16:12:55 +01:00
|
|
|
struct bt_conn *conn;
|
|
|
|
struct bt_hci_cp_io_capability_reply *cp;
|
2017-04-20 12:00:29 -05:00
|
|
|
u8_t auth;
|
2016-01-29 13:08:59 +01:00
|
|
|
|
|
|
|
BT_DBG("");
|
|
|
|
|
2016-01-29 16:12:55 +01:00
|
|
|
conn = bt_conn_lookup_addr_br(&evt->bdaddr);
|
|
|
|
if (!conn) {
|
|
|
|
BT_ERR("Can't find conn for %s", bt_addr_str(&evt->bdaddr));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
resp_buf = bt_hci_cmd_create(BT_HCI_OP_IO_CAPABILITY_REPLY,
|
2016-01-29 13:08:59 +01:00
|
|
|
sizeof(*cp));
|
|
|
|
if (!resp_buf) {
|
2016-01-29 16:12:55 +01:00
|
|
|
BT_ERR("Out of command buffers");
|
|
|
|
bt_conn_unref(conn);
|
2016-01-29 13:08:59 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-03-18 14:13:23 +01:00
|
|
|
/*
|
|
|
|
* Set authentication requirements when acting as pairing initiator to
|
|
|
|
* 'dedicated bond' with MITM protection set if local IO capa
|
|
|
|
* potentially allows it, and for acceptor, based on local IO capa and
|
|
|
|
* remote's authentication set.
|
|
|
|
*/
|
|
|
|
if (atomic_test_bit(conn->flags, BT_CONN_BR_PAIRING_INITIATOR)) {
|
|
|
|
if (bt_conn_get_io_capa() != BT_IO_NO_INPUT_OUTPUT) {
|
|
|
|
auth = BT_HCI_DEDICATED_BONDING_MITM;
|
|
|
|
} else {
|
|
|
|
auth = BT_HCI_DEDICATED_BONDING;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
auth = bt_conn_ssp_get_auth(conn);
|
|
|
|
}
|
|
|
|
|
2016-01-29 13:08:59 +01:00
|
|
|
cp = net_buf_add(resp_buf, sizeof(*cp));
|
|
|
|
bt_addr_copy(&cp->bdaddr, &evt->bdaddr);
|
2016-01-29 16:12:55 +01:00
|
|
|
cp->capability = bt_conn_get_io_capa();
|
2016-03-18 14:13:23 +01:00
|
|
|
cp->authentication = auth;
|
2016-01-29 16:12:55 +01:00
|
|
|
cp->oob_data = 0;
|
|
|
|
bt_hci_cmd_send_sync(BT_HCI_OP_IO_CAPABILITY_REPLY, resp_buf, NULL);
|
|
|
|
bt_conn_unref(conn);
|
2016-01-29 13:08:59 +01:00
|
|
|
}
|
2016-01-29 13:29:54 +01:00
|
|
|
|
|
|
|
static void ssp_complete(struct net_buf *buf)
|
|
|
|
{
|
|
|
|
struct bt_hci_evt_ssp_complete *evt = (void *)buf->data;
|
|
|
|
struct bt_conn *conn;
|
|
|
|
|
|
|
|
BT_DBG("status %u", evt->status);
|
|
|
|
|
|
|
|
conn = bt_conn_lookup_addr_br(&evt->bdaddr);
|
|
|
|
if (!conn) {
|
|
|
|
BT_ERR("Can't find conn for %s", bt_addr_str(&evt->bdaddr));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (evt->status) {
|
|
|
|
bt_conn_disconnect(conn, BT_HCI_ERR_AUTHENTICATION_FAIL);
|
|
|
|
}
|
|
|
|
|
|
|
|
bt_conn_unref(conn);
|
|
|
|
}
|
2016-02-01 12:41:04 +01:00
|
|
|
|
|
|
|
static void user_confirm_req(struct net_buf *buf)
|
|
|
|
{
|
|
|
|
struct bt_hci_evt_user_confirm_req *evt = (void *)buf->data;
|
|
|
|
struct bt_conn *conn;
|
|
|
|
|
|
|
|
conn = bt_conn_lookup_addr_br(&evt->bdaddr);
|
|
|
|
if (!conn) {
|
|
|
|
BT_ERR("Can't find conn for %s", bt_addr_str(&evt->bdaddr));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
bt_conn_ssp_auth(conn, sys_le32_to_cpu(evt->passkey));
|
|
|
|
bt_conn_unref(conn);
|
|
|
|
}
|
2016-02-24 14:47:01 +01:00
|
|
|
|
|
|
|
static void user_passkey_notify(struct net_buf *buf)
|
|
|
|
{
|
|
|
|
struct bt_hci_evt_user_passkey_notify *evt = (void *)buf->data;
|
|
|
|
struct bt_conn *conn;
|
|
|
|
|
|
|
|
BT_DBG("");
|
|
|
|
|
|
|
|
conn = bt_conn_lookup_addr_br(&evt->bdaddr);
|
|
|
|
if (!conn) {
|
|
|
|
BT_ERR("Can't find conn for %s", bt_addr_str(&evt->bdaddr));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
bt_conn_ssp_auth(conn, sys_le32_to_cpu(evt->passkey));
|
|
|
|
bt_conn_unref(conn);
|
|
|
|
}
|
2016-02-24 14:58:03 +01:00
|
|
|
|
|
|
|
static void user_passkey_req(struct net_buf *buf)
|
|
|
|
{
|
|
|
|
struct bt_hci_evt_user_passkey_req *evt = (void *)buf->data;
|
|
|
|
struct bt_conn *conn;
|
|
|
|
|
|
|
|
conn = bt_conn_lookup_addr_br(&evt->bdaddr);
|
|
|
|
if (!conn) {
|
|
|
|
BT_ERR("Can't find conn for %s", bt_addr_str(&evt->bdaddr));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
bt_conn_ssp_auth(conn, 0);
|
|
|
|
bt_conn_unref(conn);
|
|
|
|
}
|
2016-03-10 11:58:56 +01:00
|
|
|
|
2016-03-17 18:35:58 +01:00
|
|
|
struct discovery_priv {
|
2017-04-20 12:00:29 -05:00
|
|
|
u16_t clock_offset;
|
|
|
|
u8_t pscan_rep_mode;
|
|
|
|
u8_t resolving;
|
2016-03-17 18:35:58 +01:00
|
|
|
} __packed;
|
|
|
|
|
2017-04-20 12:00:29 -05:00
|
|
|
static int request_name(const bt_addr_t *addr, u8_t pscan, u16_t offset)
|
2016-03-17 18:35:58 +01:00
|
|
|
{
|
|
|
|
struct bt_hci_cp_remote_name_request *cp;
|
|
|
|
struct net_buf *buf;
|
|
|
|
|
|
|
|
buf = bt_hci_cmd_create(BT_HCI_OP_REMOTE_NAME_REQUEST, sizeof(*cp));
|
|
|
|
if (!buf) {
|
|
|
|
return -ENOBUFS;
|
|
|
|
}
|
|
|
|
|
|
|
|
cp = net_buf_add(buf, sizeof(*cp));
|
|
|
|
|
|
|
|
bt_addr_copy(&cp->bdaddr, addr);
|
|
|
|
cp->pscan_rep_mode = pscan;
|
|
|
|
cp->reserved = 0x00; /* reserver, should be set to 0x00 */
|
|
|
|
cp->clock_offset = offset;
|
|
|
|
|
|
|
|
return bt_hci_cmd_send_sync(BT_HCI_OP_REMOTE_NAME_REQUEST, buf, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
#define EIR_SHORT_NAME 0x08
|
|
|
|
#define EIR_COMPLETE_NAME 0x09
|
|
|
|
|
2017-04-20 12:00:29 -05:00
|
|
|
static bool eir_has_name(const u8_t *eir)
|
2016-03-17 18:35:58 +01:00
|
|
|
{
|
|
|
|
int len = 240;
|
|
|
|
|
|
|
|
while (len) {
|
|
|
|
if (len < 2) {
|
|
|
|
break;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Look for early termination */
|
|
|
|
if (!eir[0]) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check if field length is correct */
|
|
|
|
if (eir[0] > len - 1) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (eir[1]) {
|
|
|
|
case EIR_SHORT_NAME:
|
|
|
|
case EIR_COMPLETE_NAME:
|
|
|
|
if (eir[0] > 1) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Parse next AD Structure */
|
|
|
|
len -= eir[0] + 1;
|
|
|
|
eir += eir[0] + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-03-10 12:03:55 +01:00
|
|
|
static void report_discovery_results(void)
|
|
|
|
{
|
2016-03-17 18:35:58 +01:00
|
|
|
bool resolving_names = false;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < discovery_results_count; i++) {
|
|
|
|
struct discovery_priv *priv;
|
|
|
|
|
2016-11-08 12:21:46 +02:00
|
|
|
priv = (struct discovery_priv *)&discovery_results[i]._priv;
|
2016-03-17 18:35:58 +01:00
|
|
|
|
|
|
|
if (eir_has_name(discovery_results[i].eir)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (request_name(&discovery_results[i].addr,
|
|
|
|
priv->pscan_rep_mode, priv->clock_offset)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
priv->resolving = 1;
|
|
|
|
resolving_names = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (resolving_names) {
|
|
|
|
return;
|
|
|
|
}
|
2016-03-10 12:03:55 +01:00
|
|
|
|
|
|
|
atomic_clear_bit(bt_dev.flags, BT_DEV_INQUIRY);
|
|
|
|
|
|
|
|
discovery_cb(discovery_results, discovery_results_count);
|
|
|
|
|
|
|
|
discovery_cb = NULL;
|
|
|
|
discovery_results = NULL;
|
|
|
|
discovery_results_size = 0;
|
|
|
|
discovery_results_count = 0;
|
|
|
|
}
|
|
|
|
|
2016-03-10 11:58:56 +01:00
|
|
|
static void inquiry_complete(struct net_buf *buf)
|
|
|
|
{
|
|
|
|
struct bt_hci_evt_inquiry_complete *evt = (void *)buf->data;
|
|
|
|
|
|
|
|
if (evt->status) {
|
|
|
|
BT_ERR("Failed to complete inquiry");
|
|
|
|
}
|
2016-03-10 12:03:55 +01:00
|
|
|
|
|
|
|
report_discovery_results();
|
|
|
|
}
|
|
|
|
|
2016-12-19 18:02:41 +01:00
|
|
|
static struct bt_br_discovery_result *get_result_slot(const bt_addr_t *addr,
|
2017-04-20 12:00:29 -05:00
|
|
|
s8_t rssi)
|
2016-03-10 12:03:55 +01:00
|
|
|
{
|
2016-12-19 18:02:41 +01:00
|
|
|
struct bt_br_discovery_result *result = NULL;
|
2016-03-10 12:03:55 +01:00
|
|
|
size_t i;
|
|
|
|
|
|
|
|
/* check if already present in results */
|
|
|
|
for (i = 0; i < discovery_results_count; i++) {
|
|
|
|
if (!bt_addr_cmp(addr, &discovery_results[i].addr)) {
|
|
|
|
return &discovery_results[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-16 10:29:18 +03:00
|
|
|
/* Pick a new slot (if available) */
|
2016-03-10 12:03:55 +01:00
|
|
|
if (discovery_results_count < discovery_results_size) {
|
|
|
|
bt_addr_copy(&discovery_results[discovery_results_count].addr,
|
|
|
|
addr);
|
|
|
|
return &discovery_results[discovery_results_count++];
|
|
|
|
}
|
|
|
|
|
2016-12-19 18:02:41 +01:00
|
|
|
/* ignore if invalid RSSI */
|
|
|
|
if (rssi == 0xff) {
|
2016-06-16 10:29:18 +03:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2016-12-19 18:02:41 +01:00
|
|
|
/*
|
|
|
|
* Pick slot with smallest RSSI that is smaller then passed RSSI
|
|
|
|
* TODO handle TX if present
|
|
|
|
*/
|
|
|
|
for (i = 0; i < discovery_results_size; i++) {
|
|
|
|
if (discovery_results[i].rssi > rssi) {
|
|
|
|
continue;
|
|
|
|
}
|
2016-03-10 12:03:55 +01:00
|
|
|
|
2016-12-19 18:02:41 +01:00
|
|
|
if (!result || result->rssi > discovery_results[i].rssi) {
|
|
|
|
result = &discovery_results[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (result) {
|
|
|
|
BT_DBG("Reusing slot (old %s rssi %d dBm)",
|
|
|
|
bt_addr_str(&result->addr), result->rssi);
|
|
|
|
|
|
|
|
bt_addr_copy(&result->addr, addr);
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
2016-03-10 12:03:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void inquiry_result_with_rssi(struct net_buf *buf)
|
|
|
|
{
|
|
|
|
struct bt_hci_evt_inquiry_result_with_rssi *evt;
|
2017-04-20 12:00:29 -05:00
|
|
|
u8_t num_reports = net_buf_pull_u8(buf);
|
2016-03-10 12:03:55 +01:00
|
|
|
|
|
|
|
if (!atomic_test_bit(bt_dev.flags, BT_DEV_INQUIRY)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
BT_DBG("number of results: %u", num_reports);
|
|
|
|
|
|
|
|
evt = (void *)buf->data;
|
|
|
|
while (num_reports--) {
|
|
|
|
struct bt_br_discovery_result *result;
|
2016-03-17 18:35:58 +01:00
|
|
|
struct discovery_priv *priv;
|
2016-03-10 12:03:55 +01:00
|
|
|
|
|
|
|
BT_DBG("%s rssi %d dBm", bt_addr_str(&evt->addr), evt->rssi);
|
|
|
|
|
2016-12-19 18:02:41 +01:00
|
|
|
result = get_result_slot(&evt->addr, evt->rssi);
|
2016-03-10 12:03:55 +01:00
|
|
|
if (!result) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-11-08 12:21:46 +02:00
|
|
|
priv = (struct discovery_priv *)&result->_priv;
|
2016-03-17 18:35:58 +01:00
|
|
|
priv->pscan_rep_mode = evt->pscan_rep_mode;
|
|
|
|
priv->clock_offset = evt->clock_offset;
|
|
|
|
|
2016-03-10 12:03:55 +01:00
|
|
|
memcpy(result->cod, evt->cod, 3);
|
|
|
|
result->rssi = evt->rssi;
|
|
|
|
|
2016-12-19 18:02:41 +01:00
|
|
|
/* we could reuse slot so make sure EIR is cleared */
|
|
|
|
memset(result->eir, 0, sizeof(result->eir));
|
|
|
|
|
2016-03-10 12:03:55 +01:00
|
|
|
/*
|
|
|
|
* Get next report iteration by moving pointer to right offset
|
|
|
|
* in buf according to spec 4.2, Vol 2, Part E, 7.7.33.
|
|
|
|
*/
|
|
|
|
evt = net_buf_pull(buf, sizeof(*evt));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void extended_inquiry_result(struct net_buf *buf)
|
|
|
|
{
|
|
|
|
struct bt_hci_evt_extended_inquiry_result *evt = (void *)buf->data;
|
|
|
|
struct bt_br_discovery_result *result;
|
2016-03-17 18:35:58 +01:00
|
|
|
struct discovery_priv *priv;
|
2016-03-10 12:03:55 +01:00
|
|
|
|
|
|
|
if (!atomic_test_bit(bt_dev.flags, BT_DEV_INQUIRY)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
BT_DBG("%s rssi %d dBm", bt_addr_str(&evt->addr), evt->rssi);
|
|
|
|
|
2016-12-19 18:02:41 +01:00
|
|
|
result = get_result_slot(&evt->addr, evt->rssi);
|
2016-03-10 12:03:55 +01:00
|
|
|
if (!result) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-11-08 12:21:46 +02:00
|
|
|
priv = (struct discovery_priv *)&result->_priv;
|
2016-03-17 18:35:58 +01:00
|
|
|
priv->pscan_rep_mode = evt->pscan_rep_mode;
|
|
|
|
priv->clock_offset = evt->clock_offset;
|
|
|
|
|
2016-03-10 12:03:55 +01:00
|
|
|
result->rssi = evt->rssi;
|
|
|
|
memcpy(result->cod, evt->cod, 3);
|
|
|
|
memcpy(result->eir, evt->eir, sizeof(result->eir));
|
2016-03-10 11:58:56 +01:00
|
|
|
}
|
2016-03-17 18:35:58 +01:00
|
|
|
|
2016-06-16 10:55:17 +03:00
|
|
|
static void remote_name_request_complete(struct net_buf *buf)
|
2016-03-17 18:35:58 +01:00
|
|
|
{
|
|
|
|
struct bt_hci_evt_remote_name_req_complete *evt = (void *)buf->data;
|
|
|
|
struct bt_br_discovery_result *result;
|
|
|
|
struct discovery_priv *priv;
|
|
|
|
int eir_len = 240;
|
2017-04-20 12:00:29 -05:00
|
|
|
u8_t *eir;
|
2016-03-17 18:35:58 +01:00
|
|
|
int i;
|
|
|
|
|
2016-12-19 18:02:41 +01:00
|
|
|
result = get_result_slot(&evt->bdaddr, 0xff);
|
2016-03-17 18:35:58 +01:00
|
|
|
if (!result) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-11-08 12:21:46 +02:00
|
|
|
priv = (struct discovery_priv *)&result->_priv;
|
2016-03-17 18:35:58 +01:00
|
|
|
priv->resolving = 0;
|
|
|
|
|
|
|
|
if (evt->status) {
|
|
|
|
goto check_names;
|
|
|
|
}
|
|
|
|
|
|
|
|
eir = result->eir;
|
|
|
|
|
|
|
|
while (eir_len) {
|
|
|
|
if (eir_len < 2) {
|
|
|
|
break;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Look for early termination */
|
|
|
|
if (!eir[0]) {
|
|
|
|
size_t name_len;
|
|
|
|
|
|
|
|
eir_len -= 2;
|
|
|
|
|
|
|
|
/* name is null terminated */
|
Bluetooth: Fix compiler warnings/errors related to string casts
Fix the following compiler warnings/errors that show up with llvm:
tests/bluetooth/shell/src/main.c:594:2: error:
initializing 'const uint8_t *' (aka 'const unsigned char *') with an
expression of type 'char [11]' converts between pointers to integer types
with different sign [-Werror,-Wpointer-sign]
BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/bluetooth/bluetooth.h:93:11: note: expanded
from macro 'BT_DATA'
.data = (_data), \
^~~~~~~
1 error generated.
net/bluetooth/hci_core.c:1759:22: error: passing
'uint8_t [248]' to parameter of type 'const char *' converts between
pointers to integer types with different sign [-Werror,-Wpointer-sign]
name_len = strlen(evt->name);
^~~~~~~~~
lib/libc/minimal/include/string.h:32:34: note: passing
argument to parameter 's' here
extern size_t strlen(const char *s);
^
CC net/bluetooth/log.o
net/bluetooth/hci_core.c:3136:10: error: passing
'uint8_t [248]' to parameter of type 'char *' converts between pointers to
integer types with different sign [-Werror,-Wpointer-sign]
strncpy(name_cp->local_name, CONFIG_BLUETOOTH_BREDR_NAME,
^~~~~~~~~~~~~~~~~~~
lib/libc/minimal/include/string.h:30:39: note: passing
argument to parameter 'd' here
extern char *strncpy(char *_Restrict d, const char *_Restrict s, size_t n);
net/bluetooth/conn.c:301:10: error: passing
'uint8_t [16]' to parameter of type 'char *' converts between pointers to
integer types with different sign [-Werror,-Wpointer-sign]
strncpy(cp->pin_code, pin, sizeof(cp->pin_code));
^~~~~~~~~~~~
lib/libc/minimal/include/string.h:30:39: note: passing
argument to parameter 'd' here
extern char *strncpy(char *_Restrict d, const char *_Restrict s, size_t n);
Change-Id: I342131c6c2b25445382b2317d673561c4087096b
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2016-10-04 10:21:42 +03:00
|
|
|
name_len = strlen((const char *)evt->name);
|
2016-03-17 18:35:58 +01:00
|
|
|
|
|
|
|
if (name_len > eir_len) {
|
|
|
|
eir[0] = eir_len + 1;
|
|
|
|
eir[1] = EIR_SHORT_NAME;
|
|
|
|
} else {
|
|
|
|
eir[0] = name_len + 1;
|
|
|
|
eir[1] = EIR_SHORT_NAME;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(&eir[2], evt->name, eir[0] - 1);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check if field length is correct */
|
|
|
|
if (eir[0] > eir_len - 1) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* next EIR Structure */
|
|
|
|
eir_len -= eir[0] + 1;
|
|
|
|
eir += eir[0] + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
check_names:
|
|
|
|
/* if still waiting for names */
|
|
|
|
for (i = 0; i < discovery_results_count; i++) {
|
|
|
|
struct discovery_priv *priv;
|
|
|
|
|
2016-11-08 12:21:46 +02:00
|
|
|
priv = (struct discovery_priv *)&discovery_results[i]._priv;
|
2016-03-17 18:35:58 +01:00
|
|
|
|
|
|
|
if (priv->resolving) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* all names resolved, report discovery results */
|
|
|
|
atomic_clear_bit(bt_dev.flags, BT_DEV_INQUIRY);
|
|
|
|
|
|
|
|
discovery_cb(discovery_results, discovery_results_count);
|
|
|
|
|
|
|
|
discovery_cb = NULL;
|
|
|
|
discovery_results = NULL;
|
|
|
|
discovery_results_size = 0;
|
|
|
|
discovery_results_count = 0;
|
|
|
|
}
|
2016-03-18 14:13:23 +01:00
|
|
|
|
2017-04-20 12:00:29 -05:00
|
|
|
static void link_encr(const u16_t handle)
|
2016-03-18 14:19:35 +01:00
|
|
|
{
|
|
|
|
struct bt_hci_cp_set_conn_encrypt *encr;
|
|
|
|
struct net_buf *buf;
|
|
|
|
|
|
|
|
BT_DBG("");
|
|
|
|
|
|
|
|
buf = bt_hci_cmd_create(BT_HCI_OP_SET_CONN_ENCRYPT, sizeof(*encr));
|
|
|
|
if (!buf) {
|
|
|
|
BT_ERR("Out of command buffers");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
encr = net_buf_add(buf, sizeof(*encr));
|
|
|
|
encr->handle = sys_cpu_to_le16(handle);
|
|
|
|
encr->encrypt = 0x01;
|
|
|
|
|
|
|
|
bt_hci_cmd_send_sync(BT_HCI_OP_SET_CONN_ENCRYPT, buf, NULL);
|
|
|
|
}
|
|
|
|
|
2016-03-18 14:13:23 +01:00
|
|
|
static void auth_complete(struct net_buf *buf)
|
|
|
|
{
|
|
|
|
struct bt_hci_evt_auth_complete *evt = (void *)buf->data;
|
|
|
|
struct bt_conn *conn;
|
2017-04-20 12:00:29 -05:00
|
|
|
u16_t handle = sys_le16_to_cpu(evt->handle);
|
2016-03-18 14:13:23 +01:00
|
|
|
|
|
|
|
BT_DBG("status %u, handle %u", evt->status, handle);
|
|
|
|
|
|
|
|
conn = bt_conn_lookup_handle(handle);
|
|
|
|
if (!conn) {
|
|
|
|
BT_ERR("Can't find conn for handle %u", handle);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (evt->status) {
|
2016-09-13 09:38:10 +02:00
|
|
|
if (conn->state == BT_CONN_CONNECTED) {
|
|
|
|
/*
|
|
|
|
* Inform layers above HCI about non-zero authentication
|
|
|
|
* status to make them able cleanup pending jobs.
|
|
|
|
*/
|
|
|
|
bt_l2cap_encrypt_change(conn, evt->status);
|
|
|
|
}
|
2016-04-27 12:39:44 +02:00
|
|
|
reset_pairing(conn);
|
2016-03-18 14:19:35 +01:00
|
|
|
} else {
|
|
|
|
link_encr(handle);
|
2016-03-18 14:13:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bt_conn_unref(conn);
|
|
|
|
}
|
2016-06-17 21:27:41 +02:00
|
|
|
|
|
|
|
static void read_remote_features_complete(struct net_buf *buf)
|
|
|
|
{
|
|
|
|
struct bt_hci_evt_remote_features *evt = (void *)buf->data;
|
2017-04-20 12:00:29 -05:00
|
|
|
u16_t handle = sys_le16_to_cpu(evt->handle);
|
2016-06-17 21:27:41 +02:00
|
|
|
struct bt_hci_cp_read_remote_ext_features *cp;
|
|
|
|
struct bt_conn *conn;
|
|
|
|
|
|
|
|
BT_DBG("status %u handle %u", evt->status, handle);
|
|
|
|
|
|
|
|
conn = bt_conn_lookup_handle(handle);
|
|
|
|
if (!conn) {
|
|
|
|
BT_ERR("Can't find conn for handle %u", handle);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-06-20 13:36:40 +03:00
|
|
|
if (evt->status) {
|
|
|
|
goto done;
|
|
|
|
}
|
2016-06-17 21:27:41 +02:00
|
|
|
|
2016-06-20 13:36:40 +03:00
|
|
|
memcpy(conn->br.features[0], evt->features, sizeof(evt->features));
|
2016-06-17 21:27:41 +02:00
|
|
|
|
2016-08-28 16:01:28 +03:00
|
|
|
if (!BT_FEAT_EXT_FEATURES(conn->br.features)) {
|
2016-06-20 13:36:40 +03:00
|
|
|
goto done;
|
|
|
|
}
|
2016-06-17 21:27:41 +02:00
|
|
|
|
2016-06-20 13:36:40 +03:00
|
|
|
buf = bt_hci_cmd_create(BT_HCI_OP_READ_REMOTE_EXT_FEATURES,
|
|
|
|
sizeof(*cp));
|
|
|
|
if (!buf) {
|
|
|
|
goto done;
|
2016-06-17 21:27:41 +02:00
|
|
|
}
|
2016-06-20 13:36:40 +03:00
|
|
|
|
|
|
|
/* Read remote host features (page 1) */
|
|
|
|
cp = net_buf_add(buf, sizeof(*cp));
|
|
|
|
cp->handle = evt->handle;
|
|
|
|
cp->page = 0x01;
|
|
|
|
|
|
|
|
bt_hci_cmd_send_sync(BT_HCI_OP_READ_REMOTE_EXT_FEATURES, buf, NULL);
|
|
|
|
|
2016-06-17 21:27:41 +02:00
|
|
|
done:
|
|
|
|
bt_conn_unref(conn);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void read_remote_ext_features_complete(struct net_buf *buf)
|
|
|
|
{
|
|
|
|
struct bt_hci_evt_remote_ext_features *evt = (void *)buf->data;
|
2017-04-20 12:00:29 -05:00
|
|
|
u16_t handle = sys_le16_to_cpu(evt->handle);
|
2016-06-17 21:27:41 +02:00
|
|
|
struct bt_conn *conn;
|
|
|
|
|
|
|
|
BT_DBG("status %u handle %u", evt->status, handle);
|
|
|
|
|
|
|
|
conn = bt_conn_lookup_handle(handle);
|
|
|
|
if (!conn) {
|
|
|
|
BT_ERR("Can't find conn for handle %u", handle);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!evt->status && evt->page == 0x01) {
|
|
|
|
memcpy(conn->br.features[1], evt->features,
|
|
|
|
sizeof(conn->br.features[1]));
|
|
|
|
}
|
|
|
|
|
|
|
|
bt_conn_unref(conn);
|
|
|
|
}
|
|
|
|
|
2016-10-07 12:04:33 +02:00
|
|
|
static void role_change(struct net_buf *buf)
|
|
|
|
{
|
|
|
|
struct bt_hci_evt_role_change *evt = (void *)buf->data;
|
|
|
|
struct bt_conn *conn;
|
|
|
|
|
|
|
|
BT_DBG("status %u role %u addr %s", evt->status, evt->role,
|
|
|
|
bt_addr_str(&evt->bdaddr));
|
|
|
|
|
|
|
|
if (evt->status) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
conn = bt_conn_lookup_addr_br(&evt->bdaddr);
|
|
|
|
if (!conn) {
|
|
|
|
BT_ERR("Can't find conn for %s", bt_addr_str(&evt->bdaddr));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (evt->role) {
|
|
|
|
conn->role = BT_CONN_ROLE_SLAVE;
|
|
|
|
} else {
|
|
|
|
conn->role = BT_CONN_ROLE_MASTER;
|
|
|
|
}
|
|
|
|
|
|
|
|
bt_conn_unref(conn);
|
|
|
|
}
|
2016-03-10 11:58:56 +01:00
|
|
|
#endif /* CONFIG_BLUETOOTH_BREDR */
|
2016-01-21 09:31:09 +01:00
|
|
|
|
2016-08-08 16:40:30 +02:00
|
|
|
#if defined(CONFIG_BLUETOOTH_SMP)
|
2015-10-01 17:50:19 +02:00
|
|
|
static void update_sec_level(struct bt_conn *conn)
|
|
|
|
{
|
|
|
|
if (!conn->encrypt) {
|
|
|
|
conn->sec_level = BT_SECURITY_LOW;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-08-08 16:40:30 +02:00
|
|
|
if (conn->le.keys && atomic_test_bit(conn->le.keys->flags,
|
|
|
|
BT_KEYS_AUTHENTICATED)) {
|
|
|
|
if (conn->le.keys->keys & BT_KEYS_LTK_P256) {
|
2015-11-19 16:50:41 +01:00
|
|
|
conn->sec_level = BT_SECURITY_FIPS;
|
|
|
|
} else {
|
|
|
|
conn->sec_level = BT_SECURITY_HIGH;
|
|
|
|
}
|
2015-10-01 17:50:19 +02:00
|
|
|
} else {
|
|
|
|
conn->sec_level = BT_SECURITY_MEDIUM;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (conn->required_sec_level > conn->sec_level) {
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_ERR("Failed to set required security level");
|
2015-10-01 17:50:19 +02:00
|
|
|
bt_conn_disconnect(conn, BT_HCI_ERR_AUTHENTICATION_FAIL);
|
|
|
|
}
|
|
|
|
}
|
2016-08-08 16:40:30 +02:00
|
|
|
#endif /* CONFIG_BLUETOOTH_SMP */
|
2015-10-01 17:50:19 +02:00
|
|
|
|
2016-08-08 16:40:30 +02:00
|
|
|
#if defined(CONFIG_BLUETOOTH_SMP) || defined(CONFIG_BLUETOOTH_BREDR)
|
2015-10-28 10:34:15 +02:00
|
|
|
static void hci_encrypt_change(struct net_buf *buf)
|
2015-10-01 17:50:19 +02:00
|
|
|
{
|
|
|
|
struct bt_hci_evt_encrypt_change *evt = (void *)buf->data;
|
2017-04-20 12:00:29 -05:00
|
|
|
u16_t handle = sys_le16_to_cpu(evt->handle);
|
2015-10-01 17:50:19 +02:00
|
|
|
struct bt_conn *conn;
|
|
|
|
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_DBG("status %u handle %u encrypt 0x%02x", evt->status, handle,
|
2015-10-01 17:50:19 +02:00
|
|
|
evt->encrypt);
|
|
|
|
|
|
|
|
conn = bt_conn_lookup_handle(handle);
|
|
|
|
if (!conn) {
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_ERR("Unable to look up conn with handle %u", handle);
|
2015-10-01 17:50:19 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-10-13 16:17:42 +02:00
|
|
|
if (evt->status) {
|
|
|
|
/* TODO report error */
|
2016-04-27 12:39:44 +02:00
|
|
|
if (conn->type == BT_CONN_TYPE_LE) {
|
|
|
|
/* reset required security level in case of error */
|
|
|
|
conn->required_sec_level = conn->sec_level;
|
|
|
|
#if defined(CONFIG_BLUETOOTH_BREDR)
|
|
|
|
} else {
|
2016-09-13 09:38:10 +02:00
|
|
|
bt_l2cap_encrypt_change(conn, evt->status);
|
2016-04-27 12:39:44 +02:00
|
|
|
reset_pairing(conn);
|
|
|
|
#endif /* CONFIG_BLUETOOTH_BREDR */
|
|
|
|
}
|
2015-10-23 12:45:33 +03:00
|
|
|
bt_conn_unref(conn);
|
2015-10-13 16:17:42 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-10-01 17:50:19 +02:00
|
|
|
conn->encrypt = evt->encrypt;
|
|
|
|
|
2016-08-08 16:40:30 +02:00
|
|
|
#if defined(CONFIG_BLUETOOTH_SMP)
|
2016-01-21 09:46:51 +01:00
|
|
|
if (conn->type == BT_CONN_TYPE_LE) {
|
2016-08-08 16:40:30 +02:00
|
|
|
/*
|
|
|
|
* we update keys properties only on successful encryption to
|
|
|
|
* avoid losing valid keys if encryption was not successful.
|
|
|
|
*
|
|
|
|
* Update keys with last pairing info for proper sec level
|
|
|
|
* update. This is done only for LE transport, for BR/EDR keys
|
|
|
|
* are updated on HCI 'Link Key Notification Event'
|
|
|
|
*/
|
|
|
|
if (conn->encrypt) {
|
|
|
|
bt_smp_update_keys(conn);
|
|
|
|
}
|
2016-01-21 09:46:51 +01:00
|
|
|
update_sec_level(conn);
|
2016-08-08 16:40:30 +02:00
|
|
|
}
|
|
|
|
#endif /* CONFIG_BLUETOOTH_SMP */
|
2016-01-21 09:46:51 +01:00
|
|
|
#if defined(CONFIG_BLUETOOTH_BREDR)
|
2016-08-08 16:40:30 +02:00
|
|
|
if (conn->type == BT_CONN_TYPE_BR) {
|
2016-01-21 09:46:51 +01:00
|
|
|
update_sec_level_br(conn);
|
2016-10-03 16:31:22 +02:00
|
|
|
|
2017-01-17 14:28:01 +02:00
|
|
|
if (IS_ENABLED(CONFIG_BLUETOOTH_SMP)) {
|
|
|
|
/*
|
|
|
|
* Start SMP over BR/EDR if we are pairing and are
|
|
|
|
* master on the link
|
|
|
|
*/
|
|
|
|
if (atomic_test_bit(conn->flags, BT_CONN_BR_PAIRING) &&
|
|
|
|
conn->role == BT_CONN_ROLE_MASTER) {
|
|
|
|
bt_smp_br_send_pairing_req(conn);
|
|
|
|
}
|
2016-10-03 16:31:22 +02:00
|
|
|
}
|
|
|
|
|
2016-04-27 12:39:44 +02:00
|
|
|
reset_pairing(conn);
|
2016-01-21 09:46:51 +01:00
|
|
|
}
|
2016-08-08 16:40:30 +02:00
|
|
|
#endif /* CONFIG_BLUETOOTH_BREDR */
|
2016-01-21 09:46:51 +01:00
|
|
|
|
2016-09-13 09:38:10 +02:00
|
|
|
bt_l2cap_encrypt_change(conn, evt->status);
|
2015-10-01 17:50:19 +02:00
|
|
|
bt_conn_security_changed(conn);
|
|
|
|
|
2015-10-23 12:45:33 +03:00
|
|
|
bt_conn_unref(conn);
|
2015-10-01 17:50:19 +02:00
|
|
|
}
|
|
|
|
|
2015-10-28 10:34:15 +02:00
|
|
|
static void hci_encrypt_key_refresh_complete(struct net_buf *buf)
|
2015-10-01 17:50:19 +02:00
|
|
|
{
|
|
|
|
struct bt_hci_evt_encrypt_key_refresh_complete *evt = (void *)buf->data;
|
|
|
|
struct bt_conn *conn;
|
2017-04-20 12:00:29 -05:00
|
|
|
u16_t handle;
|
2015-10-01 17:50:19 +02:00
|
|
|
|
|
|
|
handle = sys_le16_to_cpu(evt->handle);
|
|
|
|
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_DBG("status %u handle %u", evt->status, handle);
|
2015-10-01 17:50:19 +02:00
|
|
|
|
|
|
|
conn = bt_conn_lookup_handle(handle);
|
|
|
|
if (!conn) {
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_ERR("Unable to look up conn with handle %u", handle);
|
2015-10-01 17:50:19 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-09-13 09:38:10 +02:00
|
|
|
if (evt->status) {
|
|
|
|
bt_l2cap_encrypt_change(conn, evt->status);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-01-28 18:09:26 +01:00
|
|
|
/*
|
|
|
|
* Update keys with last pairing info for proper sec level update.
|
2016-01-21 09:55:03 +01:00
|
|
|
* This is done only for LE transport. For BR/EDR transport keys are
|
|
|
|
* updated on HCI 'Link Key Notification Event', therefore update here
|
|
|
|
* only security level based on available keys and encryption state.
|
2016-01-28 18:09:26 +01:00
|
|
|
*/
|
2016-08-08 16:40:30 +02:00
|
|
|
#if defined(CONFIG_BLUETOOTH_SMP)
|
2016-01-28 18:09:26 +01:00
|
|
|
if (conn->type == BT_CONN_TYPE_LE) {
|
|
|
|
bt_smp_update_keys(conn);
|
2016-01-21 09:55:03 +01:00
|
|
|
update_sec_level(conn);
|
2016-08-08 16:40:30 +02:00
|
|
|
}
|
|
|
|
#endif /* CONFIG_BLUETOOTH_SMP */
|
2016-01-21 09:55:03 +01:00
|
|
|
#if defined(CONFIG_BLUETOOTH_BREDR)
|
2016-08-08 16:40:30 +02:00
|
|
|
if (conn->type == BT_CONN_TYPE_BR) {
|
2016-01-21 09:55:03 +01:00
|
|
|
update_sec_level_br(conn);
|
2016-01-28 18:09:26 +01:00
|
|
|
}
|
2016-08-08 16:40:30 +02:00
|
|
|
#endif /* CONFIG_BLUETOOTH_BREDR */
|
2016-01-28 18:09:26 +01:00
|
|
|
|
2016-09-13 09:38:10 +02:00
|
|
|
bt_l2cap_encrypt_change(conn, evt->status);
|
2015-10-13 09:25:21 +02:00
|
|
|
bt_conn_security_changed(conn);
|
2015-10-23 12:45:33 +03:00
|
|
|
bt_conn_unref(conn);
|
2015-10-01 17:50:19 +02:00
|
|
|
}
|
2016-01-08 11:11:56 +01:00
|
|
|
#endif /* CONFIG_BLUETOOTH_SMP || CONFIG_BLUETOOTH_BREDR */
|
2015-10-01 17:50:19 +02:00
|
|
|
|
2016-01-08 11:11:56 +01:00
|
|
|
#if defined(CONFIG_BLUETOOTH_SMP)
|
2015-10-28 10:34:15 +02:00
|
|
|
static void le_ltk_request(struct net_buf *buf)
|
2015-10-01 17:50:19 +02:00
|
|
|
{
|
|
|
|
struct bt_hci_evt_le_ltk_request *evt = (void *)buf->data;
|
2015-12-08 17:22:52 +01:00
|
|
|
struct bt_hci_cp_le_ltk_req_neg_reply *cp;
|
2015-10-01 17:50:19 +02:00
|
|
|
struct bt_conn *conn;
|
2017-04-20 12:00:29 -05:00
|
|
|
u16_t handle;
|
|
|
|
u8_t tk[16];
|
2015-10-01 17:50:19 +02:00
|
|
|
|
|
|
|
handle = sys_le16_to_cpu(evt->handle);
|
|
|
|
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_DBG("handle %u", handle);
|
2015-10-01 17:50:19 +02:00
|
|
|
|
|
|
|
conn = bt_conn_lookup_handle(handle);
|
|
|
|
if (!conn) {
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_ERR("Unable to lookup conn for handle %u", handle);
|
2015-10-01 17:50:19 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-11-24 16:11:21 +01:00
|
|
|
/*
|
|
|
|
* if TK is present use it, that means pairing is in progress and
|
|
|
|
* we should use new TK for encryption
|
2015-11-25 08:58:45 +01:00
|
|
|
*
|
|
|
|
* Both legacy STK and LE SC LTK have rand and ediv equal to zero.
|
2015-11-24 16:11:21 +01:00
|
|
|
*/
|
|
|
|
if (evt->rand == 0 && evt->ediv == 0 && bt_smp_get_tk(conn, tk)) {
|
|
|
|
struct bt_hci_cp_le_ltk_req_reply *cp;
|
|
|
|
|
|
|
|
buf = bt_hci_cmd_create(BT_HCI_OP_LE_LTK_REQ_REPLY,
|
|
|
|
sizeof(*cp));
|
|
|
|
if (!buf) {
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_ERR("Out of command buffers");
|
2015-11-24 16:11:21 +01:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
cp = net_buf_add(buf, sizeof(*cp));
|
|
|
|
cp->handle = evt->handle;
|
|
|
|
memcpy(cp->ltk, tk, sizeof(cp->ltk));
|
|
|
|
|
|
|
|
bt_hci_cmd_send(BT_HCI_OP_LE_LTK_REQ_REPLY, buf);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2016-08-08 16:40:30 +02:00
|
|
|
if (!conn->le.keys) {
|
|
|
|
conn->le.keys = bt_keys_find(BT_KEYS_LTK_P256, &conn->le.dst);
|
|
|
|
if (!conn->le.keys) {
|
|
|
|
conn->le.keys = bt_keys_find(BT_KEYS_SLAVE_LTK,
|
|
|
|
&conn->le.dst);
|
2015-11-12 10:17:49 +01:00
|
|
|
}
|
2015-10-01 17:50:19 +02:00
|
|
|
}
|
|
|
|
|
2016-08-08 16:40:30 +02:00
|
|
|
if (conn->le.keys && (conn->le.keys->keys & BT_KEYS_LTK_P256) &&
|
2015-11-12 10:17:49 +01:00
|
|
|
evt->rand == 0 && evt->ediv == 0) {
|
|
|
|
struct bt_hci_cp_le_ltk_req_reply *cp;
|
|
|
|
|
|
|
|
buf = bt_hci_cmd_create(BT_HCI_OP_LE_LTK_REQ_REPLY,
|
|
|
|
sizeof(*cp));
|
|
|
|
if (!buf) {
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_ERR("Out of command buffers");
|
2015-11-12 10:17:49 +01:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
cp = net_buf_add(buf, sizeof(*cp));
|
|
|
|
cp->handle = evt->handle;
|
|
|
|
|
|
|
|
/* use only enc_size bytes of key for encryption */
|
2016-08-08 16:40:30 +02:00
|
|
|
memcpy(cp->ltk, conn->le.keys->ltk.val,
|
|
|
|
conn->le.keys->enc_size);
|
|
|
|
if (conn->le.keys->enc_size < sizeof(cp->ltk)) {
|
|
|
|
memset(cp->ltk + conn->le.keys->enc_size, 0,
|
|
|
|
sizeof(cp->ltk) - conn->le.keys->enc_size);
|
2015-11-12 10:17:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bt_hci_cmd_send(BT_HCI_OP_LE_LTK_REQ_REPLY, buf);
|
2015-12-08 17:22:52 +01:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2015-12-08 16:59:19 +01:00
|
|
|
#if !defined(CONFIG_BLUETOOTH_SMP_SC_ONLY)
|
2016-08-08 16:40:30 +02:00
|
|
|
if (conn->le.keys && (conn->le.keys->keys & BT_KEYS_SLAVE_LTK) &&
|
|
|
|
conn->le.keys->slave_ltk.rand == evt->rand &&
|
|
|
|
conn->le.keys->slave_ltk.ediv == evt->ediv) {
|
2015-10-01 17:50:19 +02:00
|
|
|
struct bt_hci_cp_le_ltk_req_reply *cp;
|
2015-12-08 17:22:52 +01:00
|
|
|
struct net_buf *buf;
|
2015-10-01 17:50:19 +02:00
|
|
|
|
|
|
|
buf = bt_hci_cmd_create(BT_HCI_OP_LE_LTK_REQ_REPLY,
|
|
|
|
sizeof(*cp));
|
|
|
|
if (!buf) {
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_ERR("Out of command buffers");
|
2015-10-01 17:50:19 +02:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2015-10-28 10:34:15 +02:00
|
|
|
cp = net_buf_add(buf, sizeof(*cp));
|
2015-10-01 17:50:19 +02:00
|
|
|
cp->handle = evt->handle;
|
Bluetooth: SMP: Add support for encryption key size reduction
This allows to pair with devices that use reduced encryption key size.
Encryption key size is stored with keys for future use. LTKs are kept
in full form (16 bytes) and are reduced only when used.
As master:
< ACL Data TX: Handle 64 flags 0x00 dlen 11
SMP: Pairing Request (0x01) len 6
IO capability: NoInputNoOutput (0x03)
OOB data: Authentication data not present (0x00)
Authentication requirement: Bonding, No MITM, Legacy,
No Keypresses (0x01)
Max encryption key size: 16
Initiator key distribution: EncKey Sign (0x05)
Responder key distribution: EncKey IdKey Sign (0x07)
> ACL Data RX: Handle 64 flags 0x02 dlen 11
SMP: Pairing Response (0x02) len 6
IO capability: KeyboardDisplay (0x04)
OOB data: Authentication data not present (0x00)
Authentication requirement: No bonding, No MITM, Legacy,
No Keypresses (0x00)
Max encryption key size: 7
Initiator key distribution: <none> (0x00)
Responder key distribution: <none> (0x00)
...
< HCI Command: LE Start Encryption (0x08|0x0019) plen 28
Handle: 64
Random number: 0x0000000000000000
Encrypted diversifier: 0x0000
Long term key: df3cff52a981d6000000000000000000
As slave:
> ACL Data RX: Handle 64 flags 0x02 dlen 11
SMP: Pairing Request (0x01) len 6
IO capability: KeyboardDisplay (0x04)
OOB data: Authentication data not present (0x00)
Authentication requirement: No bonding, No MITM, Legacy,
No Keypresses (0x00)
Max encryption key size: 7
Initiator key distribution: <none> (0x00)
Responder key distribution: <none> (0x00)
< ACL Data TX: Handle 64 flags 0x00 dlen 11
SMP: Pairing Response (0x02) len 6
IO capability: NoInputNoOutput (0x03)
OOB data: Authentication data not present (0x00)
Authentication requirement: No bonding, No MITM, Legacy,
No Keypresses (0x00)
Max encryption key size: 16
Initiator key distribution: <none> (0x00)
Responder key distribution: <none> (0x00)
...
> HCI Event: LE Meta Event (0x3e) plen 13
LE Long Term Key Request (0x05)
Handle: 64
Random number: 0x0000000000000000
Encrypted diversifier: 0x0000
< HCI Command: LE Long Term Key Request Reply (0x08|0x001a) plen 18
Handle: 64
Long term key: 701b431a9e17bb000000000000000000
Change-Id: Ibc70aa01c040aff0d39410d273d6880d35aa5ae0
Signed-off-by: Szymon Janc <ext.szymon.janc@tieto.com>
2015-10-07 12:33:45 +02:00
|
|
|
|
|
|
|
/* use only enc_size bytes of key for encryption */
|
2016-08-08 16:40:30 +02:00
|
|
|
memcpy(cp->ltk, conn->le.keys->slave_ltk.val,
|
|
|
|
conn->le.keys->enc_size);
|
|
|
|
if (conn->le.keys->enc_size < sizeof(cp->ltk)) {
|
|
|
|
memset(cp->ltk + conn->le.keys->enc_size, 0,
|
|
|
|
sizeof(cp->ltk) - conn->le.keys->enc_size);
|
Bluetooth: SMP: Add support for encryption key size reduction
This allows to pair with devices that use reduced encryption key size.
Encryption key size is stored with keys for future use. LTKs are kept
in full form (16 bytes) and are reduced only when used.
As master:
< ACL Data TX: Handle 64 flags 0x00 dlen 11
SMP: Pairing Request (0x01) len 6
IO capability: NoInputNoOutput (0x03)
OOB data: Authentication data not present (0x00)
Authentication requirement: Bonding, No MITM, Legacy,
No Keypresses (0x01)
Max encryption key size: 16
Initiator key distribution: EncKey Sign (0x05)
Responder key distribution: EncKey IdKey Sign (0x07)
> ACL Data RX: Handle 64 flags 0x02 dlen 11
SMP: Pairing Response (0x02) len 6
IO capability: KeyboardDisplay (0x04)
OOB data: Authentication data not present (0x00)
Authentication requirement: No bonding, No MITM, Legacy,
No Keypresses (0x00)
Max encryption key size: 7
Initiator key distribution: <none> (0x00)
Responder key distribution: <none> (0x00)
...
< HCI Command: LE Start Encryption (0x08|0x0019) plen 28
Handle: 64
Random number: 0x0000000000000000
Encrypted diversifier: 0x0000
Long term key: df3cff52a981d6000000000000000000
As slave:
> ACL Data RX: Handle 64 flags 0x02 dlen 11
SMP: Pairing Request (0x01) len 6
IO capability: KeyboardDisplay (0x04)
OOB data: Authentication data not present (0x00)
Authentication requirement: No bonding, No MITM, Legacy,
No Keypresses (0x00)
Max encryption key size: 7
Initiator key distribution: <none> (0x00)
Responder key distribution: <none> (0x00)
< ACL Data TX: Handle 64 flags 0x00 dlen 11
SMP: Pairing Response (0x02) len 6
IO capability: NoInputNoOutput (0x03)
OOB data: Authentication data not present (0x00)
Authentication requirement: No bonding, No MITM, Legacy,
No Keypresses (0x00)
Max encryption key size: 16
Initiator key distribution: <none> (0x00)
Responder key distribution: <none> (0x00)
...
> HCI Event: LE Meta Event (0x3e) plen 13
LE Long Term Key Request (0x05)
Handle: 64
Random number: 0x0000000000000000
Encrypted diversifier: 0x0000
< HCI Command: LE Long Term Key Request Reply (0x08|0x001a) plen 18
Handle: 64
Long term key: 701b431a9e17bb000000000000000000
Change-Id: Ibc70aa01c040aff0d39410d273d6880d35aa5ae0
Signed-off-by: Szymon Janc <ext.szymon.janc@tieto.com>
2015-10-07 12:33:45 +02:00
|
|
|
}
|
2015-10-01 17:50:19 +02:00
|
|
|
|
|
|
|
bt_hci_cmd_send(BT_HCI_OP_LE_LTK_REQ_REPLY, buf);
|
2015-12-08 17:22:52 +01:00
|
|
|
goto done;
|
|
|
|
}
|
2015-12-08 16:59:19 +01:00
|
|
|
#endif /* !CONFIG_BLUETOOTH_SMP_SC_ONLY */
|
2015-10-01 17:50:19 +02:00
|
|
|
|
2015-12-08 17:22:52 +01:00
|
|
|
buf = bt_hci_cmd_create(BT_HCI_OP_LE_LTK_REQ_NEG_REPLY, sizeof(*cp));
|
|
|
|
if (!buf) {
|
|
|
|
BT_ERR("Out of command buffers");
|
|
|
|
goto done;
|
|
|
|
}
|
2015-10-01 17:50:19 +02:00
|
|
|
|
2015-12-08 17:22:52 +01:00
|
|
|
cp = net_buf_add(buf, sizeof(*cp));
|
|
|
|
cp->handle = evt->handle;
|
2015-10-01 17:50:19 +02:00
|
|
|
|
2015-12-08 17:22:52 +01:00
|
|
|
bt_hci_cmd_send(BT_HCI_OP_LE_LTK_REQ_NEG_REPLY, buf);
|
2015-10-01 17:50:19 +02:00
|
|
|
|
|
|
|
done:
|
2015-10-23 12:45:33 +03:00
|
|
|
bt_conn_unref(conn);
|
2015-10-01 17:50:19 +02:00
|
|
|
}
|
2016-06-30 20:05:36 +03:00
|
|
|
#endif /* CONFIG_BLUETOOTH_SMP */
|
2015-10-26 14:51:48 +01:00
|
|
|
|
|
|
|
static void le_pkey_complete(struct net_buf *buf)
|
|
|
|
{
|
|
|
|
struct bt_hci_evt_le_p256_public_key_complete *evt = (void *)buf->data;
|
2016-06-30 20:05:36 +03:00
|
|
|
struct bt_pub_key_cb *cb;
|
2015-10-26 14:51:48 +01:00
|
|
|
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_DBG("status: 0x%x", evt->status);
|
2015-10-26 14:51:48 +01:00
|
|
|
|
2016-06-30 20:05:36 +03:00
|
|
|
atomic_clear_bit(bt_dev.flags, BT_DEV_PUB_KEY_BUSY);
|
|
|
|
|
|
|
|
if (!evt->status) {
|
2016-07-03 17:06:49 +03:00
|
|
|
memcpy(pub_key, evt->key, 64);
|
2016-06-30 20:05:36 +03:00
|
|
|
atomic_set_bit(bt_dev.flags, BT_DEV_HAS_PUB_KEY);
|
2015-10-26 14:51:48 +01:00
|
|
|
}
|
|
|
|
|
2016-06-30 20:05:36 +03:00
|
|
|
for (cb = pub_key_cb; cb; cb = cb->_next) {
|
|
|
|
cb->func(evt->status ? NULL : evt->key);
|
|
|
|
}
|
2015-10-26 14:51:48 +01:00
|
|
|
}
|
2015-10-28 16:02:17 +01:00
|
|
|
|
|
|
|
static void le_dhkey_complete(struct net_buf *buf)
|
|
|
|
{
|
|
|
|
struct bt_hci_evt_le_generate_dhkey_complete *evt = (void *)buf->data;
|
|
|
|
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_DBG("status: 0x%x", evt->status);
|
2015-10-28 16:02:17 +01:00
|
|
|
|
2016-06-30 20:05:36 +03:00
|
|
|
if (dh_key_cb) {
|
|
|
|
dh_key_cb(evt->status ? NULL : evt->dhkey);
|
|
|
|
dh_key_cb = NULL;
|
2015-10-28 16:02:17 +01:00
|
|
|
}
|
|
|
|
}
|
2015-10-01 17:50:19 +02:00
|
|
|
|
2015-10-28 10:34:15 +02:00
|
|
|
static void hci_reset_complete(struct net_buf *buf)
|
2015-10-01 17:50:19 +02:00
|
|
|
{
|
2017-04-20 12:00:29 -05:00
|
|
|
u8_t status = buf->data[0];
|
2015-10-01 17:50:19 +02:00
|
|
|
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_DBG("status %u", status);
|
2015-10-01 17:50:19 +02:00
|
|
|
|
|
|
|
if (status) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
scan_dev_found_cb = NULL;
|
2016-03-10 11:58:56 +01:00
|
|
|
#if defined(CONFIG_BLUETOOTH_BREDR)
|
|
|
|
discovery_cb = NULL;
|
|
|
|
discovery_results = NULL;
|
|
|
|
discovery_results_size = 0;
|
|
|
|
discovery_results_count = 0;
|
|
|
|
#endif /* CONFIG_BLUETOOTH_BREDR */
|
2016-06-02 14:45:07 +02:00
|
|
|
|
|
|
|
/* we only allow to enable once so this bit must be keep set */
|
|
|
|
atomic_set(bt_dev.flags, BIT(BT_DEV_ENABLE));
|
2015-10-01 17:50:19 +02:00
|
|
|
}
|
|
|
|
|
2017-04-20 12:00:29 -05:00
|
|
|
static void hci_cmd_done(u16_t opcode, u8_t status, struct net_buf *buf)
|
2015-10-01 17:50:19 +02:00
|
|
|
{
|
2017-02-01 17:37:14 +02:00
|
|
|
BT_DBG("opcode 0x%04x status 0x%02x buf %p", opcode, status, buf);
|
2015-10-01 17:50:19 +02:00
|
|
|
|
2017-02-08 11:59:50 +02:00
|
|
|
if (buf->pool != &hci_cmd_pool) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-02-01 17:37:14 +02:00
|
|
|
if (cmd(buf)->opcode != opcode) {
|
|
|
|
BT_WARN("OpCode 0x%04x completed instead of expected 0x%04x",
|
|
|
|
opcode, cmd(buf)->opcode);
|
2015-10-01 17:50:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* If the command was synchronous wake up bt_hci_cmd_send_sync() */
|
2017-02-08 11:59:50 +02:00
|
|
|
if (cmd(buf)->sync) {
|
2017-02-01 17:37:14 +02:00
|
|
|
cmd(buf)->status = status;
|
|
|
|
k_sem_give(cmd(buf)->sync);
|
2015-10-01 17:50:19 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-28 10:34:15 +02:00
|
|
|
static void hci_cmd_complete(struct net_buf *buf)
|
2015-10-01 17:50:19 +02:00
|
|
|
{
|
2016-09-06 14:28:04 +02:00
|
|
|
struct bt_hci_evt_cmd_complete *evt = (void *)buf->data;
|
2017-04-20 12:00:29 -05:00
|
|
|
u16_t opcode = sys_le16_to_cpu(evt->opcode);
|
|
|
|
u8_t status, ncmd = evt->ncmd;
|
2015-10-01 17:50:19 +02:00
|
|
|
|
2016-03-14 12:35:39 +02:00
|
|
|
BT_DBG("opcode 0x%04x", opcode);
|
2015-10-01 17:50:19 +02:00
|
|
|
|
2015-10-28 10:34:15 +02:00
|
|
|
net_buf_pull(buf, sizeof(*evt));
|
2015-10-01 17:50:19 +02:00
|
|
|
|
|
|
|
/* All command return parameters have a 1-byte status in the
|
|
|
|
* beginning, so we can safely make this generalization.
|
|
|
|
*/
|
2015-12-09 14:13:14 +02:00
|
|
|
status = buf->data[0];
|
2015-10-01 17:50:19 +02:00
|
|
|
|
2015-12-09 14:13:14 +02:00
|
|
|
hci_cmd_done(opcode, status, buf);
|
2015-10-01 17:50:19 +02:00
|
|
|
|
2016-11-10 22:45:08 +02:00
|
|
|
/* Allow next command to be sent */
|
2017-02-01 17:37:14 +02:00
|
|
|
if (ncmd) {
|
2016-11-24 13:28:31 +01:00
|
|
|
k_sem_give(&bt_dev.ncmd_sem);
|
|
|
|
}
|
2015-08-10 22:23:05 +02:00
|
|
|
}
|
|
|
|
|
2015-10-28 10:34:15 +02:00
|
|
|
static void hci_cmd_status(struct net_buf *buf)
|
2015-08-10 22:23:05 +02:00
|
|
|
{
|
2015-10-01 17:50:19 +02:00
|
|
|
struct bt_hci_evt_cmd_status *evt = (void *)buf->data;
|
2017-04-20 12:00:29 -05:00
|
|
|
u16_t opcode = sys_le16_to_cpu(evt->opcode);
|
|
|
|
u8_t ncmd = evt->ncmd;
|
2015-08-10 22:23:05 +02:00
|
|
|
|
2016-03-14 12:35:39 +02:00
|
|
|
BT_DBG("opcode 0x%04x", opcode);
|
2015-08-10 22:23:05 +02:00
|
|
|
|
2015-10-28 10:34:15 +02:00
|
|
|
net_buf_pull(buf, sizeof(*evt));
|
2015-10-01 17:50:19 +02:00
|
|
|
|
|
|
|
hci_cmd_done(opcode, evt->status, buf);
|
2015-08-10 22:23:05 +02:00
|
|
|
|
2016-11-10 22:45:08 +02:00
|
|
|
/* Allow next command to be sent */
|
2017-02-01 17:37:14 +02:00
|
|
|
if (ncmd) {
|
2016-11-24 13:28:31 +01:00
|
|
|
k_sem_give(&bt_dev.ncmd_sem);
|
|
|
|
}
|
2015-08-10 22:23:05 +02:00
|
|
|
}
|
|
|
|
|
2017-04-20 12:00:29 -05:00
|
|
|
static int start_le_scan(u8_t scan_type, u16_t interval, u16_t window,
|
|
|
|
u8_t filter_dup)
|
2015-08-11 09:13:40 +02:00
|
|
|
{
|
2015-10-28 10:34:15 +02:00
|
|
|
struct net_buf *buf, *rsp;
|
2017-04-11 08:39:58 +02:00
|
|
|
struct bt_hci_cp_le_set_scan_param *set_param;
|
2015-10-01 17:50:19 +02:00
|
|
|
struct bt_hci_cp_le_set_scan_enable *scan_enable;
|
|
|
|
int err;
|
2015-08-11 09:13:40 +02:00
|
|
|
|
2017-04-11 08:39:58 +02:00
|
|
|
buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_SCAN_PARAM,
|
2015-10-01 17:50:19 +02:00
|
|
|
sizeof(*set_param));
|
|
|
|
if (!buf) {
|
|
|
|
return -ENOBUFS;
|
|
|
|
}
|
2015-08-11 09:13:40 +02:00
|
|
|
|
2015-10-28 10:34:15 +02:00
|
|
|
set_param = net_buf_add(buf, sizeof(*set_param));
|
2015-10-01 17:50:19 +02:00
|
|
|
memset(set_param, 0, sizeof(*set_param));
|
|
|
|
set_param->scan_type = scan_type;
|
2015-08-11 09:13:40 +02:00
|
|
|
|
2015-10-01 17:50:19 +02:00
|
|
|
/* for the rest parameters apply default values according to
|
|
|
|
* spec 4.2, vol2, part E, 7.8.10
|
|
|
|
*/
|
2015-12-03 20:17:34 +02:00
|
|
|
set_param->interval = sys_cpu_to_le16(interval);
|
|
|
|
set_param->window = sys_cpu_to_le16(window);
|
2015-10-01 17:50:19 +02:00
|
|
|
set_param->filter_policy = 0x00;
|
2015-12-07 08:00:32 +02:00
|
|
|
|
2017-01-17 14:28:01 +02:00
|
|
|
if (IS_ENABLED(CONFIG_BLUETOOTH_PRIVACY)) {
|
|
|
|
err = le_set_private_addr();
|
|
|
|
if (err) {
|
|
|
|
net_buf_unref(buf);
|
|
|
|
return err;
|
|
|
|
}
|
2016-11-15 13:55:31 +01:00
|
|
|
|
2017-01-17 14:28:01 +02:00
|
|
|
set_param->addr_type = BT_ADDR_LE_RANDOM;
|
|
|
|
} else {
|
|
|
|
set_param->addr_type = bt_dev.id_addr.type;
|
2016-11-15 13:55:31 +01:00
|
|
|
|
2016-07-14 15:30:59 +02:00
|
|
|
/* only set NRPA if there is no advertising ongoing */
|
2017-01-17 14:28:01 +02:00
|
|
|
if (scan_type == BT_HCI_LE_SCAN_ACTIVE &&
|
|
|
|
!atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING)) {
|
|
|
|
err = le_set_private_addr();
|
2016-07-14 15:30:59 +02:00
|
|
|
if (err) {
|
|
|
|
net_buf_unref(buf);
|
|
|
|
return err;
|
|
|
|
}
|
2015-12-07 08:00:32 +02:00
|
|
|
|
2016-11-15 13:55:31 +01:00
|
|
|
set_param->addr_type = BT_ADDR_LE_RANDOM;
|
|
|
|
}
|
2015-12-07 08:00:32 +02:00
|
|
|
}
|
2015-10-01 17:50:19 +02:00
|
|
|
|
2017-04-11 08:39:58 +02:00
|
|
|
bt_hci_cmd_send(BT_HCI_OP_LE_SET_SCAN_PARAM, buf);
|
2015-10-01 17:50:19 +02:00
|
|
|
buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_SCAN_ENABLE,
|
|
|
|
sizeof(*scan_enable));
|
|
|
|
if (!buf) {
|
|
|
|
return -ENOBUFS;
|
2015-08-11 09:13:40 +02:00
|
|
|
}
|
|
|
|
|
2015-10-28 10:34:15 +02:00
|
|
|
scan_enable = net_buf_add(buf, sizeof(*scan_enable));
|
2015-10-01 17:50:19 +02:00
|
|
|
memset(scan_enable, 0, sizeof(*scan_enable));
|
2015-12-03 20:10:46 +02:00
|
|
|
scan_enable->filter_dup = filter_dup;
|
2015-12-04 13:22:18 +02:00
|
|
|
scan_enable->enable = BT_HCI_LE_SCAN_ENABLE;
|
2015-10-01 17:50:19 +02:00
|
|
|
|
|
|
|
err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_SCAN_ENABLE, buf, &rsp);
|
|
|
|
if (err) {
|
|
|
|
return err;
|
2015-08-11 09:13:40 +02:00
|
|
|
}
|
|
|
|
|
2015-10-01 17:50:19 +02:00
|
|
|
/* Update scan state in case of success (0) status */
|
|
|
|
err = rsp->data[0];
|
|
|
|
if (!err) {
|
|
|
|
atomic_set_bit(bt_dev.flags, BT_DEV_SCANNING);
|
2016-07-14 15:30:38 +02:00
|
|
|
if (scan_type == BT_HCI_LE_SCAN_ACTIVE) {
|
|
|
|
atomic_set_bit(bt_dev.flags, BT_DEV_ACTIVE_SCAN);
|
|
|
|
}
|
2015-10-01 17:50:19 +02:00
|
|
|
}
|
2015-08-11 09:13:40 +02:00
|
|
|
|
2015-10-28 10:34:15 +02:00
|
|
|
net_buf_unref(rsp);
|
2015-10-01 17:50:19 +02:00
|
|
|
|
|
|
|
return err;
|
2015-08-11 09:13:40 +02:00
|
|
|
}
|
|
|
|
|
2015-12-03 22:51:16 +02:00
|
|
|
int bt_le_scan_update(bool fast_scan)
|
2015-07-02 11:53:54 +02:00
|
|
|
{
|
2015-12-04 10:55:54 +02:00
|
|
|
if (atomic_test_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-10-01 17:50:19 +02:00
|
|
|
if (atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING)) {
|
|
|
|
int err;
|
2015-07-02 11:53:54 +02:00
|
|
|
|
2015-10-01 17:50:19 +02:00
|
|
|
err = bt_hci_stop_scanning();
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
2015-07-02 11:53:54 +02:00
|
|
|
}
|
|
|
|
|
2017-01-17 14:28:01 +02:00
|
|
|
if (IS_ENABLED(CONFIG_BLUETOOTH_CENTRAL)) {
|
2017-04-20 12:00:29 -05:00
|
|
|
u16_t interval, window;
|
2017-01-17 14:28:01 +02:00
|
|
|
struct bt_conn *conn;
|
2015-07-02 11:53:54 +02:00
|
|
|
|
2017-01-17 14:28:01 +02:00
|
|
|
conn = bt_conn_lookup_state_le(NULL, BT_CONN_CONNECT_SCAN);
|
|
|
|
if (!conn) {
|
|
|
|
return 0;
|
|
|
|
}
|
2015-12-03 22:51:16 +02:00
|
|
|
|
2017-01-17 14:28:01 +02:00
|
|
|
bt_conn_unref(conn);
|
|
|
|
|
|
|
|
if (fast_scan) {
|
|
|
|
interval = BT_GAP_SCAN_FAST_INTERVAL;
|
|
|
|
window = BT_GAP_SCAN_FAST_WINDOW;
|
|
|
|
} else {
|
|
|
|
interval = BT_GAP_SCAN_SLOW_INTERVAL_1;
|
|
|
|
window = BT_GAP_SCAN_SLOW_WINDOW_1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return start_le_scan(BT_HCI_LE_SCAN_PASSIVE, interval, window,
|
|
|
|
0x01);
|
2015-10-01 17:50:19 +02:00
|
|
|
}
|
2015-04-18 18:44:38 +03:00
|
|
|
|
2015-12-03 20:05:42 +02:00
|
|
|
return 0;
|
2015-10-01 17:50:19 +02:00
|
|
|
}
|
|
|
|
|
2015-10-28 10:34:15 +02:00
|
|
|
static void le_adv_report(struct net_buf *buf)
|
2015-05-08 20:53:39 +02:00
|
|
|
{
|
2017-04-20 12:00:29 -05:00
|
|
|
u8_t num_reports = net_buf_pull_u8(buf);
|
2017-04-27 15:22:53 +02:00
|
|
|
struct bt_hci_evt_le_advertising_info *info;
|
2015-05-08 20:53:39 +02:00
|
|
|
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_DBG("Adv number of reports %u", num_reports);
|
2015-05-08 20:53:39 +02:00
|
|
|
|
|
|
|
while (num_reports--) {
|
2015-09-09 17:35:39 +02:00
|
|
|
const bt_addr_le_t *addr;
|
2017-04-20 12:00:29 -05:00
|
|
|
s8_t rssi;
|
2016-07-19 13:58:02 +03:00
|
|
|
|
|
|
|
info = (void *)buf->data;
|
|
|
|
net_buf_pull(buf, sizeof(*info));
|
|
|
|
|
|
|
|
rssi = info->data[info->length];
|
2015-10-01 18:21:40 +02:00
|
|
|
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_DBG("%s event %u, len %u, rssi %d dBm",
|
|
|
|
bt_addr_le_str(&info->addr),
|
|
|
|
info->evt_type, info->length, rssi);
|
2015-10-01 18:21:40 +02:00
|
|
|
|
|
|
|
addr = find_id_addr(&info->addr);
|
2015-06-02 17:28:00 +02:00
|
|
|
|
|
|
|
if (scan_dev_found_cb) {
|
2016-07-19 13:58:02 +03:00
|
|
|
struct net_buf_simple_state state;
|
|
|
|
|
|
|
|
net_buf_simple_save(&buf->b, &state);
|
|
|
|
|
|
|
|
buf->len = info->length;
|
|
|
|
scan_dev_found_cb(addr, rssi, info->evt_type, &buf->b);
|
|
|
|
|
|
|
|
net_buf_simple_restore(&buf->b, &state);
|
2015-06-01 10:25:05 +07:00
|
|
|
}
|
|
|
|
|
2015-10-01 18:21:40 +02:00
|
|
|
#if defined(CONFIG_BLUETOOTH_CONN)
|
2015-10-02 10:10:39 +02:00
|
|
|
check_pending_conn(addr, &info->addr, info->evt_type);
|
2015-09-07 18:25:59 +02:00
|
|
|
#endif /* CONFIG_BLUETOOTH_CONN */
|
2016-07-19 13:58:02 +03:00
|
|
|
|
2015-05-08 20:53:39 +02:00
|
|
|
/* Get next report iteration by moving pointer to right offset
|
|
|
|
* in buf according to spec 4.2, Vol 2, Part E, 7.7.65.2.
|
|
|
|
*/
|
2016-07-19 13:58:02 +03:00
|
|
|
net_buf_pull(buf, info->length + sizeof(rssi));
|
2015-05-08 20:53:39 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-28 10:34:15 +02:00
|
|
|
static void hci_le_meta_event(struct net_buf *buf)
|
2015-04-18 18:37:03 +03:00
|
|
|
{
|
|
|
|
struct bt_hci_evt_le_meta_event *evt = (void *)buf->data;
|
|
|
|
|
2017-05-15 14:20:12 +02:00
|
|
|
BT_DBG("subevent 0x%02x", evt->subevent);
|
|
|
|
|
2015-10-28 10:34:15 +02:00
|
|
|
net_buf_pull(buf, sizeof(*evt));
|
2015-04-18 18:37:03 +03:00
|
|
|
|
|
|
|
switch (evt->subevent) {
|
2015-09-07 18:25:59 +02:00
|
|
|
#if defined(CONFIG_BLUETOOTH_CONN)
|
2015-04-18 18:44:38 +03:00
|
|
|
case BT_HCI_EVT_LE_CONN_COMPLETE:
|
|
|
|
le_conn_complete(buf);
|
|
|
|
break;
|
2015-08-11 09:13:40 +02:00
|
|
|
case BT_HCI_EVT_LE_CONN_UPDATE_COMPLETE:
|
|
|
|
le_conn_update_complete(buf);
|
|
|
|
break;
|
2015-07-28 13:02:43 +03:00
|
|
|
case BT_HCI_EV_LE_REMOTE_FEAT_COMPLETE:
|
|
|
|
le_remote_feat_complete(buf);
|
|
|
|
break;
|
2015-08-10 22:23:05 +02:00
|
|
|
case BT_HCI_EVT_LE_CONN_PARAM_REQ:
|
|
|
|
le_conn_param_req(buf);
|
|
|
|
break;
|
2017-05-15 23:18:08 +02:00
|
|
|
case BT_HCI_EVT_LE_DATA_LEN_CHANGE:
|
|
|
|
le_data_len_change(buf);
|
|
|
|
break;
|
2017-05-06 07:10:50 +02:00
|
|
|
case BT_HCI_EVT_LE_PHY_UPDATE_COMPLETE:
|
|
|
|
le_phy_update_complete(buf);
|
|
|
|
break;
|
2015-09-07 18:25:59 +02:00
|
|
|
#endif /* CONFIG_BLUETOOTH_CONN */
|
2015-09-09 17:27:16 +02:00
|
|
|
#if defined(CONFIG_BLUETOOTH_SMP)
|
|
|
|
case BT_HCI_EVT_LE_LTK_REQUEST:
|
|
|
|
le_ltk_request(buf);
|
|
|
|
break;
|
2016-06-30 20:05:36 +03:00
|
|
|
#endif /* CONFIG_BLUETOOTH_SMP */
|
2015-10-26 14:51:48 +01:00
|
|
|
case BT_HCI_EVT_LE_P256_PUBLIC_KEY_COMPLETE:
|
|
|
|
le_pkey_complete(buf);
|
|
|
|
break;
|
2015-10-28 16:02:17 +01:00
|
|
|
case BT_HCI_EVT_LE_GENERATE_DHKEY_COMPLETE:
|
|
|
|
le_dhkey_complete(buf);
|
|
|
|
break;
|
2015-09-07 18:25:59 +02:00
|
|
|
case BT_HCI_EVT_LE_ADVERTISING_REPORT:
|
|
|
|
le_adv_report(buf);
|
|
|
|
break;
|
2015-04-18 18:37:03 +03:00
|
|
|
default:
|
2016-11-09 22:27:51 +02:00
|
|
|
BT_WARN("Unhandled LE event 0x%02x len %u: %s",
|
|
|
|
evt->subevent, buf->len, bt_hex(buf->data, buf->len));
|
2015-04-18 18:37:03 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-28 10:34:15 +02:00
|
|
|
static void hci_event(struct net_buf *buf)
|
2015-04-14 15:41:55 +03:00
|
|
|
{
|
|
|
|
struct bt_hci_evt_hdr *hdr = (void *)buf->data;
|
|
|
|
|
2016-06-30 13:34:10 +02:00
|
|
|
BT_DBG("event 0x%02x", hdr->evt);
|
2015-04-14 15:41:55 +03:00
|
|
|
|
2017-01-02 13:43:12 +02:00
|
|
|
BT_ASSERT(!bt_hci_evt_is_prio(hdr->evt));
|
|
|
|
|
2015-10-28 10:34:15 +02:00
|
|
|
net_buf_pull(buf, sizeof(*hdr));
|
2015-04-14 15:41:55 +03:00
|
|
|
|
|
|
|
switch (hdr->evt) {
|
2015-12-03 12:19:02 +01:00
|
|
|
#if defined(CONFIG_BLUETOOTH_BREDR)
|
|
|
|
case BT_HCI_EVT_CONN_REQUEST:
|
2015-12-16 22:39:08 +01:00
|
|
|
conn_req(buf);
|
2015-12-03 12:19:02 +01:00
|
|
|
break;
|
2015-12-03 17:20:29 +01:00
|
|
|
case BT_HCI_EVT_CONN_COMPLETE:
|
|
|
|
conn_complete(buf);
|
|
|
|
break;
|
2015-12-16 11:08:25 +01:00
|
|
|
case BT_HCI_EVT_PIN_CODE_REQ:
|
|
|
|
pin_code_req(buf);
|
|
|
|
break;
|
2015-12-16 16:35:28 +01:00
|
|
|
case BT_HCI_EVT_LINK_KEY_NOTIFY:
|
|
|
|
link_key_notify(buf);
|
|
|
|
break;
|
2016-01-07 22:55:01 +01:00
|
|
|
case BT_HCI_EVT_LINK_KEY_REQ:
|
|
|
|
link_key_req(buf);
|
|
|
|
break;
|
2016-01-29 12:29:11 +01:00
|
|
|
case BT_HCI_EVT_IO_CAPA_RESP:
|
|
|
|
io_capa_resp(buf);
|
|
|
|
break;
|
2016-01-29 13:08:59 +01:00
|
|
|
case BT_HCI_EVT_IO_CAPA_REQ:
|
|
|
|
io_capa_req(buf);
|
|
|
|
break;
|
2016-01-29 13:29:54 +01:00
|
|
|
case BT_HCI_EVT_SSP_COMPLETE:
|
|
|
|
ssp_complete(buf);
|
|
|
|
break;
|
2016-02-01 12:41:04 +01:00
|
|
|
case BT_HCI_EVT_USER_CONFIRM_REQ:
|
|
|
|
user_confirm_req(buf);
|
|
|
|
break;
|
2016-02-24 14:47:01 +01:00
|
|
|
case BT_HCI_EVT_USER_PASSKEY_NOTIFY:
|
|
|
|
user_passkey_notify(buf);
|
|
|
|
break;
|
2016-02-24 14:58:03 +01:00
|
|
|
case BT_HCI_EVT_USER_PASSKEY_REQ:
|
|
|
|
user_passkey_req(buf);
|
|
|
|
break;
|
2016-03-10 11:58:56 +01:00
|
|
|
case BT_HCI_EVT_INQUIRY_COMPLETE:
|
|
|
|
inquiry_complete(buf);
|
|
|
|
break;
|
2016-03-10 12:03:55 +01:00
|
|
|
case BT_HCI_EVT_INQUIRY_RESULT_WITH_RSSI:
|
|
|
|
inquiry_result_with_rssi(buf);
|
|
|
|
break;
|
|
|
|
case BT_HCI_EVT_EXTENDED_INQUIRY_RESULT:
|
|
|
|
extended_inquiry_result(buf);
|
|
|
|
break;
|
2016-03-17 18:35:58 +01:00
|
|
|
case BT_HCI_EVT_REMOTE_NAME_REQ_COMPLETE:
|
|
|
|
remote_name_request_complete(buf);
|
|
|
|
break;
|
2016-03-18 14:13:23 +01:00
|
|
|
case BT_HCI_EVT_AUTH_COMPLETE:
|
|
|
|
auth_complete(buf);
|
|
|
|
break;
|
2016-06-17 21:27:41 +02:00
|
|
|
case BT_HCI_EVT_REMOTE_FEATURES:
|
|
|
|
read_remote_features_complete(buf);
|
|
|
|
break;
|
|
|
|
case BT_HCI_EVT_REMOTE_EXT_FEATURES:
|
|
|
|
read_remote_ext_features_complete(buf);
|
|
|
|
break;
|
2016-10-07 12:04:33 +02:00
|
|
|
case BT_HCI_EVT_ROLE_CHANGE:
|
|
|
|
role_change(buf);
|
|
|
|
break;
|
2017-02-15 15:08:25 +05:30
|
|
|
case BT_HCI_EVT_SYNC_CONN_COMPLETE:
|
|
|
|
synchronous_conn_complete(buf);
|
|
|
|
break;
|
2015-12-03 12:19:02 +01:00
|
|
|
#endif
|
2015-09-07 18:25:59 +02:00
|
|
|
#if defined(CONFIG_BLUETOOTH_CONN)
|
2015-04-18 18:52:54 +03:00
|
|
|
case BT_HCI_EVT_DISCONN_COMPLETE:
|
|
|
|
hci_disconn_complete(buf);
|
|
|
|
break;
|
2015-09-09 17:27:16 +02:00
|
|
|
#endif /* CONFIG_BLUETOOTH_CONN */
|
2016-01-08 11:11:56 +01:00
|
|
|
#if defined(CONFIG_BLUETOOTH_SMP) || defined(CONFIG_BLUETOOTH_BREDR)
|
2015-05-21 21:00:50 +03:00
|
|
|
case BT_HCI_EVT_ENCRYPT_CHANGE:
|
|
|
|
hci_encrypt_change(buf);
|
|
|
|
break;
|
2015-06-01 09:22:36 +07:00
|
|
|
case BT_HCI_EVT_ENCRYPT_KEY_REFRESH_COMPLETE:
|
|
|
|
hci_encrypt_key_refresh_complete(buf);
|
|
|
|
break;
|
2016-01-08 11:11:56 +01:00
|
|
|
#endif /* CONFIG_BLUETOOTH_SMP || CONFIG_BLUETOOTH_BREDR */
|
2015-04-18 18:37:03 +03:00
|
|
|
case BT_HCI_EVT_LE_META_EVENT:
|
|
|
|
hci_le_meta_event(buf);
|
|
|
|
break;
|
2015-04-14 15:41:55 +03:00
|
|
|
default:
|
2016-11-09 22:27:51 +02:00
|
|
|
BT_WARN("Unhandled event 0x%02x len %u: %s", hdr->evt,
|
|
|
|
buf->len, bt_hex(buf->data, buf->len));
|
2015-04-14 15:41:55 +03:00
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
2015-04-14 15:44:48 +03:00
|
|
|
|
2015-10-28 10:34:15 +02:00
|
|
|
net_buf_unref(buf);
|
2015-04-14 15:41:55 +03:00
|
|
|
}
|
|
|
|
|
2017-02-02 14:39:28 +02:00
|
|
|
static void send_cmd(void)
|
2015-04-14 15:41:55 +03:00
|
|
|
{
|
2017-02-02 14:39:28 +02:00
|
|
|
struct net_buf *buf;
|
|
|
|
int err;
|
2015-04-14 15:41:55 +03:00
|
|
|
|
2017-02-02 14:39:28 +02:00
|
|
|
/* Get next command */
|
|
|
|
BT_DBG("calling net_buf_get");
|
|
|
|
buf = net_buf_get(&bt_dev.cmd_tx_queue, K_NO_WAIT);
|
|
|
|
BT_ASSERT(buf);
|
|
|
|
|
|
|
|
/* Wait until ncmd > 0 */
|
|
|
|
BT_DBG("calling sem_take_wait");
|
|
|
|
k_sem_take(&bt_dev.ncmd_sem, K_FOREVER);
|
|
|
|
|
|
|
|
/* Clear out any existing sent command */
|
|
|
|
if (bt_dev.sent_cmd) {
|
|
|
|
BT_ERR("Uncleared pending sent_cmd");
|
|
|
|
net_buf_unref(bt_dev.sent_cmd);
|
|
|
|
bt_dev.sent_cmd = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
bt_dev.sent_cmd = net_buf_ref(buf);
|
|
|
|
|
|
|
|
BT_DBG("Sending command 0x%04x (buf %p) to driver",
|
|
|
|
cmd(buf)->opcode, buf);
|
|
|
|
|
|
|
|
err = bt_send(buf);
|
|
|
|
if (err) {
|
|
|
|
BT_ERR("Unable to send to driver (err %d)", err);
|
|
|
|
k_sem_give(&bt_dev.ncmd_sem);
|
|
|
|
hci_cmd_done(cmd(buf)->opcode, BT_HCI_ERR_UNSPECIFIED,
|
|
|
|
NULL);
|
|
|
|
net_buf_unref(bt_dev.sent_cmd);
|
|
|
|
bt_dev.sent_cmd = NULL;
|
|
|
|
net_buf_unref(buf);
|
|
|
|
}
|
|
|
|
}
|
2015-04-14 15:41:55 +03:00
|
|
|
|
2017-02-02 14:39:28 +02:00
|
|
|
static void process_events(struct k_poll_event *ev, int count)
|
|
|
|
{
|
|
|
|
BT_DBG("count %d", count);
|
2015-04-14 15:41:55 +03:00
|
|
|
|
2017-02-02 14:39:28 +02:00
|
|
|
for (; count; ev++, count--) {
|
|
|
|
BT_DBG("ev->state %u", ev->state);
|
2015-04-14 15:41:55 +03:00
|
|
|
|
2017-02-02 14:39:28 +02:00
|
|
|
switch (ev->state) {
|
|
|
|
case K_POLL_STATE_SIGNALED:
|
|
|
|
break;
|
|
|
|
case K_POLL_STATE_FIFO_DATA_AVAILABLE:
|
|
|
|
if (ev->tag == BT_EVENT_CMD_TX) {
|
|
|
|
send_cmd();
|
2017-03-17 08:02:57 +02:00
|
|
|
} else if (IS_ENABLED(CONFIG_BLUETOOTH_CONN)) {
|
2017-02-02 14:39:28 +02:00
|
|
|
struct bt_conn *conn;
|
|
|
|
|
2017-03-17 08:02:57 +02:00
|
|
|
if (ev->tag == BT_EVENT_CONN_TX_NOTIFY) {
|
|
|
|
conn = CONTAINER_OF(ev->fifo,
|
|
|
|
struct bt_conn,
|
|
|
|
tx_notify);
|
|
|
|
bt_conn_notify_tx(conn);
|
|
|
|
} else if (ev->tag == BT_EVENT_CONN_TX_QUEUE) {
|
|
|
|
conn = CONTAINER_OF(ev->fifo,
|
|
|
|
struct bt_conn,
|
|
|
|
tx_queue);
|
|
|
|
bt_conn_process_tx(conn);
|
|
|
|
}
|
2017-02-02 14:39:28 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case K_POLL_STATE_NOT_READY:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
BT_WARN("Unexpected k_poll event state %u", ev->state);
|
|
|
|
break;
|
2015-04-28 15:16:03 +03:00
|
|
|
}
|
2017-02-02 14:39:28 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(CONFIG_BLUETOOTH_CONN)
|
2017-03-17 08:02:57 +02:00
|
|
|
/* command FIFO + conn_change signal + MAX_CONN * 2 (tx & tx_notify) */
|
|
|
|
#define EV_COUNT (2 + (CONFIG_BLUETOOTH_MAX_CONN * 2))
|
2017-02-02 14:39:28 +02:00
|
|
|
#else
|
|
|
|
/* command FIFO */
|
|
|
|
#define EV_COUNT 1
|
|
|
|
#endif
|
2015-04-28 15:16:03 +03:00
|
|
|
|
2017-02-02 14:39:28 +02:00
|
|
|
static void hci_tx_thread(void *p1, void *p2, void *p3)
|
|
|
|
{
|
|
|
|
static struct k_poll_event events[EV_COUNT] = {
|
|
|
|
K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_FIFO_DATA_AVAILABLE,
|
|
|
|
K_POLL_MODE_NOTIFY_ONLY,
|
|
|
|
&bt_dev.cmd_tx_queue,
|
|
|
|
BT_EVENT_CMD_TX),
|
|
|
|
};
|
2015-11-04 21:18:03 +02:00
|
|
|
|
2017-02-02 14:39:28 +02:00
|
|
|
BT_DBG("Started");
|
2015-09-15 17:57:00 +03:00
|
|
|
|
2017-02-02 14:39:28 +02:00
|
|
|
while (1) {
|
|
|
|
int ev_count, err;
|
|
|
|
|
|
|
|
events[0].state = K_POLL_STATE_NOT_READY;
|
|
|
|
ev_count = 1;
|
|
|
|
|
|
|
|
if (IS_ENABLED(CONFIG_BLUETOOTH_CONN)) {
|
|
|
|
ev_count += bt_conn_prepare_events(&events[1]);
|
2015-09-15 17:57:00 +03:00
|
|
|
}
|
2017-02-02 14:39:28 +02:00
|
|
|
|
|
|
|
BT_DBG("Calling k_poll with %d events", ev_count);
|
|
|
|
|
|
|
|
err = k_poll(events, ev_count, K_FOREVER);
|
|
|
|
BT_ASSERT(err == 0);
|
|
|
|
|
|
|
|
process_events(events, ev_count);
|
|
|
|
|
|
|
|
/* Make sure we don't hog the CPU if there's all the time
|
|
|
|
* some ready events.
|
|
|
|
*/
|
|
|
|
k_yield();
|
2015-04-14 15:41:55 +03:00
|
|
|
}
|
2015-04-14 15:32:32 +03:00
|
|
|
}
|
|
|
|
|
2017-02-02 14:39:28 +02:00
|
|
|
|
2015-10-28 10:34:15 +02:00
|
|
|
static void read_local_ver_complete(struct net_buf *buf)
|
2015-04-30 13:19:44 +03:00
|
|
|
{
|
|
|
|
struct bt_hci_rp_read_local_version_info *rp = (void *)buf->data;
|
|
|
|
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_DBG("status %u", rp->status);
|
2015-04-30 13:19:44 +03:00
|
|
|
|
2015-07-15 13:53:17 +03:00
|
|
|
bt_dev.hci_version = rp->hci_version;
|
|
|
|
bt_dev.hci_revision = sys_le16_to_cpu(rp->hci_revision);
|
2016-11-04 15:10:34 +02:00
|
|
|
bt_dev.lmp_version = rp->lmp_version;
|
|
|
|
bt_dev.lmp_subversion = sys_le16_to_cpu(rp->lmp_subversion);
|
2015-07-15 13:53:17 +03:00
|
|
|
bt_dev.manufacturer = sys_le16_to_cpu(rp->manufacturer);
|
2015-04-30 13:19:44 +03:00
|
|
|
}
|
|
|
|
|
2015-10-28 10:34:15 +02:00
|
|
|
static void read_bdaddr_complete(struct net_buf *buf)
|
2015-04-30 13:19:44 +03:00
|
|
|
{
|
|
|
|
struct bt_hci_rp_read_bd_addr *rp = (void *)buf->data;
|
|
|
|
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_DBG("status %u", rp->status);
|
2015-04-30 13:19:44 +03:00
|
|
|
|
2016-04-04 13:06:55 +03:00
|
|
|
bt_addr_copy(&bt_dev.id_addr.a, &rp->bdaddr);
|
2016-04-02 09:42:08 +03:00
|
|
|
bt_dev.id_addr.type = BT_ADDR_LE_PUBLIC;
|
2015-04-30 13:19:44 +03:00
|
|
|
}
|
|
|
|
|
2015-10-28 10:34:15 +02:00
|
|
|
static void read_le_features_complete(struct net_buf *buf)
|
2015-04-30 13:19:44 +03:00
|
|
|
{
|
|
|
|
struct bt_hci_rp_le_read_local_features *rp = (void *)buf->data;
|
|
|
|
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_DBG("status %u", rp->status);
|
2015-04-30 13:19:44 +03:00
|
|
|
|
2015-11-03 11:19:19 +01:00
|
|
|
memcpy(bt_dev.le.features, rp->features, sizeof(bt_dev.le.features));
|
2015-04-30 13:19:44 +03:00
|
|
|
}
|
|
|
|
|
2015-11-16 14:57:58 +01:00
|
|
|
#if defined(CONFIG_BLUETOOTH_BREDR)
|
|
|
|
static void read_buffer_size_complete(struct net_buf *buf)
|
|
|
|
{
|
|
|
|
struct bt_hci_rp_read_buffer_size *rp = (void *)buf->data;
|
2017-04-20 12:00:29 -05:00
|
|
|
u16_t pkts;
|
2015-11-16 14:57:58 +01:00
|
|
|
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_DBG("status %u", rp->status);
|
2015-11-16 14:57:58 +01:00
|
|
|
|
|
|
|
bt_dev.br.mtu = sys_le16_to_cpu(rp->acl_max_len);
|
2015-11-18 08:59:26 +01:00
|
|
|
pkts = sys_le16_to_cpu(rp->acl_max_num);
|
|
|
|
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_DBG("ACL BR/EDR buffers: pkts %u mtu %u", pkts, bt_dev.br.mtu);
|
2015-11-18 08:59:26 +01:00
|
|
|
|
2016-10-27 11:32:30 +02:00
|
|
|
k_sem_init(&bt_dev.br.pkts, pkts, pkts);
|
2015-11-16 14:57:58 +01:00
|
|
|
}
|
2017-03-19 13:35:09 +02:00
|
|
|
#elif defined(CONFIG_BLUETOOTH_CONN)
|
2015-10-28 10:34:15 +02:00
|
|
|
static void read_buffer_size_complete(struct net_buf *buf)
|
2015-04-30 13:19:44 +03:00
|
|
|
{
|
|
|
|
struct bt_hci_rp_read_buffer_size *rp = (void *)buf->data;
|
2017-04-20 12:00:29 -05:00
|
|
|
u16_t pkts;
|
2015-04-30 13:19:44 +03:00
|
|
|
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_DBG("status %u", rp->status);
|
2015-04-30 13:19:44 +03:00
|
|
|
|
|
|
|
/* If LE-side has buffers we can ignore the BR/EDR values */
|
2015-11-03 11:19:19 +01:00
|
|
|
if (bt_dev.le.mtu) {
|
2015-04-30 13:19:44 +03:00
|
|
|
return;
|
2015-05-05 10:50:14 +03:00
|
|
|
}
|
2015-04-30 13:19:44 +03:00
|
|
|
|
2015-11-03 11:19:19 +01:00
|
|
|
bt_dev.le.mtu = sys_le16_to_cpu(rp->acl_max_len);
|
2015-11-18 08:02:55 +01:00
|
|
|
pkts = sys_le16_to_cpu(rp->acl_max_num);
|
|
|
|
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_DBG("ACL BR/EDR buffers: pkts %u mtu %u", pkts, bt_dev.le.mtu);
|
2015-11-18 08:02:55 +01:00
|
|
|
|
2017-03-17 08:02:57 +02:00
|
|
|
pkts = min(pkts, CONFIG_BLUETOOTH_CONN_TX_MAX);
|
|
|
|
|
2016-10-27 11:32:30 +02:00
|
|
|
k_sem_init(&bt_dev.le.pkts, pkts, pkts);
|
2015-04-30 13:19:44 +03:00
|
|
|
}
|
2015-11-16 14:57:58 +01:00
|
|
|
#endif
|
2015-04-30 13:19:44 +03:00
|
|
|
|
2017-03-19 13:35:09 +02:00
|
|
|
#if defined(CONFIG_BLUETOOTH_CONN)
|
2015-10-28 10:34:15 +02:00
|
|
|
static void le_read_buffer_size_complete(struct net_buf *buf)
|
2015-04-30 13:19:44 +03:00
|
|
|
{
|
|
|
|
struct bt_hci_rp_le_read_buffer_size *rp = (void *)buf->data;
|
2017-04-20 12:00:29 -05:00
|
|
|
u8_t le_max_num;
|
2015-04-30 13:19:44 +03:00
|
|
|
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_DBG("status %u", rp->status);
|
2015-04-30 13:19:44 +03:00
|
|
|
|
2015-11-03 11:19:19 +01:00
|
|
|
bt_dev.le.mtu = sys_le16_to_cpu(rp->le_max_len);
|
2017-03-17 08:02:57 +02:00
|
|
|
if (!bt_dev.le.mtu) {
|
|
|
|
return;
|
2015-11-18 08:02:55 +01:00
|
|
|
}
|
2017-03-17 08:02:57 +02:00
|
|
|
|
|
|
|
BT_DBG("ACL LE buffers: pkts %u mtu %u", rp->le_max_num, bt_dev.le.mtu);
|
|
|
|
|
|
|
|
le_max_num = min(rp->le_max_num, CONFIG_BLUETOOTH_CONN_TX_MAX);
|
|
|
|
k_sem_init(&bt_dev.le.pkts, le_max_num, le_max_num);
|
2015-04-30 13:19:44 +03:00
|
|
|
}
|
2017-03-19 13:35:09 +02:00
|
|
|
#endif
|
2015-04-30 13:19:44 +03:00
|
|
|
|
2015-10-21 16:09:37 +02:00
|
|
|
static void read_supported_commands_complete(struct net_buf *buf)
|
|
|
|
{
|
|
|
|
struct bt_hci_rp_read_supported_commands *rp = (void *)buf->data;
|
|
|
|
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_DBG("status %u", rp->status);
|
2015-10-21 16:09:37 +02:00
|
|
|
|
|
|
|
memcpy(bt_dev.supported_commands, rp->commands,
|
|
|
|
sizeof(bt_dev.supported_commands));
|
2016-05-24 17:15:03 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Report "LE Read Local P-256 Public Key" and "LE Generate DH Key" as
|
|
|
|
* supported if TinyCrypt ECC is used for emulation.
|
|
|
|
*/
|
2017-01-17 14:28:01 +02:00
|
|
|
if (IS_ENABLED(CONFIG_BLUETOOTH_TINYCRYPT_ECC)) {
|
|
|
|
bt_dev.supported_commands[34] |= 0x02;
|
|
|
|
bt_dev.supported_commands[34] |= 0x04;
|
|
|
|
}
|
2015-10-21 16:09:37 +02:00
|
|
|
}
|
|
|
|
|
2016-08-27 20:06:18 +03:00
|
|
|
static void read_local_features_complete(struct net_buf *buf)
|
2015-09-15 14:25:26 +02:00
|
|
|
{
|
2016-08-27 20:06:18 +03:00
|
|
|
struct bt_hci_rp_read_local_features *rp = (void *)buf->data;
|
2015-04-14 15:44:48 +03:00
|
|
|
|
2016-08-27 20:06:18 +03:00
|
|
|
BT_DBG("status %u", rp->status);
|
2015-04-14 15:41:55 +03:00
|
|
|
|
2016-08-27 20:06:18 +03:00
|
|
|
memcpy(bt_dev.features[0], rp->features, sizeof(bt_dev.features[0]));
|
|
|
|
}
|
|
|
|
|
2016-08-30 06:08:27 +02:00
|
|
|
static void le_read_supp_states_complete(struct net_buf *buf)
|
|
|
|
{
|
|
|
|
struct bt_hci_rp_le_read_supp_states *rp = (void *)buf->data;
|
|
|
|
|
|
|
|
BT_DBG("status %u", rp->status);
|
|
|
|
|
|
|
|
bt_dev.le.states = sys_get_le64(rp->le_states);
|
|
|
|
}
|
|
|
|
|
2016-08-27 20:06:18 +03:00
|
|
|
static int common_init(void)
|
|
|
|
{
|
|
|
|
struct net_buf *rsp;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
/* Send HCI_RESET */
|
|
|
|
err = bt_hci_cmd_send_sync(BT_HCI_OP_RESET, NULL, &rsp);
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
hci_reset_complete(rsp);
|
|
|
|
net_buf_unref(rsp);
|
|
|
|
|
2017-03-15 11:19:27 +01:00
|
|
|
#if defined(CONFIG_BLUETOOTH_HOST_CRYPTO)
|
2016-08-27 20:06:18 +03:00
|
|
|
/*
|
|
|
|
* initialize PRNG right after reset so that it is safe to use it later
|
|
|
|
* on in initialization process
|
|
|
|
*/
|
2017-03-15 11:19:27 +01:00
|
|
|
err = prng_init();
|
2016-08-27 20:06:18 +03:00
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
2017-01-09 13:42:17 +02:00
|
|
|
#endif
|
2016-08-27 20:06:18 +03:00
|
|
|
|
|
|
|
/* Read Local Supported Features */
|
|
|
|
err = bt_hci_cmd_send_sync(BT_HCI_OP_READ_LOCAL_FEATURES, NULL, &rsp);
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
read_local_features_complete(rsp);
|
|
|
|
net_buf_unref(rsp);
|
|
|
|
|
2015-04-14 15:44:48 +03:00
|
|
|
/* Read Local Version Information */
|
2015-04-30 13:19:44 +03:00
|
|
|
err = bt_hci_cmd_send_sync(BT_HCI_OP_READ_LOCAL_VERSION_INFO, NULL,
|
|
|
|
&rsp);
|
2015-05-05 10:50:14 +03:00
|
|
|
if (err) {
|
2015-04-30 13:19:44 +03:00
|
|
|
return err;
|
2015-05-05 10:50:14 +03:00
|
|
|
}
|
2015-04-30 13:19:44 +03:00
|
|
|
read_local_ver_complete(rsp);
|
2015-10-28 10:34:15 +02:00
|
|
|
net_buf_unref(rsp);
|
2015-04-14 15:44:48 +03:00
|
|
|
|
|
|
|
/* Read Bluetooth Address */
|
2015-04-30 13:19:44 +03:00
|
|
|
err = bt_hci_cmd_send_sync(BT_HCI_OP_READ_BD_ADDR, NULL, &rsp);
|
2015-05-05 10:50:14 +03:00
|
|
|
if (err) {
|
2015-04-30 13:19:44 +03:00
|
|
|
return err;
|
2015-05-05 10:50:14 +03:00
|
|
|
}
|
2015-04-30 13:19:44 +03:00
|
|
|
read_bdaddr_complete(rsp);
|
2015-10-28 10:34:15 +02:00
|
|
|
net_buf_unref(rsp);
|
2015-04-14 15:44:48 +03:00
|
|
|
|
2016-04-01 08:37:18 +03:00
|
|
|
/* Read Local Supported Commands */
|
|
|
|
err = bt_hci_cmd_send_sync(BT_HCI_OP_READ_SUPPORTED_COMMANDS, NULL,
|
|
|
|
&rsp);
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
read_supported_commands_complete(rsp);
|
|
|
|
net_buf_unref(rsp);
|
|
|
|
|
2017-05-04 16:09:53 +02:00
|
|
|
#if defined(CONFIG_BLUETOOTH_HCI_ACL_FLOW_CONTROL)
|
2017-05-04 14:09:10 +03:00
|
|
|
err = set_flow_control();
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_BLUETOOTH_CONN */
|
|
|
|
|
2015-10-30 12:46:08 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-05-05 13:33:48 +02:00
|
|
|
static int le_set_event_mask(void)
|
|
|
|
{
|
|
|
|
struct bt_hci_cp_le_set_event_mask *cp_mask;
|
|
|
|
struct net_buf *buf;
|
|
|
|
u64_t mask = 0;
|
|
|
|
|
|
|
|
/* Set LE event mask */
|
|
|
|
buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_EVENT_MASK, sizeof(*cp_mask));
|
|
|
|
if (!buf) {
|
|
|
|
return -ENOBUFS;
|
|
|
|
}
|
|
|
|
|
|
|
|
cp_mask = net_buf_add(buf, sizeof(*cp_mask));
|
|
|
|
|
|
|
|
mask |= BT_EVT_MASK_LE_ADVERTISING_REPORT;
|
|
|
|
|
|
|
|
if (IS_ENABLED(CONFIG_BLUETOOTH_CONN)) {
|
|
|
|
mask |= BT_EVT_MASK_LE_CONN_COMPLETE;
|
|
|
|
mask |= BT_EVT_MASK_LE_CONN_UPDATE_COMPLETE;
|
|
|
|
mask |= BT_EVT_MASK_LE_REMOTE_FEAT_COMPLETE;
|
|
|
|
if (BT_FEAT_LE_CONN_PARAM_REQ_PROC(bt_dev.le.features)) {
|
|
|
|
mask |= BT_EVT_MASK_LE_CONN_PARAM_REQ;
|
|
|
|
}
|
2017-05-15 23:18:08 +02:00
|
|
|
if (BT_FEAT_LE_DLE(bt_dev.le.features)) {
|
|
|
|
mask |= BT_EVT_MASK_LE_DATA_LEN_CHANGE;
|
|
|
|
}
|
2017-05-06 07:10:50 +02:00
|
|
|
if (BT_FEAT_LE_PHY_2M(bt_dev.le.features) ||
|
|
|
|
BT_FEAT_LE_PHY_CODED(bt_dev.le.features)) {
|
|
|
|
mask |= BT_EVT_MASK_LE_PHY_UPDATE_COMPLETE;
|
|
|
|
}
|
2017-05-05 13:33:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (IS_ENABLED(CONFIG_BLUETOOTH_SMP) &&
|
|
|
|
BT_FEAT_LE_ENCR(bt_dev.le.features)) {
|
|
|
|
mask |= BT_EVT_MASK_LE_LTK_REQUEST;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If "LE Read Local P-256 Public Key" and "LE Generate DH Key" are
|
|
|
|
* supported we need to enable events generated by those commands.
|
|
|
|
*/
|
|
|
|
if ((bt_dev.supported_commands[34] & 0x02) &&
|
|
|
|
(bt_dev.supported_commands[34] & 0x04)) {
|
|
|
|
mask |= BT_EVT_MASK_LE_P256_PUBLIC_KEY_COMPLETE;
|
|
|
|
mask |= BT_EVT_MASK_LE_GENERATE_DHKEY_COMPLETE;
|
|
|
|
}
|
|
|
|
|
|
|
|
sys_put_le64(mask, cp_mask->events);
|
|
|
|
return bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_EVENT_MASK, buf, NULL);
|
|
|
|
}
|
|
|
|
|
2015-10-30 12:46:08 +01:00
|
|
|
static int le_init(void)
|
|
|
|
{
|
2015-11-16 12:19:19 +01:00
|
|
|
struct bt_hci_cp_write_le_host_supp *cp_le;
|
|
|
|
struct net_buf *buf;
|
2015-10-30 12:46:08 +01:00
|
|
|
struct net_buf *rsp;
|
|
|
|
int err;
|
|
|
|
|
2015-04-14 15:44:48 +03:00
|
|
|
/* For now we only support LE capable controllers */
|
2016-08-28 16:01:28 +03:00
|
|
|
if (!BT_FEAT_LE(bt_dev.features)) {
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_ERR("Non-LE capable controller detected!");
|
2015-04-14 15:44:48 +03:00
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Read Low Energy Supported Features */
|
2015-04-30 13:19:44 +03:00
|
|
|
err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_READ_LOCAL_FEATURES, NULL,
|
|
|
|
&rsp);
|
2015-05-05 10:50:14 +03:00
|
|
|
if (err) {
|
2015-04-30 13:19:44 +03:00
|
|
|
return err;
|
2015-05-05 10:50:14 +03:00
|
|
|
}
|
2015-04-30 13:19:44 +03:00
|
|
|
read_le_features_complete(rsp);
|
2015-10-28 10:34:15 +02:00
|
|
|
net_buf_unref(rsp);
|
2015-04-14 15:44:48 +03:00
|
|
|
|
2017-03-19 13:35:09 +02:00
|
|
|
#if defined(CONFIG_BLUETOOTH_CONN)
|
2015-04-14 15:44:48 +03:00
|
|
|
/* Read LE Buffer Size */
|
2017-03-19 13:35:09 +02:00
|
|
|
err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_READ_BUFFER_SIZE,
|
|
|
|
NULL, &rsp);
|
2015-05-05 10:50:14 +03:00
|
|
|
if (err) {
|
2015-04-30 13:19:44 +03:00
|
|
|
return err;
|
2015-05-05 10:50:14 +03:00
|
|
|
}
|
2015-04-30 13:19:44 +03:00
|
|
|
le_read_buffer_size_complete(rsp);
|
2015-10-28 10:34:15 +02:00
|
|
|
net_buf_unref(rsp);
|
2017-03-19 13:35:09 +02:00
|
|
|
#endif
|
2015-04-14 15:44:48 +03:00
|
|
|
|
2016-08-28 16:01:28 +03:00
|
|
|
if (BT_FEAT_BREDR(bt_dev.features)) {
|
2015-10-30 12:46:08 +01:00
|
|
|
buf = bt_hci_cmd_create(BT_HCI_OP_LE_WRITE_LE_HOST_SUPP,
|
2015-11-16 12:19:19 +01:00
|
|
|
sizeof(*cp_le));
|
2015-10-30 12:46:08 +01:00
|
|
|
if (!buf) {
|
|
|
|
return -ENOBUFS;
|
|
|
|
}
|
|
|
|
|
2015-11-16 12:19:19 +01:00
|
|
|
cp_le = net_buf_add(buf, sizeof(*cp_le));
|
2015-10-30 12:46:08 +01:00
|
|
|
|
2016-08-22 16:38:01 +02:00
|
|
|
/* Explicitly enable LE for dual-mode controllers */
|
2015-11-16 12:19:19 +01:00
|
|
|
cp_le->le = 0x01;
|
|
|
|
cp_le->simul = 0x00;
|
|
|
|
err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_WRITE_LE_HOST_SUPP, buf,
|
|
|
|
NULL);
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
2015-10-30 12:46:08 +01:00
|
|
|
}
|
|
|
|
|
2016-08-30 06:08:27 +02:00
|
|
|
/* Read LE Supported States */
|
|
|
|
if (BT_CMD_LE_STATES(bt_dev.supported_commands)) {
|
|
|
|
err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_READ_SUPP_STATES, NULL,
|
|
|
|
&rsp);
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
le_read_supp_states_complete(rsp);
|
|
|
|
net_buf_unref(rsp);
|
|
|
|
}
|
|
|
|
|
2017-05-28 12:18:53 +03:00
|
|
|
if (IS_ENABLED(CONFIG_BLUETOOTH_CONN) &&
|
|
|
|
BT_FEAT_LE_DLE(bt_dev.le.features)) {
|
2017-05-15 23:18:08 +02:00
|
|
|
struct bt_hci_cp_le_write_default_data_len *cp;
|
|
|
|
struct bt_hci_rp_le_read_max_data_len *rp;
|
|
|
|
struct net_buf *buf, *rsp;
|
|
|
|
u16_t tx_octets, tx_time;
|
|
|
|
|
|
|
|
err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_READ_MAX_DATA_LEN, NULL,
|
|
|
|
&rsp);
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
rp = (void *)rsp->data;
|
|
|
|
tx_octets = sys_le16_to_cpu(rp->max_tx_octets);
|
|
|
|
tx_time = sys_le16_to_cpu(rp->max_tx_time);
|
|
|
|
net_buf_unref(rsp);
|
|
|
|
|
|
|
|
buf = bt_hci_cmd_create(BT_HCI_OP_LE_WRITE_DEFAULT_DATA_LEN,
|
|
|
|
sizeof(*cp));
|
|
|
|
if (!buf) {
|
|
|
|
return -ENOBUFS;
|
|
|
|
}
|
|
|
|
|
|
|
|
cp = net_buf_add(buf, sizeof(*cp));
|
|
|
|
cp->max_tx_octets = sys_cpu_to_le16(tx_octets);
|
|
|
|
cp->max_tx_time = sys_cpu_to_le16(tx_time);
|
|
|
|
|
|
|
|
err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_WRITE_DEFAULT_DATA_LEN,
|
|
|
|
buf, NULL);
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-05 13:33:48 +02:00
|
|
|
return le_set_event_mask();
|
2015-10-30 12:46:08 +01:00
|
|
|
}
|
|
|
|
|
2015-11-16 14:57:58 +01:00
|
|
|
#if defined(CONFIG_BLUETOOTH_BREDR)
|
2016-08-29 14:53:46 +02:00
|
|
|
static int read_ext_features(void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* Read Local Supported Extended Features */
|
|
|
|
for (i = 1; i < LMP_FEAT_PAGES_COUNT; i++) {
|
|
|
|
struct bt_hci_cp_read_local_ext_features *cp;
|
|
|
|
struct bt_hci_rp_read_local_ext_features *rp;
|
|
|
|
struct net_buf *buf, *rsp;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
buf = bt_hci_cmd_create(BT_HCI_OP_READ_LOCAL_EXT_FEATURES,
|
|
|
|
sizeof(*cp));
|
|
|
|
if (!buf) {
|
|
|
|
return -ENOBUFS;
|
|
|
|
}
|
|
|
|
|
|
|
|
cp = net_buf_add(buf, sizeof(*cp));
|
|
|
|
cp->page = i;
|
|
|
|
|
|
|
|
err = bt_hci_cmd_send_sync(BT_HCI_OP_READ_LOCAL_EXT_FEATURES,
|
|
|
|
buf, &rsp);
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
rp = (void *)rsp->data;
|
|
|
|
|
|
|
|
memcpy(&bt_dev.features[i], rp->ext_features,
|
|
|
|
sizeof(bt_dev.features[i]));
|
|
|
|
|
|
|
|
if (rp->max_page <= i) {
|
|
|
|
net_buf_unref(rsp);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
net_buf_unref(rsp);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-02-13 11:47:11 +05:30
|
|
|
void device_supported_pkt_type(void)
|
|
|
|
{
|
|
|
|
/* Device supported features and sco packet types */
|
|
|
|
if (BT_FEAT_HV2_PKT(bt_dev.features)) {
|
2017-04-21 13:47:08 +03:00
|
|
|
bt_dev.br.esco_pkt_type |= (HCI_PKT_TYPE_ESCO_HV2);
|
2017-02-13 11:47:11 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
if (BT_FEAT_HV3_PKT(bt_dev.features)) {
|
2017-04-21 13:47:08 +03:00
|
|
|
bt_dev.br.esco_pkt_type |= (HCI_PKT_TYPE_ESCO_HV3);
|
2017-02-13 11:47:11 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
if (BT_FEAT_LMP_ESCO_CAPABLE(bt_dev.features)) {
|
2017-04-21 13:47:08 +03:00
|
|
|
bt_dev.br.esco_pkt_type |= (HCI_PKT_TYPE_ESCO_EV3);
|
2017-02-13 11:47:11 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
if (BT_FEAT_EV4_PKT(bt_dev.features)) {
|
2017-04-21 13:47:08 +03:00
|
|
|
bt_dev.br.esco_pkt_type |= (HCI_PKT_TYPE_ESCO_EV4);
|
2017-02-13 11:47:11 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
if (BT_FEAT_EV5_PKT(bt_dev.features)) {
|
2017-04-21 13:47:08 +03:00
|
|
|
bt_dev.br.esco_pkt_type |= (HCI_PKT_TYPE_ESCO_EV5);
|
2017-02-13 11:47:11 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
if (BT_FEAT_2EV3_PKT(bt_dev.features)) {
|
2017-04-21 13:47:08 +03:00
|
|
|
bt_dev.br.esco_pkt_type |= (HCI_PKT_TYPE_ESCO_2EV3);
|
2017-02-13 11:47:11 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
if (BT_FEAT_3EV3_PKT(bt_dev.features)) {
|
2017-04-21 13:47:08 +03:00
|
|
|
bt_dev.br.esco_pkt_type |= (HCI_PKT_TYPE_ESCO_3EV3);
|
2017-02-13 11:47:11 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
if (BT_FEAT_3SLOT_PKT(bt_dev.features)) {
|
2017-04-21 13:47:08 +03:00
|
|
|
bt_dev.br.esco_pkt_type |= (HCI_PKT_TYPE_ESCO_2EV5 |
|
|
|
|
HCI_PKT_TYPE_ESCO_3EV5);
|
2017-02-13 11:47:11 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-16 14:57:58 +01:00
|
|
|
static int br_init(void)
|
|
|
|
{
|
2016-02-22 10:55:29 +01:00
|
|
|
struct net_buf *buf;
|
2016-03-10 11:58:56 +01:00
|
|
|
struct bt_hci_cp_write_ssp_mode *ssp_cp;
|
|
|
|
struct bt_hci_cp_write_inquiry_mode *inq_cp;
|
2016-08-09 10:06:41 +02:00
|
|
|
struct bt_hci_write_local_name *name_cp;
|
2015-11-16 14:57:58 +01:00
|
|
|
int err;
|
|
|
|
|
2016-08-29 14:53:46 +02:00
|
|
|
/* Read extended local features */
|
|
|
|
if (BT_FEAT_EXT_FEATURES(bt_dev.features)) {
|
|
|
|
err = read_ext_features();
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-13 11:47:11 +05:30
|
|
|
/* Add local supported packet types to bt_dev */
|
|
|
|
device_supported_pkt_type();
|
|
|
|
|
2015-11-16 14:57:58 +01:00
|
|
|
/* Get BR/EDR buffer size */
|
2016-02-22 10:55:29 +01:00
|
|
|
err = bt_hci_cmd_send_sync(BT_HCI_OP_READ_BUFFER_SIZE, NULL, &buf);
|
2015-11-16 14:57:58 +01:00
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2016-02-22 10:55:29 +01:00
|
|
|
read_buffer_size_complete(buf);
|
|
|
|
net_buf_unref(buf);
|
2015-11-16 14:57:58 +01:00
|
|
|
|
2016-01-16 22:29:59 +01:00
|
|
|
/* Set SSP mode */
|
2016-03-10 11:58:56 +01:00
|
|
|
buf = bt_hci_cmd_create(BT_HCI_OP_WRITE_SSP_MODE, sizeof(*ssp_cp));
|
2016-01-16 22:29:59 +01:00
|
|
|
if (!buf) {
|
|
|
|
return -ENOBUFS;
|
|
|
|
}
|
|
|
|
|
2016-03-10 11:58:56 +01:00
|
|
|
ssp_cp = net_buf_add(buf, sizeof(*ssp_cp));
|
|
|
|
ssp_cp->mode = 0x01;
|
2016-01-16 22:29:59 +01:00
|
|
|
err = bt_hci_cmd_send_sync(BT_HCI_OP_WRITE_SSP_MODE, buf, NULL);
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2016-03-10 11:58:56 +01:00
|
|
|
/* Enable Inquiry results with RSSI or extended Inquiry */
|
|
|
|
buf = bt_hci_cmd_create(BT_HCI_OP_WRITE_INQUIRY_MODE, sizeof(*inq_cp));
|
|
|
|
if (!buf) {
|
|
|
|
return -ENOBUFS;
|
|
|
|
}
|
|
|
|
|
|
|
|
inq_cp = net_buf_add(buf, sizeof(*inq_cp));
|
|
|
|
inq_cp->mode = 0x02;
|
|
|
|
err = bt_hci_cmd_send_sync(BT_HCI_OP_WRITE_INQUIRY_MODE, buf, NULL);
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2016-08-09 10:06:41 +02:00
|
|
|
/* Set local name */
|
|
|
|
buf = bt_hci_cmd_create(BT_HCI_OP_WRITE_LOCAL_NAME, sizeof(*name_cp));
|
|
|
|
if (!buf) {
|
|
|
|
return -ENOBUFS;
|
|
|
|
}
|
|
|
|
|
|
|
|
name_cp = net_buf_add(buf, sizeof(*name_cp));
|
2017-01-27 15:20:32 +02:00
|
|
|
strncpy((char *)name_cp->local_name, CONFIG_BLUETOOTH_DEVICE_NAME,
|
2016-08-09 10:06:41 +02:00
|
|
|
sizeof(name_cp->local_name));
|
|
|
|
|
|
|
|
err = bt_hci_cmd_send_sync(BT_HCI_OP_WRITE_LOCAL_NAME, buf, NULL);
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2016-10-12 15:26:32 +05:30
|
|
|
/* Set page timeout*/
|
2017-04-20 12:00:29 -05:00
|
|
|
buf = bt_hci_cmd_create(BT_HCI_OP_WRITE_PAGE_TIMEOUT, sizeof(u16_t));
|
2016-10-12 15:26:32 +05:30
|
|
|
if (!buf) {
|
|
|
|
return -ENOBUFS;
|
|
|
|
}
|
|
|
|
|
|
|
|
net_buf_add_le16(buf, CONFIG_BLUETOOTH_PAGE_TIMEOUT);
|
|
|
|
|
|
|
|
err = bt_hci_cmd_send_sync(BT_HCI_OP_WRITE_PAGE_TIMEOUT, buf, NULL);
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2016-08-24 11:59:45 +02:00
|
|
|
/* Enable BR/EDR SC if supported */
|
2016-08-28 16:01:28 +03:00
|
|
|
if (BT_FEAT_SC(bt_dev.features)) {
|
2016-08-24 11:59:45 +02:00
|
|
|
struct bt_hci_cp_write_sc_host_supp *sc_cp;
|
|
|
|
|
|
|
|
buf = bt_hci_cmd_create(BT_HCI_OP_WRITE_SC_HOST_SUPP,
|
|
|
|
sizeof(*sc_cp));
|
|
|
|
if (!buf) {
|
|
|
|
return -ENOBUFS;
|
|
|
|
}
|
|
|
|
|
|
|
|
sc_cp = net_buf_add(buf, sizeof(*sc_cp));
|
|
|
|
sc_cp->sc_support = 0x01;
|
|
|
|
|
|
|
|
err = bt_hci_cmd_send_sync(BT_HCI_OP_WRITE_SC_HOST_SUPP, buf,
|
|
|
|
NULL);
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-16 14:57:58 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#else
|
2015-10-30 12:46:08 +01:00
|
|
|
static int br_init(void)
|
|
|
|
{
|
2017-03-19 13:35:09 +02:00
|
|
|
#if defined(CONFIG_BLUETOOTH_CONN)
|
2015-10-30 12:46:08 +01:00
|
|
|
struct net_buf *rsp;
|
|
|
|
int err;
|
|
|
|
|
2015-11-03 14:45:59 +01:00
|
|
|
if (bt_dev.le.mtu) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-10-30 12:46:08 +01:00
|
|
|
/* Use BR/EDR buffer size if LE reports zero buffers */
|
2015-11-03 14:45:59 +01:00
|
|
|
err = bt_hci_cmd_send_sync(BT_HCI_OP_READ_BUFFER_SIZE, NULL, &rsp);
|
|
|
|
if (err) {
|
|
|
|
return err;
|
2015-10-30 12:46:08 +01:00
|
|
|
}
|
|
|
|
|
2015-11-03 14:45:59 +01:00
|
|
|
read_buffer_size_complete(rsp);
|
|
|
|
net_buf_unref(rsp);
|
2017-03-19 13:35:09 +02:00
|
|
|
#endif /* CONFIG_BLUETOOTH_CONN */
|
2015-11-03 14:45:59 +01:00
|
|
|
|
2015-10-30 12:46:08 +01:00
|
|
|
return 0;
|
|
|
|
}
|
2015-11-16 14:57:58 +01:00
|
|
|
#endif
|
2015-10-30 12:46:08 +01:00
|
|
|
|
|
|
|
static int set_event_mask(void)
|
|
|
|
{
|
|
|
|
struct bt_hci_cp_set_event_mask *ev;
|
|
|
|
struct net_buf *buf;
|
2017-04-20 12:00:29 -05:00
|
|
|
u64_t mask = 0;
|
2015-10-30 12:46:08 +01:00
|
|
|
|
2015-05-08 12:49:09 +03:00
|
|
|
buf = bt_hci_cmd_create(BT_HCI_OP_SET_EVENT_MASK, sizeof(*ev));
|
2015-05-05 10:50:14 +03:00
|
|
|
if (!buf) {
|
2015-04-14 15:44:48 +03:00
|
|
|
return -ENOBUFS;
|
2015-05-05 10:50:14 +03:00
|
|
|
}
|
2015-04-14 15:44:48 +03:00
|
|
|
|
2015-10-28 10:34:15 +02:00
|
|
|
ev = net_buf_add(buf, sizeof(*ev));
|
2015-09-07 18:25:59 +02:00
|
|
|
|
2017-01-17 14:28:01 +02:00
|
|
|
if (IS_ENABLED(CONFIG_BLUETOOTH_BREDR)) {
|
2017-05-05 13:33:48 +02:00
|
|
|
/* Since we require LE support, we can count on a
|
|
|
|
* Bluetooth 4.0 feature set
|
|
|
|
*/
|
2017-04-18 23:02:28 +02:00
|
|
|
mask |= BT_EVT_MASK_INQUIRY_COMPLETE;
|
|
|
|
mask |= BT_EVT_MASK_CONN_COMPLETE;
|
|
|
|
mask |= BT_EVT_MASK_CONN_REQUEST;
|
|
|
|
mask |= BT_EVT_MASK_AUTH_COMPLETE;
|
|
|
|
mask |= BT_EVT_MASK_REMOTE_NAME_REQ_COMPLETE;
|
|
|
|
mask |= BT_EVT_MASK_REMOTE_FEATURES;
|
|
|
|
mask |= BT_EVT_MASK_ROLE_CHANGE;
|
|
|
|
mask |= BT_EVT_MASK_PIN_CODE_REQ;
|
|
|
|
mask |= BT_EVT_MASK_LINK_KEY_REQ;
|
|
|
|
mask |= BT_EVT_MASK_LINK_KEY_NOTIFY;
|
|
|
|
mask |= BT_EVT_MASK_INQUIRY_RESULT_WITH_RSSI;
|
|
|
|
mask |= BT_EVT_MASK_REMOTE_EXT_FEATURES;
|
|
|
|
mask |= BT_EVT_MASK_SYNC_CONN_COMPLETE;
|
|
|
|
mask |= BT_EVT_MASK_EXTENDED_INQUIRY_RESULT;
|
|
|
|
mask |= BT_EVT_MASK_IO_CAPA_REQ;
|
|
|
|
mask |= BT_EVT_MASK_IO_CAPA_RESP;
|
|
|
|
mask |= BT_EVT_MASK_USER_CONFIRM_REQ;
|
|
|
|
mask |= BT_EVT_MASK_USER_PASSKEY_REQ;
|
|
|
|
mask |= BT_EVT_MASK_SSP_COMPLETE;
|
|
|
|
mask |= BT_EVT_MASK_USER_PASSKEY_NOTIFY;
|
|
|
|
}
|
|
|
|
|
|
|
|
mask |= BT_EVT_MASK_HARDWARE_ERROR;
|
|
|
|
mask |= BT_EVT_MASK_DATA_BUFFER_OVERFLOW;
|
|
|
|
mask |= BT_EVT_MASK_LE_META_EVENT;
|
2015-09-07 18:25:59 +02:00
|
|
|
|
2017-01-17 14:28:01 +02:00
|
|
|
if (IS_ENABLED(CONFIG_BLUETOOTH_CONN)) {
|
2017-04-18 23:02:28 +02:00
|
|
|
mask |= BT_EVT_MASK_DISCONN_COMPLETE;
|
|
|
|
mask |= BT_EVT_MASK_REMOTE_VERSION_INFO;
|
2017-01-17 14:28:01 +02:00
|
|
|
}
|
2015-09-07 18:25:59 +02:00
|
|
|
|
2017-01-17 14:28:01 +02:00
|
|
|
if (IS_ENABLED(CONFIG_BLUETOOTH_SMP) &&
|
|
|
|
BT_FEAT_LE_ENCR(bt_dev.le.features)) {
|
2017-04-18 23:02:28 +02:00
|
|
|
mask |= BT_EVT_MASK_ENCRYPT_CHANGE;
|
|
|
|
mask |= BT_EVT_MASK_ENCRYPT_KEY_REFRESH_COMPLETE;
|
2015-04-14 15:44:48 +03:00
|
|
|
}
|
|
|
|
|
2017-04-18 23:02:28 +02:00
|
|
|
sys_put_le64(mask, ev->events);
|
2015-10-30 12:46:08 +01:00
|
|
|
return bt_hci_cmd_send_sync(BT_HCI_OP_SET_EVENT_MASK, buf, NULL);
|
|
|
|
}
|
2015-04-14 15:44:48 +03:00
|
|
|
|
2016-11-30 16:19:48 +00:00
|
|
|
static inline int create_random_addr(bt_addr_le_t *addr)
|
|
|
|
{
|
|
|
|
addr->type = BT_ADDR_LE_RANDOM;
|
|
|
|
|
|
|
|
return bt_rand(addr->a.val, 6);
|
|
|
|
}
|
|
|
|
|
|
|
|
int bt_addr_le_create_nrpa(bt_addr_le_t *addr)
|
|
|
|
{
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = create_random_addr(addr);
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
BT_ADDR_SET_NRPA(&addr->a);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int bt_addr_le_create_static(bt_addr_le_t *addr)
|
|
|
|
{
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = create_random_addr(addr);
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
BT_ADDR_SET_STATIC(&addr->a);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-04-02 09:42:22 +03:00
|
|
|
static int set_static_addr(void)
|
|
|
|
{
|
2016-05-09 11:49:41 +02:00
|
|
|
int err;
|
2016-04-02 09:42:22 +03:00
|
|
|
|
2016-04-05 10:14:32 +03:00
|
|
|
if (bt_storage) {
|
2016-05-09 11:49:41 +02:00
|
|
|
ssize_t ret;
|
|
|
|
|
|
|
|
ret = bt_storage->read(NULL, BT_STORAGE_ID_ADDR,
|
2016-04-05 10:14:32 +03:00
|
|
|
&bt_dev.id_addr, sizeof(bt_dev.id_addr));
|
2016-05-09 11:49:41 +02:00
|
|
|
if (ret == sizeof(bt_dev.id_addr)) {
|
2016-04-02 09:42:22 +03:00
|
|
|
goto set_addr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-30 11:24:48 +01:00
|
|
|
#if defined(CONFIG_SOC_FAMILY_NRF5)
|
|
|
|
/* Read address from nRF5-specific storage
|
|
|
|
* Non-initialized FICR values default to 0xFF, skip if no address
|
|
|
|
* present. Also if a public address lives in FICR, do not use in this
|
|
|
|
* function.
|
|
|
|
*/
|
|
|
|
if (((NRF_FICR->DEVICEADDR[0] != UINT32_MAX) ||
|
|
|
|
((NRF_FICR->DEVICEADDR[1] & UINT16_MAX) != UINT16_MAX)) &&
|
|
|
|
(NRF_FICR->DEVICEADDRTYPE & 0x01)) {
|
|
|
|
|
|
|
|
bt_dev.id_addr.type = BT_ADDR_LE_RANDOM;
|
|
|
|
sys_put_le32(NRF_FICR->DEVICEADDR[0], &bt_dev.id_addr.a.val[0]);
|
|
|
|
sys_put_le16(NRF_FICR->DEVICEADDR[1], &bt_dev.id_addr.a.val[4]);
|
|
|
|
/* The FICR value is a just a random number, with no knowledge
|
|
|
|
* of the Bluetooth Specification requirements for random
|
|
|
|
* static addresses.
|
|
|
|
*/
|
|
|
|
BT_ADDR_SET_STATIC(&bt_dev.id_addr.a);
|
|
|
|
|
|
|
|
goto set_addr;
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_SOC_FAMILY_NRF5 */
|
|
|
|
|
2016-04-02 09:42:22 +03:00
|
|
|
BT_DBG("Generating new static random address");
|
|
|
|
|
2016-11-30 16:19:48 +00:00
|
|
|
err = bt_addr_le_create_static(&bt_dev.id_addr);
|
2016-04-02 09:42:22 +03:00
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2016-04-05 10:14:32 +03:00
|
|
|
if (bt_storage) {
|
2016-05-09 11:49:41 +02:00
|
|
|
ssize_t ret;
|
|
|
|
|
|
|
|
ret = bt_storage->write(NULL, BT_STORAGE_ID_ADDR,
|
2016-04-05 10:14:32 +03:00
|
|
|
&bt_dev.id_addr,
|
|
|
|
sizeof(bt_dev.id_addr));
|
2016-05-09 11:49:41 +02:00
|
|
|
if (ret != sizeof(bt_dev.id_addr)) {
|
2016-04-02 09:42:22 +03:00
|
|
|
BT_ERR("Unable to store static address");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
BT_WARN("Using temporary static random address");
|
|
|
|
}
|
|
|
|
|
|
|
|
set_addr:
|
|
|
|
if (bt_dev.id_addr.type != BT_ADDR_LE_RANDOM ||
|
2016-04-04 13:06:55 +03:00
|
|
|
(bt_dev.id_addr.a.val[5] & 0xc0) != 0xc0) {
|
2016-04-02 09:42:22 +03:00
|
|
|
BT_ERR("Only static random address supported as identity");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2016-05-09 11:48:20 +02:00
|
|
|
err = set_random_address(&bt_dev.id_addr.a);
|
2016-05-09 11:41:14 +02:00
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
atomic_set_bit(bt_dev.flags, BT_DEV_ID_STATIC_RANDOM);
|
|
|
|
return 0;
|
2016-04-02 09:42:22 +03:00
|
|
|
}
|
|
|
|
|
2016-11-04 15:10:34 +02:00
|
|
|
#if defined(CONFIG_BLUETOOTH_DEBUG)
|
2017-04-20 12:00:29 -05:00
|
|
|
static const char *ver_str(u8_t ver)
|
2016-11-04 15:10:34 +02:00
|
|
|
{
|
|
|
|
const char * const str[] = {
|
|
|
|
"1.0b", "1.1", "1.2", "2.0", "2.1", "3.0", "4.0", "4.1", "4.2",
|
2017-03-02 18:11:50 +02:00
|
|
|
"5.0",
|
2016-11-04 15:10:34 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
if (ver < ARRAY_SIZE(str)) {
|
|
|
|
return str[ver];
|
|
|
|
}
|
|
|
|
|
|
|
|
return "unknown";
|
|
|
|
}
|
|
|
|
|
|
|
|
static void show_dev_info(void)
|
|
|
|
{
|
|
|
|
char addr[BT_ADDR_LE_STR_LEN];
|
|
|
|
|
|
|
|
bt_addr_le_to_str(&bt_dev.id_addr, addr, sizeof(addr));
|
|
|
|
|
|
|
|
BT_INFO("Identity: %s", addr);
|
|
|
|
BT_INFO("HCI: version %s (0x%02x) revision 0x%04x, manufacturer 0x%04x",
|
|
|
|
ver_str(bt_dev.hci_version), bt_dev.hci_version,
|
|
|
|
bt_dev.hci_revision, bt_dev.manufacturer);
|
|
|
|
BT_INFO("LMP: version %s (0x%02x) subver 0x%04x",
|
|
|
|
ver_str(bt_dev.lmp_version), bt_dev.lmp_version,
|
|
|
|
bt_dev.lmp_subversion);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
static inline void show_dev_info(void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_BLUETOOTH_DEBUG */
|
|
|
|
|
2015-10-30 12:46:08 +01:00
|
|
|
static int hci_init(void)
|
|
|
|
{
|
2015-11-18 08:02:55 +01:00
|
|
|
int err;
|
2015-10-30 12:46:08 +01:00
|
|
|
|
|
|
|
err = common_init();
|
2015-05-18 12:04:50 +02:00
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
2015-04-14 15:44:48 +03:00
|
|
|
|
2015-10-30 12:46:08 +01:00
|
|
|
err = le_init();
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
2015-04-14 15:44:48 +03:00
|
|
|
|
2016-08-28 16:01:28 +03:00
|
|
|
if (BT_FEAT_BREDR(bt_dev.features)) {
|
2015-11-19 10:45:59 +02:00
|
|
|
err = br_init();
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
2017-01-17 14:28:01 +02:00
|
|
|
} else if (IS_ENABLED(CONFIG_BLUETOOTH_BREDR)) {
|
2016-08-16 14:22:26 +02:00
|
|
|
BT_ERR("Non-BR/EDR controller detected");
|
|
|
|
return -EIO;
|
2015-10-30 12:46:08 +01:00
|
|
|
}
|
2015-04-14 15:44:48 +03:00
|
|
|
|
2015-10-30 12:46:08 +01:00
|
|
|
err = set_event_mask();
|
|
|
|
if (err) {
|
|
|
|
return err;
|
2015-04-14 15:44:48 +03:00
|
|
|
}
|
|
|
|
|
2017-02-01 13:52:14 +02:00
|
|
|
if (!bt_addr_le_cmp(&bt_dev.id_addr, BT_ADDR_LE_ANY) ||
|
|
|
|
!bt_addr_le_cmp(&bt_dev.id_addr, BT_ADDR_LE_NONE)) {
|
2016-04-02 09:42:22 +03:00
|
|
|
BT_DBG("No public address. Trying to set static random.");
|
|
|
|
err = set_static_addr();
|
|
|
|
if (err) {
|
|
|
|
BT_ERR("Unable to set identity address");
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-04 15:10:34 +02:00
|
|
|
show_dev_info();
|
2015-05-12 14:57:38 +03:00
|
|
|
|
2015-04-14 15:41:55 +03:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-04-20 14:46:48 +03:00
|
|
|
int bt_send(struct net_buf *buf)
|
|
|
|
{
|
|
|
|
BT_DBG("buf %p len %u type %u", buf, buf->len, bt_buf_get_type(buf));
|
|
|
|
|
2016-04-20 17:54:07 +03:00
|
|
|
bt_monitor_send(bt_monitor_opcode(buf), buf->data, buf->len);
|
|
|
|
|
2017-03-14 15:00:15 +02:00
|
|
|
if (IS_ENABLED(CONFIG_BLUETOOTH_TINYCRYPT_ECC)) {
|
|
|
|
return bt_hci_ecc_send(buf);
|
|
|
|
}
|
|
|
|
|
2016-04-20 14:46:48 +03:00
|
|
|
return bt_dev.drv->send(buf);
|
|
|
|
}
|
|
|
|
|
2016-12-21 19:00:26 +02:00
|
|
|
int bt_recv(struct net_buf *buf)
|
|
|
|
{
|
|
|
|
bt_monitor_send(bt_monitor_opcode(buf), buf->data, buf->len);
|
|
|
|
|
|
|
|
BT_DBG("buf %p len %u", buf, buf->len);
|
|
|
|
|
|
|
|
if (buf->pool->user_data_size < BT_BUF_USER_DATA_MIN) {
|
|
|
|
BT_ERR("Too small user data size");
|
|
|
|
net_buf_unref(buf);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (bt_buf_get_type(buf)) {
|
2016-12-21 21:09:27 +02:00
|
|
|
#if defined(CONFIG_BLUETOOTH_CONN)
|
2016-12-21 19:00:26 +02:00
|
|
|
case BT_BUF_ACL_IN:
|
2016-12-21 21:09:27 +02:00
|
|
|
#if defined(CONFIG_BLUETOOTH_RECV_IS_RX_THREAD)
|
|
|
|
hci_acl(buf);
|
|
|
|
#else
|
2016-12-21 19:00:26 +02:00
|
|
|
net_buf_put(&bt_dev.rx_queue, buf);
|
2016-12-21 21:09:27 +02:00
|
|
|
#endif
|
2016-12-21 19:00:26 +02:00
|
|
|
return 0;
|
2016-12-21 21:09:27 +02:00
|
|
|
#endif /* BLUETOOTH_CONN */
|
2016-12-21 19:00:26 +02:00
|
|
|
case BT_BUF_EVT:
|
2017-01-02 13:43:12 +02:00
|
|
|
#if defined(CONFIG_BLUETOOTH_RECV_IS_RX_THREAD)
|
|
|
|
hci_event(buf);
|
|
|
|
#else
|
|
|
|
net_buf_put(&bt_dev.rx_queue, buf);
|
|
|
|
#endif
|
2016-12-21 19:00:26 +02:00
|
|
|
return 0;
|
|
|
|
default:
|
|
|
|
BT_ERR("Invalid buf type %u", bt_buf_get_type(buf));
|
|
|
|
net_buf_unref(buf);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
2015-04-14 15:32:32 +03:00
|
|
|
}
|
|
|
|
|
2017-01-02 13:43:12 +02:00
|
|
|
int bt_recv_prio(struct net_buf *buf)
|
|
|
|
{
|
|
|
|
struct bt_hci_evt_hdr *hdr = (void *)buf->data;
|
|
|
|
|
|
|
|
bt_monitor_send(bt_monitor_opcode(buf), buf->data, buf->len);
|
|
|
|
|
|
|
|
BT_ASSERT(bt_buf_get_type(buf) == BT_BUF_EVT);
|
|
|
|
BT_ASSERT(buf->len >= sizeof(*hdr));
|
|
|
|
BT_ASSERT(bt_hci_evt_is_prio(hdr->evt));
|
|
|
|
|
|
|
|
net_buf_pull(buf, sizeof(*hdr));
|
|
|
|
|
|
|
|
switch (hdr->evt) {
|
|
|
|
case BT_HCI_EVT_CMD_COMPLETE:
|
|
|
|
hci_cmd_complete(buf);
|
|
|
|
break;
|
|
|
|
case BT_HCI_EVT_CMD_STATUS:
|
|
|
|
hci_cmd_status(buf);
|
|
|
|
break;
|
|
|
|
#if defined(CONFIG_BLUETOOTH_CONN)
|
|
|
|
case BT_HCI_EVT_NUM_COMPLETED_PACKETS:
|
|
|
|
hci_num_completed_packets(buf);
|
|
|
|
break;
|
|
|
|
#endif /* CONFIG_BLUETOOTH_CONN */
|
|
|
|
default:
|
|
|
|
net_buf_unref(buf);
|
|
|
|
BT_ASSERT(0);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
net_buf_unref(buf);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-03-14 15:00:15 +02:00
|
|
|
int bt_hci_driver_register(const struct bt_hci_driver *drv)
|
2015-04-14 15:32:32 +03:00
|
|
|
{
|
2015-07-15 13:53:17 +03:00
|
|
|
if (bt_dev.drv) {
|
2015-04-14 15:32:32 +03:00
|
|
|
return -EALREADY;
|
2015-05-05 10:50:14 +03:00
|
|
|
}
|
2015-04-14 15:32:32 +03:00
|
|
|
|
2015-10-28 20:24:16 +02:00
|
|
|
if (!drv->open || !drv->send) {
|
2015-04-14 15:32:32 +03:00
|
|
|
return -EINVAL;
|
2015-05-05 10:50:14 +03:00
|
|
|
}
|
2015-04-14 15:32:32 +03:00
|
|
|
|
2015-07-15 13:53:17 +03:00
|
|
|
bt_dev.drv = drv;
|
2015-04-14 15:32:32 +03:00
|
|
|
|
2016-04-22 15:13:09 +03:00
|
|
|
BT_DBG("Registered %s", drv->name ? drv->name : "");
|
|
|
|
|
2016-04-22 14:42:59 +03:00
|
|
|
bt_monitor_new_index(BT_MONITOR_TYPE_PRIMARY, drv->bus,
|
2016-04-22 15:13:09 +03:00
|
|
|
BT_ADDR_ANY, drv->name ? drv->name : "bt0");
|
2016-04-20 17:54:07 +03:00
|
|
|
|
2015-04-14 15:32:32 +03:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-04-04 12:55:11 +03:00
|
|
|
#if defined(CONFIG_BLUETOOTH_PRIVACY)
|
|
|
|
static int irk_init(void)
|
|
|
|
{
|
|
|
|
ssize_t err;
|
|
|
|
|
2016-04-05 10:14:32 +03:00
|
|
|
if (bt_storage) {
|
|
|
|
err = bt_storage->read(NULL, BT_STORAGE_LOCAL_IRK, &bt_dev.irk,
|
|
|
|
sizeof(bt_dev.irk));
|
2016-04-04 12:55:11 +03:00
|
|
|
if (err == sizeof(bt_dev.irk)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BT_DBG("Generating new IRK");
|
|
|
|
|
|
|
|
err = bt_rand(bt_dev.irk, sizeof(bt_dev.irk));
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2016-04-05 10:14:32 +03:00
|
|
|
if (bt_storage) {
|
|
|
|
err = bt_storage->write(NULL, BT_STORAGE_LOCAL_IRK, bt_dev.irk,
|
|
|
|
sizeof(bt_dev.irk));
|
2016-04-04 12:55:11 +03:00
|
|
|
if (err != sizeof(bt_dev.irk)) {
|
|
|
|
BT_ERR("Unable to store IRK");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
BT_WARN("Using temporary IRK");
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_BLUETOOTH_PRIVACY */
|
|
|
|
|
2015-07-28 18:23:19 +03:00
|
|
|
static int bt_init(void)
|
|
|
|
{
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = hci_init();
|
2016-04-21 15:15:54 +02:00
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
2015-09-07 18:25:59 +02:00
|
|
|
|
2017-01-17 14:28:01 +02:00
|
|
|
if (IS_ENABLED(CONFIG_BLUETOOTH_CONN)) {
|
|
|
|
err = bt_conn_init();
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
2015-07-28 18:23:19 +03:00
|
|
|
}
|
|
|
|
|
2016-04-04 12:55:11 +03:00
|
|
|
#if defined(CONFIG_BLUETOOTH_PRIVACY)
|
2016-04-21 15:15:54 +02:00
|
|
|
err = irk_init();
|
|
|
|
if (err) {
|
|
|
|
return err;
|
2016-04-04 12:55:11 +03:00
|
|
|
}
|
2016-07-19 11:55:21 +02:00
|
|
|
|
2016-11-10 14:20:02 +02:00
|
|
|
k_delayed_work_init(&bt_dev.rpa_update, rpa_timeout);
|
2016-04-04 12:55:11 +03:00
|
|
|
#endif
|
|
|
|
|
2016-04-20 17:54:07 +03:00
|
|
|
bt_monitor_send(BT_MONITOR_OPEN_INDEX, NULL, 0);
|
2016-04-21 15:15:54 +02:00
|
|
|
atomic_set_bit(bt_dev.flags, BT_DEV_READY);
|
|
|
|
bt_le_scan_update(false);
|
2015-12-04 10:33:34 +02:00
|
|
|
|
2016-04-21 15:15:54 +02:00
|
|
|
return 0;
|
2015-07-28 18:23:19 +03:00
|
|
|
}
|
|
|
|
|
2016-12-21 21:09:27 +02:00
|
|
|
static void init_work(struct k_work *work)
|
2015-07-28 18:20:50 +03:00
|
|
|
{
|
2016-12-21 21:09:27 +02:00
|
|
|
int err;
|
2015-07-28 18:20:50 +03:00
|
|
|
|
2016-12-21 21:09:27 +02:00
|
|
|
err = bt_init();
|
2015-07-28 18:23:19 +03:00
|
|
|
if (ready_cb) {
|
2016-12-21 21:09:27 +02:00
|
|
|
ready_cb(err);
|
2015-07-28 18:23:19 +03:00
|
|
|
}
|
2016-12-21 21:09:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#if !defined(CONFIG_BLUETOOTH_RECV_IS_RX_THREAD)
|
|
|
|
static void hci_rx_thread(void)
|
|
|
|
{
|
|
|
|
struct net_buf *buf;
|
|
|
|
|
|
|
|
BT_DBG("started");
|
2015-07-28 18:23:19 +03:00
|
|
|
|
2015-07-28 18:20:50 +03:00
|
|
|
while (1) {
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_DBG("calling fifo_get_wait");
|
2016-10-18 23:24:51 +03:00
|
|
|
buf = net_buf_get(&bt_dev.rx_queue, K_FOREVER);
|
2015-07-28 18:20:50 +03:00
|
|
|
|
2016-04-09 11:29:50 +03:00
|
|
|
BT_DBG("buf %p type %u len %u", buf, bt_buf_get_type(buf),
|
|
|
|
buf->len);
|
2015-07-28 18:20:50 +03:00
|
|
|
|
2016-04-09 11:29:50 +03:00
|
|
|
switch (bt_buf_get_type(buf)) {
|
2015-09-07 18:25:59 +02:00
|
|
|
#if defined(CONFIG_BLUETOOTH_CONN)
|
2016-04-09 11:29:50 +03:00
|
|
|
case BT_BUF_ACL_IN:
|
2015-07-28 18:20:50 +03:00
|
|
|
hci_acl(buf);
|
|
|
|
break;
|
2015-09-07 18:25:59 +02:00
|
|
|
#endif /* CONFIG_BLUETOOTH_CONN */
|
2016-04-09 11:29:50 +03:00
|
|
|
case BT_BUF_EVT:
|
2015-07-28 18:20:50 +03:00
|
|
|
hci_event(buf);
|
|
|
|
break;
|
|
|
|
default:
|
2016-04-09 11:29:50 +03:00
|
|
|
BT_ERR("Unknown buf type %u", bt_buf_get_type(buf));
|
2015-10-28 10:34:15 +02:00
|
|
|
net_buf_unref(buf);
|
2015-07-28 18:20:50 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2016-06-07 21:28:07 +03:00
|
|
|
/* Make sure we don't hog the CPU if the rx_queue never
|
|
|
|
* gets empty.
|
|
|
|
*/
|
2016-11-10 21:53:12 +02:00
|
|
|
k_yield();
|
2015-07-28 18:20:50 +03:00
|
|
|
}
|
|
|
|
}
|
2016-12-21 21:09:27 +02:00
|
|
|
#endif /* !CONFIG_BLUETOOTH_RECV_IS_RX_THREAD */
|
2015-07-28 18:20:50 +03:00
|
|
|
|
2015-07-28 20:30:04 +03:00
|
|
|
int bt_enable(bt_ready_cb_t cb)
|
2015-04-14 15:41:55 +03:00
|
|
|
{
|
2016-12-21 21:09:27 +02:00
|
|
|
int err;
|
|
|
|
|
2015-07-28 20:30:04 +03:00
|
|
|
if (!bt_dev.drv) {
|
2015-11-25 14:26:48 +01:00
|
|
|
BT_ERR("No HCI driver registered");
|
2015-07-28 20:30:04 +03:00
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
|
2016-05-30 14:20:42 +02:00
|
|
|
if (atomic_test_and_set_bit(bt_dev.flags, BT_DEV_ENABLE)) {
|
|
|
|
return -EALREADY;
|
|
|
|
}
|
|
|
|
|
2016-12-21 21:09:27 +02:00
|
|
|
ready_cb = cb;
|
|
|
|
|
2016-11-10 22:01:50 +02:00
|
|
|
/* TX thread */
|
2017-05-09 12:00:09 -07:00
|
|
|
k_thread_create(&tx_thread_data, tx_thread_stack,
|
|
|
|
sizeof(tx_thread_stack), hci_tx_thread, NULL, NULL,
|
|
|
|
NULL, K_PRIO_COOP(7), 0, K_NO_WAIT);
|
2015-04-14 15:41:55 +03:00
|
|
|
|
2016-12-21 21:09:27 +02:00
|
|
|
#if !defined(CONFIG_BLUETOOTH_RECV_IS_RX_THREAD)
|
2016-11-10 22:01:50 +02:00
|
|
|
/* RX thread */
|
2017-05-09 12:00:09 -07:00
|
|
|
k_thread_create(&rx_thread_data, rx_thread_stack,
|
|
|
|
sizeof(rx_thread_stack),
|
|
|
|
(k_thread_entry_t)hci_rx_thread, NULL, NULL, NULL,
|
|
|
|
K_PRIO_COOP(7), 0, K_NO_WAIT);
|
2016-12-21 21:09:27 +02:00
|
|
|
#endif
|
|
|
|
|
2017-03-14 15:00:15 +02:00
|
|
|
if (IS_ENABLED(CONFIG_BLUETOOTH_TINYCRYPT_ECC)) {
|
|
|
|
bt_hci_ecc_init();
|
|
|
|
}
|
2016-12-21 21:09:27 +02:00
|
|
|
|
|
|
|
err = bt_dev.drv->open();
|
|
|
|
if (err) {
|
|
|
|
BT_ERR("HCI driver open failed (%d)", err);
|
|
|
|
return err;
|
|
|
|
}
|
2015-09-10 11:25:23 +03:00
|
|
|
|
2015-07-28 18:23:19 +03:00
|
|
|
if (!cb) {
|
|
|
|
return bt_init();
|
2015-07-13 11:10:17 +03:00
|
|
|
}
|
2015-05-21 18:53:13 +03:00
|
|
|
|
2016-12-21 21:09:27 +02:00
|
|
|
k_work_submit(&bt_dev.init);
|
2015-07-28 18:23:19 +03:00
|
|
|
return 0;
|
2015-04-14 14:38:13 +03:00
|
|
|
}
|
2015-04-17 13:59:34 +03:00
|
|
|
|
2016-04-04 13:38:16 +03:00
|
|
|
bool bt_addr_le_is_bonded(const bt_addr_le_t *addr)
|
|
|
|
{
|
2017-01-17 14:28:01 +02:00
|
|
|
if (IS_ENABLED(CONFIG_BLUETOOTH_SMP)) {
|
|
|
|
struct bt_keys *keys = bt_keys_find_addr(addr);
|
2016-04-04 13:38:16 +03:00
|
|
|
|
2017-01-17 14:28:01 +02:00
|
|
|
/* if there are any keys stored then device is bonded */
|
|
|
|
return keys && keys->keys;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
2016-04-04 13:38:16 +03:00
|
|
|
}
|
|
|
|
|
2015-12-05 22:47:23 +02:00
|
|
|
static bool valid_adv_param(const struct bt_le_adv_param *param)
|
|
|
|
{
|
2016-05-02 15:18:28 +02:00
|
|
|
if (!(param->options & BT_LE_ADV_OPT_CONNECTABLE)) {
|
2016-03-22 14:34:33 +01:00
|
|
|
/*
|
|
|
|
* BT Core 4.2 [Vol 2, Part E, 7.8.5]
|
|
|
|
* The Advertising_Interval_Min and Advertising_Interval_Max
|
|
|
|
* shall not be set to less than 0x00A0 (100 ms) if the
|
|
|
|
* Advertising_Type is set to ADV_SCAN_IND or ADV_NONCONN_IND.
|
|
|
|
*/
|
2017-03-03 09:50:51 +02:00
|
|
|
if (bt_dev.hci_version < BT_HCI_VERSION_5_0 &&
|
|
|
|
param->interval_min < 0x00a0) {
|
2016-03-22 14:34:33 +01:00
|
|
|
return false;
|
|
|
|
}
|
2015-12-07 08:11:41 +02:00
|
|
|
}
|
|
|
|
|
2015-12-05 22:47:23 +02:00
|
|
|
if (param->interval_min > param->interval_max ||
|
|
|
|
param->interval_min < 0x0020 || param->interval_max > 0x4000) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-04-20 12:00:29 -05:00
|
|
|
static int set_ad(u16_t hci_op, const struct bt_data *ad, size_t ad_len)
|
2015-04-17 13:59:34 +03:00
|
|
|
{
|
|
|
|
struct bt_hci_cp_le_set_adv_data *set_data;
|
2016-01-14 18:03:08 +02:00
|
|
|
struct net_buf *buf;
|
|
|
|
int i;
|
2015-12-03 12:18:10 +02:00
|
|
|
|
2016-01-14 18:03:08 +02:00
|
|
|
buf = bt_hci_cmd_create(hci_op, sizeof(*set_data));
|
2015-05-05 10:50:14 +03:00
|
|
|
if (!buf) {
|
2015-04-17 13:59:34 +03:00
|
|
|
return -ENOBUFS;
|
2015-05-05 10:50:14 +03:00
|
|
|
}
|
2015-04-17 13:59:34 +03:00
|
|
|
|
2015-10-28 10:34:15 +02:00
|
|
|
set_data = net_buf_add(buf, sizeof(*set_data));
|
2015-04-17 13:59:34 +03:00
|
|
|
|
|
|
|
memset(set_data, 0, sizeof(*set_data));
|
|
|
|
|
2016-01-13 12:53:54 +02:00
|
|
|
for (i = 0; i < ad_len; i++) {
|
2015-04-30 16:07:09 +03:00
|
|
|
/* Check if ad fit in the remaining buffer */
|
2016-01-13 12:53:54 +02:00
|
|
|
if (set_data->len + ad[i].data_len + 2 > 31) {
|
2016-01-14 18:04:45 +02:00
|
|
|
net_buf_unref(buf);
|
|
|
|
return -EINVAL;
|
2015-05-05 10:50:14 +03:00
|
|
|
}
|
2015-04-30 16:07:09 +03:00
|
|
|
|
2016-01-13 12:53:54 +02:00
|
|
|
set_data->data[set_data->len++] = ad[i].data_len + 1;
|
|
|
|
set_data->data[set_data->len++] = ad[i].type;
|
|
|
|
|
|
|
|
memcpy(&set_data->data[set_data->len], ad[i].data,
|
2016-03-21 14:48:40 +01:00
|
|
|
ad[i].data_len);
|
2016-01-13 12:53:54 +02:00
|
|
|
set_data->len += ad[i].data_len;
|
2015-04-30 16:07:09 +03:00
|
|
|
}
|
2015-04-17 13:59:34 +03:00
|
|
|
|
2016-05-09 13:16:58 +03:00
|
|
|
return bt_hci_cmd_send_sync(hci_op, buf, NULL);
|
2016-01-14 18:03:08 +02:00
|
|
|
}
|
2015-04-17 13:59:34 +03:00
|
|
|
|
2016-01-14 18:03:08 +02:00
|
|
|
int bt_le_adv_start(const struct bt_le_adv_param *param,
|
|
|
|
const struct bt_data *ad, size_t ad_len,
|
|
|
|
const struct bt_data *sd, size_t sd_len)
|
|
|
|
{
|
|
|
|
struct net_buf *buf;
|
2016-04-02 09:34:32 +03:00
|
|
|
struct bt_hci_cp_le_set_adv_param *set_param;
|
2016-01-14 18:03:08 +02:00
|
|
|
int err;
|
2015-04-30 16:07:09 +03:00
|
|
|
|
2016-01-14 18:03:08 +02:00
|
|
|
if (!valid_adv_param(param)) {
|
|
|
|
return -EINVAL;
|
2015-05-05 10:50:14 +03:00
|
|
|
}
|
2015-04-17 13:59:34 +03:00
|
|
|
|
2016-08-27 11:11:30 +02:00
|
|
|
if (atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING)) {
|
2016-01-14 18:03:08 +02:00
|
|
|
return -EALREADY;
|
|
|
|
}
|
2015-04-17 13:59:34 +03:00
|
|
|
|
2016-01-14 18:03:08 +02:00
|
|
|
err = set_ad(BT_HCI_OP_LE_SET_ADV_DATA, ad, ad_len);
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
2015-04-17 13:59:34 +03:00
|
|
|
|
2016-05-12 10:13:52 +02:00
|
|
|
/*
|
|
|
|
* We need to set SCAN_RSP when enabling advertising type that allows
|
|
|
|
* for Scan Requests.
|
|
|
|
*
|
|
|
|
* If sd was not provided but we enable connectable undirected
|
|
|
|
* advertising sd needs to be cleared from values set by previous calls.
|
|
|
|
* Clearing sd is done by calling set_ad() with NULL data and zero len.
|
|
|
|
* So following condition check is unusual but correct.
|
2016-01-14 18:03:08 +02:00
|
|
|
*/
|
2016-05-02 15:18:28 +02:00
|
|
|
if (sd || (param->options & BT_LE_ADV_OPT_CONNECTABLE)) {
|
2016-01-14 18:03:08 +02:00
|
|
|
err = set_ad(BT_HCI_OP_LE_SET_SCAN_RSP_DATA, sd, sd_len);
|
|
|
|
if (err) {
|
|
|
|
return err;
|
2015-05-05 10:50:14 +03:00
|
|
|
}
|
2015-04-30 16:07:09 +03:00
|
|
|
}
|
2015-04-17 13:59:34 +03:00
|
|
|
|
2017-04-11 08:39:58 +02:00
|
|
|
buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADV_PARAM,
|
|
|
|
sizeof(*set_param));
|
2015-05-05 10:50:14 +03:00
|
|
|
if (!buf) {
|
2015-04-17 13:59:34 +03:00
|
|
|
return -ENOBUFS;
|
2015-05-05 10:50:14 +03:00
|
|
|
}
|
2015-04-17 13:59:34 +03:00
|
|
|
|
2015-10-28 10:34:15 +02:00
|
|
|
set_param = net_buf_add(buf, sizeof(*set_param));
|
2015-04-17 13:59:34 +03:00
|
|
|
|
|
|
|
memset(set_param, 0, sizeof(*set_param));
|
2015-12-05 21:50:43 +02:00
|
|
|
set_param->min_interval = sys_cpu_to_le16(param->interval_min);
|
|
|
|
set_param->max_interval = sys_cpu_to_le16(param->interval_max);
|
|
|
|
set_param->channel_map = 0x07;
|
2015-04-17 13:59:34 +03:00
|
|
|
|
2016-05-02 15:18:28 +02:00
|
|
|
if (param->options & BT_LE_ADV_OPT_CONNECTABLE) {
|
2017-01-17 14:28:01 +02:00
|
|
|
if (IS_ENABLED(CONFIG_BLUETOOTH_PRIVACY)) {
|
|
|
|
err = le_set_private_addr();
|
|
|
|
if (err) {
|
|
|
|
net_buf_unref(buf);
|
|
|
|
return err;
|
|
|
|
}
|
2015-12-07 08:11:41 +02:00
|
|
|
|
2017-01-17 14:28:01 +02:00
|
|
|
set_param->own_addr_type = BT_ADDR_LE_RANDOM;
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* If Static Random address is used as Identity
|
|
|
|
* address we need to restore it before advertising
|
|
|
|
* is enabled. Otherwise NRPA used for active scan
|
|
|
|
* could be used for advertising.
|
|
|
|
*/
|
|
|
|
if (atomic_test_bit(bt_dev.flags,
|
|
|
|
BT_DEV_ID_STATIC_RANDOM)) {
|
|
|
|
set_random_address(&bt_dev.id_addr.a);
|
|
|
|
}
|
|
|
|
|
|
|
|
set_param->own_addr_type = bt_dev.id_addr.type;
|
2016-07-12 17:35:25 +02:00
|
|
|
}
|
|
|
|
|
2016-05-02 15:18:28 +02:00
|
|
|
set_param->type = BT_LE_ADV_IND;
|
|
|
|
} else {
|
2016-11-27 21:07:11 +02:00
|
|
|
if (param->own_addr) {
|
|
|
|
/* Only NRPA is allowed */
|
|
|
|
if (!BT_ADDR_IS_NRPA(param->own_addr)) {
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
err = set_random_address(param->own_addr);
|
|
|
|
} else {
|
2017-01-17 14:28:01 +02:00
|
|
|
err = le_set_private_addr();
|
2016-11-27 21:07:11 +02:00
|
|
|
}
|
|
|
|
|
2016-04-04 12:55:11 +03:00
|
|
|
if (err) {
|
|
|
|
net_buf_unref(buf);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
set_param->own_addr_type = BT_ADDR_LE_RANDOM;
|
2016-05-02 15:18:28 +02:00
|
|
|
|
|
|
|
if (sd) {
|
|
|
|
set_param->type = BT_LE_ADV_SCAN_IND;
|
|
|
|
} else {
|
|
|
|
set_param->type = BT_LE_ADV_NONCONN_IND;
|
|
|
|
}
|
2015-12-07 08:11:41 +02:00
|
|
|
}
|
|
|
|
|
2016-04-21 15:52:32 +02:00
|
|
|
err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_ADV_PARAM, buf, NULL);
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2016-08-27 11:11:30 +02:00
|
|
|
err = set_advertise_enable(true);
|
2015-07-23 11:35:59 +02:00
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2016-02-17 09:43:04 +01:00
|
|
|
atomic_set_bit(bt_dev.flags, BT_DEV_KEEP_ADVERTISING);
|
2015-07-08 12:17:01 +02:00
|
|
|
|
2015-07-23 11:35:59 +02:00
|
|
|
return 0;
|
2015-07-08 12:17:01 +02:00
|
|
|
}
|
|
|
|
|
2015-12-03 10:19:38 +02:00
|
|
|
int bt_le_adv_stop(void)
|
2015-07-08 12:17:01 +02:00
|
|
|
{
|
2015-07-23 11:35:59 +02:00
|
|
|
int err;
|
2015-07-08 12:17:01 +02:00
|
|
|
|
2016-08-27 11:11:30 +02:00
|
|
|
/* Advertise disable may fail if slave connections are established,
|
|
|
|
* and advertising is not kept ON as the controller does not support
|
|
|
|
* simultaneous slave connections and connectable advertising state.
|
|
|
|
* Hence, we test and clear BT_DEV_KEEP_ADVERTISING flag before trying
|
|
|
|
* to disable advertising if BT_DEV_ADVERTISING is set.
|
|
|
|
*/
|
|
|
|
if (!atomic_test_and_clear_bit(bt_dev.flags, BT_DEV_KEEP_ADVERTISING)) {
|
2015-07-08 12:17:01 +02:00
|
|
|
return -EALREADY;
|
|
|
|
}
|
|
|
|
|
2016-08-27 11:11:30 +02:00
|
|
|
if (!atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
err = set_advertise_enable(false);
|
2015-07-23 11:35:59 +02:00
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2017-01-17 14:28:01 +02:00
|
|
|
if (!IS_ENABLED(CONFIG_BLUETOOTH_PRIVACY)) {
|
|
|
|
/* If active scan is ongoing set NRPA */
|
|
|
|
if (atomic_test_bit(bt_dev.flags, BT_DEV_ACTIVE_SCAN)) {
|
|
|
|
le_set_private_addr();
|
|
|
|
}
|
2016-07-14 15:30:59 +02:00
|
|
|
}
|
2017-01-17 14:28:01 +02:00
|
|
|
|
2015-07-23 11:35:59 +02:00
|
|
|
return 0;
|
2015-04-17 13:59:34 +03:00
|
|
|
}
|
2015-05-08 10:33:34 +02:00
|
|
|
|
2015-12-03 22:39:11 +02:00
|
|
|
static bool valid_le_scan_param(const struct bt_le_scan_param *param)
|
|
|
|
{
|
|
|
|
if (param->type != BT_HCI_LE_SCAN_PASSIVE &&
|
|
|
|
param->type != BT_HCI_LE_SCAN_ACTIVE) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-12-04 13:23:28 +02:00
|
|
|
if (param->filter_dup != BT_HCI_LE_SCAN_FILTER_DUP_DISABLE &&
|
|
|
|
param->filter_dup != BT_HCI_LE_SCAN_FILTER_DUP_ENABLE) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-12-03 22:39:11 +02:00
|
|
|
if (param->interval < 0x0004 || param->interval > 0x4000) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (param->window < 0x0004 || param->window > 0x4000) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (param->window > param->interval) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-12-03 15:17:10 +02:00
|
|
|
int bt_le_scan_start(const struct bt_le_scan_param *param, bt_le_scan_cb_t cb)
|
2015-07-01 18:54:57 +02:00
|
|
|
{
|
2015-12-03 20:05:42 +02:00
|
|
|
int err;
|
|
|
|
|
2015-12-03 22:39:11 +02:00
|
|
|
/* Check that the parameters have valid values */
|
|
|
|
if (!valid_le_scan_param(param)) {
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2015-07-01 18:54:57 +02:00
|
|
|
/* Return if active scan is already enabled */
|
2015-12-03 19:41:42 +02:00
|
|
|
if (atomic_test_and_set_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN)) {
|
2015-07-01 18:54:57 +02:00
|
|
|
return -EALREADY;
|
|
|
|
}
|
|
|
|
|
2015-12-03 20:05:42 +02:00
|
|
|
if (atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING)) {
|
|
|
|
err = bt_hci_stop_scanning();
|
|
|
|
if (err) {
|
|
|
|
atomic_clear_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-03 22:39:11 +02:00
|
|
|
err = start_le_scan(param->type, param->interval, param->window,
|
|
|
|
param->filter_dup);
|
2015-12-03 20:05:42 +02:00
|
|
|
if (err) {
|
|
|
|
atomic_clear_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
scan_dev_found_cb = cb;
|
|
|
|
|
|
|
|
return 0;
|
2015-07-01 18:54:57 +02:00
|
|
|
}
|
|
|
|
|
2015-12-03 10:19:38 +02:00
|
|
|
int bt_le_scan_stop(void)
|
2015-07-01 18:54:57 +02:00
|
|
|
{
|
|
|
|
/* Return if active scanning is already disabled */
|
2015-12-03 19:41:42 +02:00
|
|
|
if (!atomic_test_and_clear_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN)) {
|
2015-07-01 18:54:57 +02:00
|
|
|
return -EALREADY;
|
|
|
|
}
|
|
|
|
|
|
|
|
scan_dev_found_cb = NULL;
|
2015-07-06 12:00:04 +02:00
|
|
|
|
2015-12-03 22:51:16 +02:00
|
|
|
return bt_le_scan_update(false);
|
2015-07-01 18:54:57 +02:00
|
|
|
}
|
2015-10-28 14:59:43 +02:00
|
|
|
|
2017-05-04 11:25:28 +03:00
|
|
|
struct net_buf *bt_buf_get_rx(enum bt_buf_type type, s32_t timeout)
|
2016-12-25 11:20:32 +02:00
|
|
|
{
|
|
|
|
struct net_buf *buf;
|
|
|
|
|
2017-05-04 11:25:28 +03:00
|
|
|
__ASSERT(type == BT_BUF_EVT || type == BT_BUF_ACL_IN,
|
|
|
|
"Invalid buffer type requested");
|
|
|
|
|
2017-05-04 16:09:53 +02:00
|
|
|
#if defined(CONFIG_BLUETOOTH_HCI_ACL_FLOW_CONTROL)
|
2017-05-04 14:09:10 +03:00
|
|
|
if (type == BT_BUF_EVT) {
|
|
|
|
buf = net_buf_alloc(&hci_rx_pool, timeout);
|
|
|
|
} else {
|
|
|
|
buf = net_buf_alloc(&acl_in_pool, timeout);
|
|
|
|
}
|
|
|
|
#else
|
2016-12-25 11:20:32 +02:00
|
|
|
buf = net_buf_alloc(&hci_rx_pool, timeout);
|
2017-05-04 14:09:10 +03:00
|
|
|
#endif
|
|
|
|
|
2016-12-25 11:20:32 +02:00
|
|
|
if (buf) {
|
2017-02-01 12:59:11 +02:00
|
|
|
net_buf_reserve(buf, CONFIG_BLUETOOTH_HCI_RESERVE);
|
2017-05-04 11:25:28 +03:00
|
|
|
bt_buf_set_type(buf, type);
|
2016-12-25 11:20:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
2017-04-20 12:00:29 -05:00
|
|
|
struct net_buf *bt_buf_get_cmd_complete(s32_t timeout)
|
2017-02-01 17:37:14 +02:00
|
|
|
{
|
|
|
|
struct net_buf *buf;
|
|
|
|
unsigned int key;
|
|
|
|
|
|
|
|
key = irq_lock();
|
|
|
|
buf = bt_dev.sent_cmd;
|
|
|
|
bt_dev.sent_cmd = NULL;
|
|
|
|
irq_unlock(key);
|
|
|
|
|
|
|
|
BT_DBG("sent_cmd %p", buf);
|
|
|
|
|
|
|
|
if (buf) {
|
|
|
|
bt_buf_set_type(buf, BT_BUF_EVT);
|
|
|
|
buf->len = 0;
|
|
|
|
net_buf_reserve(buf, CONFIG_BLUETOOTH_HCI_RESERVE);
|
|
|
|
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
2017-05-04 11:25:28 +03:00
|
|
|
return bt_buf_get_rx(BT_BUF_EVT, timeout);
|
2017-02-01 17:37:14 +02:00
|
|
|
}
|
|
|
|
|
2015-11-26 14:47:11 +01:00
|
|
|
#if defined(CONFIG_BLUETOOTH_BREDR)
|
2016-12-19 18:02:41 +01:00
|
|
|
static int br_start_inquiry(const struct bt_br_discovery_param *param)
|
2016-03-10 11:58:56 +01:00
|
|
|
{
|
2017-04-20 12:00:29 -05:00
|
|
|
const u8_t iac[3] = { 0x33, 0x8b, 0x9e };
|
2016-03-10 11:58:56 +01:00
|
|
|
struct bt_hci_op_inquiry *cp;
|
|
|
|
struct net_buf *buf;
|
|
|
|
|
|
|
|
buf = bt_hci_cmd_create(BT_HCI_OP_INQUIRY, sizeof(*cp));
|
|
|
|
if (!buf) {
|
|
|
|
return -ENOBUFS;
|
|
|
|
}
|
|
|
|
|
|
|
|
cp = net_buf_add(buf, sizeof(*cp));
|
|
|
|
|
2016-06-16 10:35:15 +03:00
|
|
|
cp->length = param->length;
|
2016-12-19 18:02:41 +01:00
|
|
|
cp->num_rsp = 0xff; /* we limit discovery only by time */
|
2016-03-10 11:58:56 +01:00
|
|
|
|
|
|
|
memcpy(cp->lap, iac, 3);
|
2016-06-16 11:28:59 +03:00
|
|
|
if (param->limited) {
|
2016-03-10 11:58:56 +01:00
|
|
|
cp->lap[0] = 0x00;
|
|
|
|
}
|
|
|
|
|
|
|
|
return bt_hci_cmd_send_sync(BT_HCI_OP_INQUIRY, buf, NULL);
|
|
|
|
}
|
|
|
|
|
2016-06-16 10:35:15 +03:00
|
|
|
static bool valid_br_discov_param(const struct bt_br_discovery_param *param,
|
|
|
|
size_t num_results)
|
|
|
|
{
|
|
|
|
if (!num_results || num_results > 255) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!param->length || param->length > 0x30) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-03-10 11:58:56 +01:00
|
|
|
int bt_br_discovery_start(const struct bt_br_discovery_param *param,
|
|
|
|
struct bt_br_discovery_result *results, size_t cnt,
|
|
|
|
bt_br_discovery_cb_t cb)
|
|
|
|
{
|
|
|
|
int err;
|
|
|
|
|
|
|
|
BT_DBG("");
|
|
|
|
|
2016-06-16 10:35:15 +03:00
|
|
|
if (!valid_br_discov_param(param, cnt)) {
|
2016-06-16 10:21:15 +03:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2016-03-10 11:58:56 +01:00
|
|
|
if (atomic_test_bit(bt_dev.flags, BT_DEV_INQUIRY)) {
|
|
|
|
return -EALREADY;
|
|
|
|
}
|
|
|
|
|
2016-12-19 18:02:41 +01:00
|
|
|
err = br_start_inquiry(param);
|
2016-03-10 11:58:56 +01:00
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
atomic_set_bit(bt_dev.flags, BT_DEV_INQUIRY);
|
|
|
|
|
|
|
|
memset(results, 0, sizeof(*results) * cnt);
|
|
|
|
|
|
|
|
discovery_cb = cb;
|
|
|
|
discovery_results = results;
|
|
|
|
discovery_results_size = cnt;
|
|
|
|
discovery_results_count = 0;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int bt_br_discovery_stop(void)
|
|
|
|
{
|
|
|
|
int err;
|
2016-03-17 18:35:58 +01:00
|
|
|
int i;
|
2016-03-10 11:58:56 +01:00
|
|
|
|
|
|
|
BT_DBG("");
|
|
|
|
|
|
|
|
if (!atomic_test_bit(bt_dev.flags, BT_DEV_INQUIRY)) {
|
|
|
|
return -EALREADY;
|
|
|
|
}
|
|
|
|
|
|
|
|
err = bt_hci_cmd_send_sync(BT_HCI_OP_INQUIRY_CANCEL, NULL, NULL);
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2016-03-17 18:35:58 +01:00
|
|
|
for (i = 0; i < discovery_results_count; i++) {
|
|
|
|
struct discovery_priv *priv;
|
|
|
|
struct bt_hci_cp_remote_name_cancel *cp;
|
|
|
|
struct net_buf *buf;
|
|
|
|
|
2016-11-08 12:21:46 +02:00
|
|
|
priv = (struct discovery_priv *)&discovery_results[i]._priv;
|
2016-03-17 18:35:58 +01:00
|
|
|
|
|
|
|
if (!priv->resolving) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
buf = bt_hci_cmd_create(BT_HCI_OP_REMOTE_NAME_CANCEL,
|
|
|
|
sizeof(*cp));
|
|
|
|
if (!buf) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
cp = net_buf_add(buf, sizeof(*cp));
|
|
|
|
bt_addr_copy(&cp->bdaddr, &discovery_results[i].addr);
|
|
|
|
|
|
|
|
bt_hci_cmd_send_sync(BT_HCI_OP_REMOTE_NAME_CANCEL, buf, NULL);
|
|
|
|
}
|
|
|
|
|
2016-03-10 11:58:56 +01:00
|
|
|
atomic_clear_bit(bt_dev.flags, BT_DEV_INQUIRY);
|
|
|
|
|
|
|
|
discovery_cb = NULL;
|
|
|
|
discovery_results = NULL;
|
|
|
|
discovery_results_size = 0;
|
|
|
|
discovery_results_count = 0;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-04-20 12:00:29 -05:00
|
|
|
static int write_scan_enable(u8_t scan)
|
2015-11-26 14:47:11 +01:00
|
|
|
{
|
|
|
|
struct net_buf *buf;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
BT_DBG("type %u", scan);
|
|
|
|
|
|
|
|
buf = bt_hci_cmd_create(BT_HCI_OP_WRITE_SCAN_ENABLE, 1);
|
|
|
|
if (!buf) {
|
|
|
|
return -ENOBUFS;
|
|
|
|
}
|
|
|
|
|
2016-02-11 13:49:28 +02:00
|
|
|
net_buf_add_u8(buf, scan);
|
2015-11-26 14:47:11 +01:00
|
|
|
err = bt_hci_cmd_send_sync(BT_HCI_OP_WRITE_SCAN_ENABLE, buf, NULL);
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (scan & BT_BREDR_SCAN_INQUIRY) {
|
|
|
|
atomic_set_bit(bt_dev.flags, BT_DEV_ISCAN);
|
|
|
|
} else {
|
|
|
|
atomic_clear_bit(bt_dev.flags, BT_DEV_ISCAN);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (scan & BT_BREDR_SCAN_PAGE) {
|
|
|
|
atomic_set_bit(bt_dev.flags, BT_DEV_PSCAN);
|
|
|
|
} else {
|
|
|
|
atomic_clear_bit(bt_dev.flags, BT_DEV_PSCAN);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-12-03 10:35:25 +02:00
|
|
|
int bt_br_set_connectable(bool enable)
|
2015-11-26 14:47:11 +01:00
|
|
|
{
|
|
|
|
if (enable) {
|
|
|
|
if (atomic_test_bit(bt_dev.flags, BT_DEV_PSCAN)) {
|
|
|
|
return -EALREADY;
|
|
|
|
} else {
|
2015-12-03 10:35:25 +02:00
|
|
|
return write_scan_enable(BT_BREDR_SCAN_PAGE);
|
2015-11-26 14:47:11 +01:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (!atomic_test_bit(bt_dev.flags, BT_DEV_PSCAN)) {
|
|
|
|
return -EALREADY;
|
|
|
|
} else {
|
2015-12-03 10:35:25 +02:00
|
|
|
return write_scan_enable(BT_BREDR_SCAN_DISABLED);
|
2015-11-26 14:47:11 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-03 10:35:25 +02:00
|
|
|
int bt_br_set_discoverable(bool enable)
|
2015-11-26 14:47:11 +01:00
|
|
|
{
|
|
|
|
if (enable) {
|
|
|
|
if (atomic_test_bit(bt_dev.flags, BT_DEV_ISCAN)) {
|
|
|
|
return -EALREADY;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!atomic_test_bit(bt_dev.flags, BT_DEV_PSCAN)) {
|
|
|
|
return -EPERM;
|
|
|
|
}
|
|
|
|
|
2015-12-03 10:35:25 +02:00
|
|
|
return write_scan_enable(BT_BREDR_SCAN_INQUIRY |
|
|
|
|
BT_BREDR_SCAN_PAGE);
|
2015-11-26 14:47:11 +01:00
|
|
|
} else {
|
|
|
|
if (!atomic_test_bit(bt_dev.flags, BT_DEV_ISCAN)) {
|
|
|
|
return -EALREADY;
|
|
|
|
}
|
|
|
|
|
2015-12-03 10:35:25 +02:00
|
|
|
return write_scan_enable(BT_BREDR_SCAN_PAGE);
|
2015-11-26 14:47:11 +01:00
|
|
|
}
|
|
|
|
}
|
2015-12-16 16:07:21 +01:00
|
|
|
#endif /* CONFIG_BLUETOOTH_BREDR */
|
2016-04-01 21:44:38 +03:00
|
|
|
|
2016-05-30 14:05:28 +02:00
|
|
|
void bt_storage_register(const struct bt_storage *storage)
|
2016-04-01 21:44:38 +03:00
|
|
|
{
|
2016-04-05 10:14:32 +03:00
|
|
|
bt_storage = storage;
|
2016-04-01 21:44:38 +03:00
|
|
|
}
|
2016-04-05 10:33:13 +03:00
|
|
|
|
2017-01-17 14:28:01 +02:00
|
|
|
static int bt_storage_clear_all(void)
|
|
|
|
{
|
|
|
|
if (IS_ENABLED(CONFIG_BLUETOOTH_CONN)) {
|
|
|
|
bt_conn_disconnect_all();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IS_ENABLED(CONFIG_BLUETOOTH_SMP)) {
|
|
|
|
bt_keys_clear_all();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IS_ENABLED(CONFIG_BLUETOOTH_BREDR)) {
|
|
|
|
bt_keys_link_key_clear_addr(NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bt_storage) {
|
|
|
|
return bt_storage->clear(NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-10-04 22:59:28 +03:00
|
|
|
int bt_storage_clear(const bt_addr_le_t *addr)
|
2016-04-05 10:33:13 +03:00
|
|
|
{
|
2017-01-17 14:28:01 +02:00
|
|
|
if (!addr) {
|
|
|
|
return bt_storage_clear_all();
|
|
|
|
}
|
2016-11-04 21:34:05 +02:00
|
|
|
|
2017-01-17 14:28:01 +02:00
|
|
|
if (IS_ENABLED(CONFIG_BLUETOOTH_CONN)) {
|
|
|
|
struct bt_conn *conn = bt_conn_lookup_addr_le(addr);
|
2016-11-04 21:34:05 +02:00
|
|
|
if (conn) {
|
|
|
|
bt_conn_disconnect(conn,
|
|
|
|
BT_HCI_ERR_REMOTE_USER_TERM_CONN);
|
|
|
|
bt_conn_unref(conn);
|
|
|
|
}
|
2017-01-17 14:28:01 +02:00
|
|
|
}
|
2016-11-04 21:34:05 +02:00
|
|
|
|
2017-01-17 14:28:01 +02:00
|
|
|
if (IS_ENABLED(CONFIG_BLUETOOTH_BREDR)) {
|
2016-11-04 21:34:05 +02:00
|
|
|
/* LE Public may indicate BR/EDR as well */
|
|
|
|
if (addr->type == BT_ADDR_LE_PUBLIC) {
|
|
|
|
bt_keys_link_key_clear_addr(&addr->a);
|
|
|
|
}
|
2017-01-17 14:28:01 +02:00
|
|
|
}
|
2016-11-04 21:34:05 +02:00
|
|
|
|
2017-01-17 14:28:01 +02:00
|
|
|
if (IS_ENABLED(CONFIG_BLUETOOTH_SMP)) {
|
|
|
|
struct bt_keys *keys = bt_keys_find_addr(addr);
|
2016-11-04 21:34:05 +02:00
|
|
|
if (keys) {
|
|
|
|
bt_keys_clear(keys);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bt_storage) {
|
2017-01-17 14:28:01 +02:00
|
|
|
return bt_storage->clear(addr);
|
2016-11-04 21:34:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2016-04-05 10:33:13 +03:00
|
|
|
}
|
2016-05-24 17:15:03 +02:00
|
|
|
|
2017-04-20 12:00:29 -05:00
|
|
|
u16_t bt_hci_get_cmd_opcode(struct net_buf *buf)
|
2016-05-24 17:15:03 +02:00
|
|
|
{
|
|
|
|
return cmd(buf)->opcode;
|
|
|
|
}
|
2016-06-30 20:05:36 +03:00
|
|
|
|
|
|
|
int bt_pub_key_gen(struct bt_pub_key_cb *new_cb)
|
|
|
|
{
|
|
|
|
struct bt_pub_key_cb *cb;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We check for both "LE Read Local P-256 Public Key" and
|
|
|
|
* "LE Generate DH Key" support here since both commands are needed for
|
|
|
|
* ECC support. If "LE Generate DH Key" is not supported then there
|
|
|
|
* is no point in reading local public key.
|
|
|
|
*/
|
|
|
|
if (!(bt_dev.supported_commands[34] & 0x02) ||
|
|
|
|
!(bt_dev.supported_commands[34] & 0x04)) {
|
2016-07-22 09:55:37 +03:00
|
|
|
BT_WARN("ECC HCI commands not available");
|
2016-06-30 20:05:36 +03:00
|
|
|
return -ENOTSUP;
|
|
|
|
}
|
|
|
|
|
|
|
|
new_cb->_next = pub_key_cb;
|
|
|
|
pub_key_cb = new_cb;
|
|
|
|
|
2017-01-05 14:46:07 +02:00
|
|
|
if (atomic_test_and_set_bit(bt_dev.flags, BT_DEV_PUB_KEY_BUSY)) {
|
2016-06-30 20:05:36 +03:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-01-05 14:46:07 +02:00
|
|
|
atomic_clear_bit(bt_dev.flags, BT_DEV_HAS_PUB_KEY);
|
|
|
|
|
2016-06-30 20:05:36 +03:00
|
|
|
err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_P256_PUBLIC_KEY, NULL, NULL);
|
|
|
|
if (err) {
|
2017-01-05 14:46:07 +02:00
|
|
|
BT_ERR("Sending LE P256 Public Key command failed");
|
|
|
|
atomic_clear_bit(bt_dev.flags, BT_DEV_PUB_KEY_BUSY);
|
2016-06-30 20:05:36 +03:00
|
|
|
pub_key_cb = NULL;
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (cb = pub_key_cb; cb; cb = cb->_next) {
|
|
|
|
if (cb != new_cb) {
|
|
|
|
cb->func(NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-04-20 12:00:29 -05:00
|
|
|
const u8_t *bt_pub_key_get(void)
|
2016-06-30 20:05:36 +03:00
|
|
|
{
|
|
|
|
if (atomic_test_bit(bt_dev.flags, BT_DEV_HAS_PUB_KEY)) {
|
|
|
|
return pub_key;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2017-04-20 12:00:29 -05:00
|
|
|
int bt_dh_key_gen(const u8_t remote_pk[64], bt_dh_key_cb_t cb)
|
2016-06-30 20:05:36 +03:00
|
|
|
{
|
|
|
|
struct bt_hci_cp_le_generate_dhkey *cp;
|
|
|
|
struct net_buf *buf;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (dh_key_cb || atomic_test_bit(bt_dev.flags, BT_DEV_PUB_KEY_BUSY)) {
|
|
|
|
return -EBUSY;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!atomic_test_bit(bt_dev.flags, BT_DEV_HAS_PUB_KEY)) {
|
|
|
|
return -EADDRNOTAVAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
dh_key_cb = cb;
|
|
|
|
|
|
|
|
buf = bt_hci_cmd_create(BT_HCI_OP_LE_GENERATE_DHKEY, sizeof(*cp));
|
|
|
|
if (!buf) {
|
|
|
|
dh_key_cb = NULL;
|
|
|
|
return -ENOBUFS;
|
|
|
|
}
|
|
|
|
|
|
|
|
cp = net_buf_add(buf, sizeof(*cp));
|
|
|
|
memcpy(cp->key, remote_pk, sizeof(cp->key));
|
|
|
|
|
|
|
|
err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_GENERATE_DHKEY, buf, NULL);
|
|
|
|
if (err) {
|
|
|
|
dh_key_cb = NULL;
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2016-07-20 12:07:46 +02:00
|
|
|
|
|
|
|
#if defined(CONFIG_BLUETOOTH_BREDR)
|
|
|
|
int bt_br_oob_get_local(struct bt_br_oob *oob)
|
|
|
|
{
|
|
|
|
bt_addr_copy(&oob->addr, &bt_dev.id_addr.a);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_BLUETOOTH_BREDR */
|
|
|
|
|
|
|
|
int bt_le_oob_get_local(struct bt_le_oob *oob)
|
|
|
|
{
|
2017-01-17 14:28:01 +02:00
|
|
|
if (IS_ENABLED(CONFIG_BLUETOOTH_PRIVACY)) {
|
|
|
|
int err;
|
2016-07-20 12:07:46 +02:00
|
|
|
|
2017-01-17 14:28:01 +02:00
|
|
|
/* Invalidate RPA so a new one is generated */
|
|
|
|
atomic_clear_bit(bt_dev.flags, BT_DEV_RPA_VALID);
|
2016-07-20 12:07:46 +02:00
|
|
|
|
2017-01-17 14:28:01 +02:00
|
|
|
err = le_set_private_addr();
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
2016-07-20 12:07:46 +02:00
|
|
|
|
2017-01-17 14:28:01 +02:00
|
|
|
bt_addr_le_copy(&oob->addr, &bt_dev.random_addr);
|
|
|
|
} else {
|
|
|
|
bt_addr_le_copy(&oob->addr, &bt_dev.id_addr);
|
|
|
|
}
|
2016-07-20 12:07:46 +02:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|