/* hci_core.c - HCI core Bluetooth handling */ /* * Copyright (c) 2017 Nordic Semiconductor ASA * Copyright (c) 2015-2016 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_CORE) #define LOG_MODULE_NAME bt_hci_core #include "common/log.h" #include "common/rpa.h" #include "keys.h" #include "monitor.h" #include "hci_core.h" #include "hci_ecc.h" #include "ecc.h" #include "conn_internal.h" #include "l2cap_internal.h" #include "gatt_internal.h" #include "smp.h" #include "crypto.h" #include "settings.h" /* Peripheral timeout to initialize Connection Parameter Update procedure */ #define CONN_UPDATE_TIMEOUT K_MSEC(CONFIG_BT_CONN_PARAM_UPDATE_TIMEOUT) #define RPA_TIMEOUT K_SECONDS(CONFIG_BT_RPA_TIMEOUT) #define HCI_CMD_TIMEOUT K_SECONDS(10) /* Stacks for the threads */ #if !defined(CONFIG_BT_RECV_IS_RX_THREAD) static struct k_thread rx_thread_data; static K_THREAD_STACK_DEFINE(rx_thread_stack, CONFIG_BT_RX_STACK_SIZE); #endif static struct k_thread tx_thread_data; static K_THREAD_STACK_DEFINE(tx_thread_stack, CONFIG_BT_HCI_TX_STACK_SIZE); static void init_work(struct k_work *work); struct bt_dev bt_dev = { .init = Z_WORK_INITIALIZER(init_work), /* 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_BT_WAIT_NOP) .ncmd_sem = Z_SEM_INITIALIZER(bt_dev.ncmd_sem, 1, 1), #else .ncmd_sem = Z_SEM_INITIALIZER(bt_dev.ncmd_sem, 0, 1), #endif .cmd_tx_queue = Z_FIFO_INITIALIZER(bt_dev.cmd_tx_queue), #if !defined(CONFIG_BT_RECV_IS_RX_THREAD) .rx_queue = Z_FIFO_INITIALIZER(bt_dev.rx_queue), #endif }; static bt_ready_cb_t ready_cb; static bt_le_scan_cb_t *scan_dev_found_cb; #if defined(CONFIG_BT_OBSERVER) static int set_le_scan_enable(u8_t enable); static sys_slist_t scan_cbs = SYS_SLIST_STATIC_INIT(&scan_cbs); #endif #if defined(CONFIG_BT_HCI_VS_EVT_USER) static bt_hci_vnd_evt_cb_t *hci_vnd_evt_cb; #endif /* CONFIG_BT_HCI_VS_EVT_USER */ #if defined(CONFIG_BT_ECC) static u8_t pub_key[64]; static struct bt_pub_key_cb *pub_key_cb; static bt_dh_key_cb_t dh_key_cb; #endif /* CONFIG_BT_ECC */ #if defined(CONFIG_BT_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_BT_BREDR */ struct cmd_state_set { atomic_t *target; int bit; bool val; }; void cmd_state_set_init(struct cmd_state_set *state, atomic_t *target, int bit, bool val) { state->target = target; state->bit = bit; state->val = val; } struct cmd_data { /** HCI status of the command completion */ u8_t status; /** The command OpCode that the buffer contains */ u16_t opcode; /** The state to update when command completes with success. */ struct cmd_state_set *state; /** Used by bt_hci_cmd_send_sync. */ struct k_sem *sync; }; struct acl_data { /** BT_BUF_ACL_IN */ u8_t type; /* Index into the bt_conn storage array */ u8_t index; /** ACL connection handle */ u16_t handle; }; static struct cmd_data cmd_data[CONFIG_BT_HCI_CMD_COUNT]; #define cmd(buf) (&cmd_data[net_buf_id(buf)]) #define acl(buf) ((struct acl_data *)net_buf_user_data(buf)) /* 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 NET_BUF_POOL_FIXED_DEFINE(hci_cmd_pool, CONFIG_BT_HCI_CMD_COUNT, CMD_BUF_SIZE, NULL); NET_BUF_POOL_FIXED_DEFINE(hci_rx_pool, CONFIG_BT_RX_BUF_COUNT, BT_BUF_RX_SIZE, NULL); #if defined(CONFIG_BT_CONN) #define NUM_COMLETE_EVENT_SIZE BT_BUF_SIZE( \ sizeof(struct bt_hci_evt_hdr) + \ sizeof(struct bt_hci_cp_host_num_completed_packets) + \ CONFIG_BT_MAX_CONN * sizeof(struct bt_hci_handle_count)) /* Dedicated pool for HCI_Number_of_Completed_Packets. This event is always * consumed synchronously by bt_recv_prio() so a single buffer is enough. * Having a dedicated pool for it ensures that exhaustion of the RX pool * cannot block the delivery of this priority event. */ NET_BUF_POOL_FIXED_DEFINE(num_complete_pool, 1, NUM_COMLETE_EVENT_SIZE, NULL); #endif /* CONFIG_BT_CONN */ #if defined(CONFIG_BT_DISCARDABLE_BUF_COUNT) #define DISCARDABLE_EVENT_SIZE BT_BUF_SIZE(CONFIG_BT_DISCARDABLE_BUF_SIZE) NET_BUF_POOL_FIXED_DEFINE(discardable_pool, CONFIG_BT_DISCARDABLE_BUF_COUNT, DISCARDABLE_EVENT_SIZE, NULL); #endif /* CONFIG_BT_DISCARDABLE_BUF_COUNT */ struct event_handler { u8_t event; u8_t min_len; void (*handler)(struct net_buf *buf); }; #define EVENT_HANDLER(_evt, _handler, _min_len) \ { \ .event = _evt, \ .handler = _handler, \ .min_len = _min_len, \ } static inline void handle_event(u8_t event, struct net_buf *buf, const struct event_handler *handlers, size_t num_handlers) { size_t i; for (i = 0; i < num_handlers; i++) { const struct event_handler *handler = &handlers[i]; if (handler->event != event) { continue; } if (buf->len < handler->min_len) { BT_ERR("Too small (%u bytes) event 0x%02x", buf->len, event); return; } handler->handler(buf); return; } BT_WARN("Unhandled event 0x%02x len %u: %s", event, buf->len, bt_hex(buf->data, buf->len)); } #if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL) 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; struct bt_conn *conn; net_buf_destroy(buf); /* Do nothing if controller to host flow control is not supported */ if (!BT_CMD_TEST(bt_dev.supported_commands, 10, 5)) { return; } conn = bt_conn_lookup_index(acl(buf)->index); if (!conn) { BT_WARN("Unable to look up conn with index 0x%02x", acl(buf)->index); return; } if (conn->state != BT_CONN_CONNECTED && conn->state != BT_CONN_DISCONNECT) { BT_WARN("Not reporting packet for non-connected conn"); bt_conn_unref(conn); return; } bt_conn_unref(conn); 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_BT_L2CAP_RX_MTU) NET_BUF_POOL_DEFINE(acl_in_pool, CONFIG_BT_ACL_RX_COUNT, ACL_IN_SIZE, sizeof(struct acl_data), report_completed_packet); #endif /* CONFIG_BT_HCI_ACL_FLOW_CONTROL */ struct net_buf *bt_hci_cmd_create(u16_t opcode, u8_t param_len) { struct bt_hci_cmd_hdr *hdr; struct net_buf *buf; BT_DBG("opcode 0x%04x param_len %u", opcode, param_len); buf = net_buf_alloc(&hci_cmd_pool, K_FOREVER); __ASSERT_NO_MSG(buf); BT_DBG("buf %p", buf); net_buf_reserve(buf, BT_BUF_RESERVE); bt_buf_set_type(buf, BT_BUF_CMD); cmd(buf)->opcode = opcode; cmd(buf)->sync = NULL; cmd(buf)->state = NULL; hdr = net_buf_add(buf, sizeof(*hdr)); hdr->opcode = sys_cpu_to_le16(opcode); hdr->param_len = param_len; return buf; } int bt_hci_cmd_send(u16_t opcode, struct net_buf *buf) { if (!buf) { buf = bt_hci_cmd_create(opcode, 0); if (!buf) { return -ENOBUFS; } } BT_DBG("opcode 0x%04x len %u", opcode, buf->len); /* 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) { int err; err = bt_send(buf); if (err) { BT_ERR("Unable to send to driver (err %d)", err); net_buf_unref(buf); } return err; } net_buf_put(&bt_dev.cmd_tx_queue, buf); return 0; } int bt_hci_cmd_send_sync(u16_t opcode, struct net_buf *buf, struct net_buf **rsp) { struct k_sem sync_sem; int err; if (!buf) { buf = bt_hci_cmd_create(opcode, 0); if (!buf) { return -ENOBUFS; } } BT_DBG("buf %p opcode 0x%04x len %u", buf, opcode, buf->len); k_sem_init(&sync_sem, 0, 1); cmd(buf)->sync = &sync_sem; /* Make sure the buffer stays around until the command completes */ net_buf_ref(buf); net_buf_put(&bt_dev.cmd_tx_queue, buf); err = k_sem_take(&sync_sem, HCI_CMD_TIMEOUT); __ASSERT(err == 0, "k_sem_take failed with err %d", err); BT_DBG("opcode 0x%04x status 0x%02x", opcode, cmd(buf)->status); if (cmd(buf)->status) { switch (cmd(buf)->status) { case BT_HCI_ERR_CONN_LIMIT_EXCEEDED: err = -ECONNREFUSED; break; default: err = -EIO; break; } net_buf_unref(buf); } else { err = 0; if (rsp) { *rsp = buf; } else { net_buf_unref(buf); } } return err; } #if defined(CONFIG_BT_OBSERVER) || defined(CONFIG_BT_CONN) const bt_addr_le_t *bt_lookup_id_addr(u8_t id, const bt_addr_le_t *addr) { if (IS_ENABLED(CONFIG_BT_SMP)) { struct bt_keys *keys; keys = bt_keys_find_irk(id, addr); if (keys) { BT_DBG("Identity %s matched RPA %s", bt_addr_le_str(&keys->addr), bt_addr_le_str(addr)); return &keys->addr; } } return addr; } #endif /* CONFIG_BT_OBSERVER || CONFIG_BT_CONN */ static int set_advertise_enable(bool enable) { struct net_buf *buf; struct cmd_state_set state; int err; buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADV_ENABLE, 1); if (!buf) { return -ENOBUFS; } if (enable) { net_buf_add_u8(buf, BT_HCI_LE_ADV_ENABLE); } else { net_buf_add_u8(buf, BT_HCI_LE_ADV_DISABLE); } cmd_state_set_init(&state, bt_dev.flags, BT_DEV_ADVERTISING, enable); cmd(buf)->state = &state; err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_ADV_ENABLE, buf, NULL); if (err) { return err; } return 0; } static int set_random_address(const bt_addr_t *addr) { struct net_buf *buf; int err; BT_DBG("%s", bt_addr_str(addr)); /* Do nothing if we already have the right address */ if (!bt_addr_cmp(addr, &bt_dev.random_addr.a)) { return 0; } buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_RANDOM_ADDRESS, sizeof(*addr)); if (!buf) { return -ENOBUFS; } net_buf_add_mem(buf, addr, sizeof(*addr)); 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; } int bt_addr_from_str(const char *str, bt_addr_t *addr) { int i, j; u8_t tmp; if (strlen(str) != 17U) { return -EINVAL; } for (i = 5, j = 1; *str != '\0'; str++, j++) { if (!(j % 3) && (*str != ':')) { return -EINVAL; } else if (*str == ':') { i--; continue; } addr->val[i] = addr->val[i] << 4; if (char2hex(*str, &tmp) < 0) { return -EINVAL; } addr->val[i] |= tmp; } return 0; } int bt_addr_le_from_str(const char *str, const char *type, bt_addr_le_t *addr) { int err; err = bt_addr_from_str(str, &addr->a); if (err < 0) { return err; } if (!strcmp(type, "public") || !strcmp(type, "(public)")) { addr->type = BT_ADDR_LE_PUBLIC; } else if (!strcmp(type, "random") || !strcmp(type, "(random)")) { addr->type = BT_ADDR_LE_RANDOM; } else if (!strcmp(type, "public-id") || !strcmp(type, "(public-id)")) { addr->type = BT_ADDR_LE_PUBLIC_ID; } else if (!strcmp(type, "random-id") || !strcmp(type, "(random-id)")) { addr->type = BT_ADDR_LE_RANDOM_ID; } else { return -EINVAL; } return 0; } #if defined(CONFIG_BT_PRIVACY) /* this function sets new RPA only if current one is no longer valid */ static int le_set_private_addr(u8_t id) { bt_addr_t rpa; int err; /* check if RPA is valid */ if (atomic_test_bit(bt_dev.flags, BT_DEV_RPA_VALID)) { return 0; } err = bt_rpa_create(bt_dev.irk[id], &rpa); if (!err) { err = set_random_address(&rpa); if (!err) { atomic_set_bit(bt_dev.flags, BT_DEV_RPA_VALID); } } /* restart timer even if failed to set new RPA */ k_delayed_work_submit(&bt_dev.rpa_update, RPA_TIMEOUT); return err; } #else static int le_set_private_addr(u8_t id) { 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 /* defined(CONFIG_BT_PRIVACY) */ static void le_update_private_addr(void) { bool adv_enabled = false; int err; /* * 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)) { set_advertise_enable(false); adv_enabled = true; } #if defined(CONFIG_BT_OBSERVER) bool scan_enabled = false; if (atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING) && atomic_test_bit(bt_dev.flags, BT_DEV_ACTIVE_SCAN)) { set_le_scan_enable(BT_HCI_LE_SCAN_DISABLE); scan_enabled = true; } #endif if (IS_ENABLED(CONFIG_BT_CENTRAL) && IS_ENABLED(CONFIG_BT_WHITELIST) && atomic_test_bit(bt_dev.flags, BT_DEV_INITIATING)) { /* Canceled initiating procedure will be restarted by * connection complete event. */ bt_le_create_conn_cancel(); } /* If both advertiser and scanner is running then the advertiser ID must * be BT_ID_DEFAULT, this will update the RPA address for both roles. */ err = le_set_private_addr(adv_enabled ? bt_dev.adv_id : BT_ID_DEFAULT); if (err) { BT_WARN("Failed to update RPA address (%d)", err); return; } if (adv_enabled) { set_advertise_enable(true); } #if defined(CONFIG_BT_OBSERVER) if (scan_enabled) { set_le_scan_enable(BT_HCI_LE_SCAN_ENABLE); } #endif } #if defined(CONFIG_BT_PRIVACY) static void rpa_timeout(struct k_work *work) { BT_DBG(""); if (IS_ENABLED(CONFIG_BT_CENTRAL)) { struct bt_conn *conn = bt_conn_lookup_state_le(BT_ID_DEFAULT, NULL, BT_CONN_CONNECT_SCAN); if (conn) { bt_conn_unref(conn); bt_le_create_conn_cancel(); } } /* Invalidate RPA */ atomic_clear_bit(bt_dev.flags, BT_DEV_RPA_VALID); /* IF no roles using the RPA is running we can stop the RPA timer */ if (!((atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING) && !atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING_IDENTITY)) || atomic_test_bit(bt_dev.flags, BT_DEV_INITIATING) || (atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING) && atomic_test_bit(bt_dev.flags, BT_DEV_ACTIVE_SCAN)))) { return; } le_update_private_addr(); } #endif /* defined(CONFIG_BT_PRIVACY) */ bool bt_le_scan_random_addr_check(void) { /* If the advertiser is not enabled or not active there is no issue */ if (!IS_ENABLED(CONFIG_BT_BROADCASTER) || !atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING)) { return true; } /* When privacy is enabled the random address will not be set * immediately before starting the role, because the RPA might still be * valid and only updated on RPA timeout. */ if (IS_ENABLED(CONFIG_BT_PRIVACY)) { /* Cannot start scannor or initiator if the random address is * used by the advertiser for an RPA with a different identity * or for a random static identity address. */ if ((atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING_IDENTITY) && bt_dev.id_addr[bt_dev.adv_id].type == BT_ADDR_LE_RANDOM) || bt_dev.adv_id != BT_ID_DEFAULT) { return false; } } /* If privacy is not enabled then the random address will be attempted * to be set before enabling the role. If another role is already using * the random address then this command will fail, and should return * the error code to the application. */ return true; } static bool bt_le_adv_random_addr_check(const struct bt_le_adv_param *param) { /* If scanner roles are not enabled or not active there is no issue. */ if (!IS_ENABLED(CONFIG_BT_OBSERVER) || !(atomic_test_bit(bt_dev.flags, BT_DEV_INITIATING) || atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING))) { return true; } /* When privacy is enabled the random address will not be set * immediately before starting the role, because the RPA might still be * valid and only updated on RPA timeout. */ if (IS_ENABLED(CONFIG_BT_PRIVACY)) { /* Cannot start an advertiser with random static identity or * using an RPA generated for a different identity than scanner * roles. */ if (((param->options & BT_LE_ADV_OPT_USE_IDENTITY) && bt_dev.id_addr[param->id].type == BT_ADDR_LE_RANDOM) || param->id != BT_ID_DEFAULT) { return false; } } else if (IS_ENABLED(CONFIG_BT_SCAN_WITH_IDENTITY) && atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING) && bt_dev.id_addr[BT_ID_DEFAULT].type == BT_ADDR_LE_RANDOM) { /* Scanning with random static identity. Stop the advertiser * from overwriting the passive scanner identity address. * In this case the LE Set Random Address command does not * protect us in the case of a passive scanner. * Explicitly stop it here. */ if (!(param->options & BT_LE_ADV_OPT_CONNECTABLE) && (param->options & BT_LE_ADV_OPT_USE_IDENTITY)) { /* Attempt to set non-connectable NRPA */ return false; } else if (bt_dev.id_addr[param->id].type == BT_ADDR_LE_RANDOM && param->id != BT_ID_DEFAULT) { /* Attempt to set connectable, or non-connectable with * identity different than scanner. */ return false; } } /* If privacy is not enabled then the random address will be attempted * to be set before enabling the role. If another role is already using * the random address then this command will fail, and should return * the error code to the application. */ return true; } #if defined(CONFIG_BT_OBSERVER) static int set_le_scan_enable(u8_t enable) { struct bt_hci_cp_le_set_scan_enable *cp; struct net_buf *buf; struct cmd_state_set state; int err; buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_SCAN_ENABLE, sizeof(*cp)); if (!buf) { return -ENOBUFS; } cp = net_buf_add(buf, sizeof(*cp)); if (enable == BT_HCI_LE_SCAN_ENABLE) { cp->filter_dup = atomic_test_bit(bt_dev.flags, BT_DEV_SCAN_FILTER_DUP); } else { cp->filter_dup = BT_HCI_LE_SCAN_FILTER_DUP_DISABLE; } cp->enable = enable; cmd_state_set_init(&state, bt_dev.flags, BT_DEV_SCANNING, enable == BT_HCI_LE_SCAN_ENABLE); cmd(buf)->state = &state; err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_SCAN_ENABLE, buf, NULL); if (err) { return err; } return 0; } #endif /* CONFIG_BT_OBSERVER */ #if defined(CONFIG_BT_CONN) static void hci_acl(struct net_buf *buf) { struct bt_hci_acl_hdr *hdr; u16_t handle, len; struct bt_conn *conn; u8_t flags; BT_DBG("buf %p", buf); BT_ASSERT(buf->len >= sizeof(*hdr)); hdr = net_buf_pull_mem(buf, sizeof(*hdr)); len = sys_le16_to_cpu(hdr->len); handle = sys_le16_to_cpu(hdr->handle); flags = bt_acl_flags(handle); acl(buf)->handle = bt_acl_handle(handle); acl(buf)->index = BT_CONN_INDEX_INVALID; BT_DBG("handle %u len %u flags %u", acl(buf)->handle, len, flags); if (buf->len != len) { BT_ERR("ACL data length mismatch (%u != %u)", buf->len, len); net_buf_unref(buf); return; } conn = bt_conn_lookup_handle(acl(buf)->handle); if (!conn) { BT_ERR("Unable to find conn for handle %u", acl(buf)->handle); net_buf_unref(buf); return; } acl(buf)->index = bt_conn_index(conn); bt_conn_recv(conn, buf, flags); bt_conn_unref(conn); } static void hci_data_buf_overflow(struct net_buf *buf) { struct bt_hci_evt_data_buf_overflow *evt = (void *)buf->data; BT_WARN("Data buffer overflow (link type 0x%02x)", evt->link_type); } static void hci_num_completed_packets(struct net_buf *buf) { struct bt_hci_evt_num_completed_packets *evt = (void *)buf->data; int i; BT_DBG("num_handles %u", evt->num_handles); for (i = 0; i < evt->num_handles; i++) { u16_t handle, count; struct bt_conn *conn; unsigned int key; handle = sys_le16_to_cpu(evt->h[i].handle); count = sys_le16_to_cpu(evt->h[i].count); BT_DBG("handle %u count %u", handle, count); key = irq_lock(); conn = bt_conn_lookup_handle(handle); if (!conn) { irq_unlock(key); BT_ERR("No connection for handle %u", handle); continue; } irq_unlock(key); while (count--) { struct bt_conn_tx *tx; sys_snode_t *node; key = irq_lock(); if (conn->pending_no_cb) { conn->pending_no_cb--; irq_unlock(key); k_sem_give(bt_conn_get_pkts(conn)); continue; } node = sys_slist_get(&conn->tx_pending); irq_unlock(key); if (!node) { BT_ERR("packets count mismatch"); break; } tx = CONTAINER_OF(node, struct bt_conn_tx, node); key = irq_lock(); conn->pending_no_cb = tx->pending_no_cb; tx->pending_no_cb = 0U; sys_slist_append(&conn->tx_complete, &tx->node); irq_unlock(key); k_work_submit(&conn->tx_complete_work); k_sem_give(bt_conn_get_pkts(conn)); } bt_conn_unref(conn); } } static inline bool rpa_timeout_valid_check(void) { #if defined(CONFIG_BT_PRIVACY) /* Check if create conn timeout will happen before RPA timeout. */ return k_delayed_work_remaining_get(&bt_dev.rpa_update) > K_SECONDS(CONFIG_BT_CREATE_CONN_TIMEOUT); #else return true; #endif } #if defined(CONFIG_BT_CENTRAL) int bt_le_create_conn(const struct bt_conn *conn) { struct bt_hci_cp_le_create_conn *cp; struct cmd_state_set state; bool use_filter = false; struct net_buf *buf; u8_t own_addr_type; int err; if (IS_ENABLED(CONFIG_BT_WHITELIST)) { use_filter = atomic_test_bit(conn->flags, BT_CONN_AUTO_CONNECT); } if (IS_ENABLED(CONFIG_BT_PRIVACY)) { if (use_filter || rpa_timeout_valid_check()) { err = le_set_private_addr(BT_ID_DEFAULT); if (err) { return err; } } else { /* Force new RPA timeout so that RPA timeout is not * triggered while direct initiator is active. */ atomic_clear_bit(bt_dev.flags, BT_DEV_RPA_VALID); le_update_private_addr(); } if (BT_FEAT_LE_PRIVACY(bt_dev.le.features)) { own_addr_type = BT_HCI_OWN_ADDR_RPA_OR_RANDOM; } else { own_addr_type = BT_ADDR_LE_RANDOM; } } else { const bt_addr_le_t *addr = &bt_dev.id_addr[BT_ID_DEFAULT]; /* 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 (addr->type == BT_ADDR_LE_RANDOM) { err = set_random_address(&addr->a); if (err) { return err; } } own_addr_type = addr->type; } buf = bt_hci_cmd_create(BT_HCI_OP_LE_CREATE_CONN, sizeof(*cp)); if (!buf) { return -ENOBUFS; } cp = net_buf_add(buf, sizeof(*cp)); memset(cp, 0, sizeof(*cp)); cp->own_addr_type = own_addr_type; if (use_filter) { /* User Initiated procedure use fast scan parameters. */ bt_addr_le_copy(&cp->peer_addr, BT_ADDR_LE_ANY); cp->filter_policy = BT_HCI_LE_CREATE_CONN_FP_WHITELIST; cp->scan_interval = sys_cpu_to_le16(BT_GAP_SCAN_FAST_INTERVAL); cp->scan_window = sys_cpu_to_le16(BT_GAP_SCAN_FAST_WINDOW); } else { const bt_addr_le_t *peer_addr = &conn->le.dst; #if defined(CONFIG_BT_SMP) if (!bt_dev.le.rl_size || bt_dev.le.rl_entries > bt_dev.le.rl_size) { /* Host resolving is used, use the RPA directly. */ peer_addr = &conn->le.resp_addr; } #endif bt_addr_le_copy(&cp->peer_addr, peer_addr); cp->filter_policy = BT_HCI_LE_CREATE_CONN_FP_DIRECT; /* Interval == window for continuous scanning */ cp->scan_interval = sys_cpu_to_le16(BT_GAP_SCAN_FAST_INTERVAL); cp->scan_window = cp->scan_interval; } cp->conn_interval_min = sys_cpu_to_le16(conn->le.interval_min); cp->conn_interval_max = sys_cpu_to_le16(conn->le.interval_max); cp->conn_latency = sys_cpu_to_le16(conn->le.latency); cp->supervision_timeout = sys_cpu_to_le16(conn->le.timeout); cmd_state_set_init(&state, bt_dev.flags, BT_DEV_INITIATING, true); cmd(buf)->state = &state; return bt_hci_cmd_send_sync(BT_HCI_OP_LE_CREATE_CONN, buf, NULL); } int bt_le_create_conn_cancel(void) { struct net_buf *buf; struct cmd_state_set state; buf = bt_hci_cmd_create(BT_HCI_OP_LE_CREATE_CONN_CANCEL, 0); cmd_state_set_init(&state, bt_dev.flags, BT_DEV_INITIATING, false); cmd(buf)->state = &state; return bt_hci_cmd_send_sync(BT_HCI_OP_LE_CREATE_CONN_CANCEL, buf, NULL); } #endif /* CONFIG_BT_CENTRAL */ int bt_hci_disconnect(u16_t handle, u8_t reason) { struct net_buf *buf; struct bt_hci_cp_disconnect *disconn; buf = bt_hci_cmd_create(BT_HCI_OP_DISCONNECT, sizeof(*disconn)); if (!buf) { return -ENOBUFS; } disconn = net_buf_add(buf, sizeof(*disconn)); disconn->handle = sys_cpu_to_le16(handle); disconn->reason = reason; return bt_hci_cmd_send(BT_HCI_OP_DISCONNECT, buf); } static void hci_disconn_complete(struct net_buf *buf) { struct bt_hci_evt_disconn_complete *evt = (void *)buf->data; u16_t handle = sys_le16_to_cpu(evt->handle); struct bt_conn *conn; BT_DBG("status 0x%02x handle %u reason 0x%02x", evt->status, handle, evt->reason); if (evt->status) { return; } conn = bt_conn_lookup_handle(handle); if (!conn) { BT_ERR("Unable to look up conn with handle %u", handle); goto advertise; } conn->err = evt->reason; /* Check stacks usage */ #if !defined(CONFIG_BT_RECV_IS_RX_THREAD) log_stack_usage(&rx_thread_data); #endif log_stack_usage(&tx_thread_data); bt_conn_set_state(conn, BT_CONN_DISCONNECTED); conn->handle = 0U; if (conn->type != BT_CONN_TYPE_LE) { #if defined(CONFIG_BT_BREDR) if (conn->type == BT_CONN_TYPE_SCO) { bt_sco_cleanup(conn); return; } /* * 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)) { bt_keys_link_key_clear(conn->br.link_key); } #endif bt_conn_unref(conn); return; } #if defined(CONFIG_BT_CENTRAL) && !defined(CONFIG_BT_WHITELIST) if (atomic_test_bit(conn->flags, BT_CONN_AUTO_CONNECT)) { bt_conn_set_state(conn, BT_CONN_CONNECT_SCAN); bt_le_scan_update(false); } #endif /* defined(CONFIG_BT_CENTRAL) && !defined(CONFIG_BT_WHITELIST) */ bt_conn_unref(conn); advertise: if (IS_ENABLED(CONFIG_BT_PERIPHERAL) && atomic_test_bit(bt_dev.flags, BT_DEV_KEEP_ADVERTISING) && !atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING)) { bt_le_adv_resume(); } } static int hci_le_read_remote_features(struct bt_conn *conn) { struct bt_hci_cp_le_read_remote_features *cp; struct net_buf *buf; buf = bt_hci_cmd_create(BT_HCI_OP_LE_READ_REMOTE_FEATURES, sizeof(*cp)); if (!buf) { return -ENOBUFS; } cp = net_buf_add(buf, sizeof(*cp)); cp->handle = sys_cpu_to_le16(conn->handle); bt_hci_cmd_send(BT_HCI_OP_LE_READ_REMOTE_FEATURES, buf); return 0; } static int hci_read_remote_version(struct bt_conn *conn) { struct bt_hci_cp_read_remote_version_info *cp; struct net_buf *buf; if (conn->state != BT_CONN_CONNECTED) { return -ENOTCONN; } /* Remote version cannot change. */ if (atomic_test_bit(conn->flags, BT_CONN_AUTO_VERSION_INFO)) { return 0; } buf = bt_hci_cmd_create(BT_HCI_OP_READ_REMOTE_VERSION_INFO, sizeof(*cp)); if (!buf) { return -ENOBUFS; } cp = net_buf_add(buf, sizeof(*cp)); cp->handle = sys_cpu_to_le16(conn->handle); return bt_hci_cmd_send_sync(BT_HCI_OP_READ_REMOTE_VERSION_INFO, buf, NULL); } /* LE Data Length Change Event is optional so this function just ignore * error and stack will continue to use default values. */ static void 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) { BT_ERR("Failed to read DLE max data len"); return; } 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) { BT_ERR("Failed to create LE Set Data Length Command"); return; } 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) { BT_ERR("Failed to send LE Set Data Length Command"); } } 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 = 0U; 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; } static void slave_update_conn_param(struct bt_conn *conn) { if (!IS_ENABLED(CONFIG_BT_PERIPHERAL)) { return; } /* don't start timer again on PHY update etc */ if (atomic_test_bit(conn->flags, BT_CONN_SLAVE_PARAM_UPDATE)) { return; } /* * Core 4.2 Vol 3, Part C, 9.3.12.2 * The Peripheral device should not perform a Connection Parameter * Update procedure within 5 s after establishing a connection. */ k_delayed_work_submit(&conn->update_work, CONN_UPDATE_TIMEOUT); } #if defined(CONFIG_BT_SMP) static void update_pending_id(struct bt_keys *keys, void *data) { if (keys->flags & BT_KEYS_ID_PENDING_ADD) { keys->flags &= ~BT_KEYS_ID_PENDING_ADD; bt_id_add(keys); return; } if (keys->flags & BT_KEYS_ID_PENDING_DEL) { keys->flags &= ~BT_KEYS_ID_PENDING_DEL; bt_id_del(keys); return; } } #endif static struct bt_conn *find_pending_connect(u8_t role, bt_addr_le_t *peer_addr) { struct bt_conn *conn; /* * Make lookup to check if there's a connection object in * CONNECT or DIR_ADV state associated with passed peer LE address. */ if (IS_ENABLED(CONFIG_BT_CENTRAL) && role == BT_HCI_ROLE_MASTER) { conn = bt_conn_lookup_state_le(BT_ID_DEFAULT, peer_addr, BT_CONN_CONNECT); if (IS_ENABLED(CONFIG_BT_WHITELIST) && !conn) { conn = bt_conn_lookup_state_le(BT_ID_DEFAULT, BT_ADDR_LE_NONE, BT_CONN_CONNECT_AUTO); } return conn; } if (IS_ENABLED(CONFIG_BT_PERIPHERAL) && role == BT_HCI_ROLE_SLAVE) { conn = bt_conn_lookup_state_le(bt_dev.adv_id, peer_addr, BT_CONN_CONNECT_DIR_ADV); if (!conn) { conn = bt_conn_lookup_state_le(bt_dev.adv_id, BT_ADDR_LE_NONE, BT_CONN_CONNECT_ADV); } return conn; } return NULL; } static void conn_auto_initiate(struct bt_conn *conn) { int err; if (conn->state != BT_CONN_CONNECTED) { /* It is possible that connection was disconnected directly from * connected callback so we must check state before doing * connection parameters update. */ return; } if (!atomic_test_bit(conn->flags, BT_CONN_AUTO_FEATURE_EXCH) && ((conn->role == BT_HCI_ROLE_MASTER) || BT_FEAT_LE_SLAVE_FEATURE_XCHG(bt_dev.le.features))) { err = hci_le_read_remote_features(conn); if (!err) { return; } } if (IS_ENABLED(CONFIG_BT_REMOTE_VERSION) && !atomic_test_bit(conn->flags, BT_CONN_AUTO_VERSION_INFO)) { err = hci_read_remote_version(conn); if (!err) { return; } } if (IS_ENABLED(CONFIG_BT_AUTO_PHY_UPDATE) && !atomic_test_bit(conn->flags, BT_CONN_AUTO_PHY_COMPLETE) && BT_FEAT_LE_PHY_2M(bt_dev.le.features)) { err = hci_le_set_phy(conn); if (!err) { atomic_set_bit(conn->flags, BT_CONN_AUTO_PHY_UPDATE); return; } } if (IS_ENABLED(CONFIG_BT_DATA_LEN_UPDATE) && BT_FEAT_LE_DLE(bt_dev.le.features)) { hci_le_set_data_len(conn); } if (IS_ENABLED(CONFIG_BT_PERIPHERAL) && conn->role == BT_CONN_ROLE_SLAVE) { slave_update_conn_param(conn); } } static void le_conn_cancel_complete(struct bt_conn *conn) { /* Handle cancellation of outgoing connection attempt. */ if (!IS_ENABLED(CONFIG_BT_WHITELIST)) { /* We notify before checking autoconnect flag * as application may choose to change it from * callback. */ bt_conn_set_state(conn, BT_CONN_DISCONNECTED); /* Check if device is marked for autoconnect. */ if (atomic_test_bit(conn->flags, BT_CONN_AUTO_CONNECT)) { /* Restart passive scanner for device */ bt_conn_set_state(conn, BT_CONN_CONNECT_SCAN); } } else { if (atomic_test_bit(conn->flags, BT_CONN_AUTO_CONNECT)) { /* Restart whitelist initiator after RPA timeout. */ bt_le_create_conn(conn); } else { /* Create connection canceled by timeout */ bt_conn_set_state(conn, BT_CONN_DISCONNECTED); } } } static void enh_conn_complete(struct bt_hci_evt_le_enh_conn_complete *evt) { u16_t handle = sys_le16_to_cpu(evt->handle); bt_addr_le_t peer_addr, id_addr; struct bt_conn *conn; BT_DBG("status 0x%02x handle %u role %u %s", evt->status, handle, evt->role, bt_addr_le_str(&evt->peer_addr)); #if defined(CONFIG_BT_SMP) if (atomic_test_and_clear_bit(bt_dev.flags, BT_DEV_ID_PENDING)) { bt_keys_foreach(BT_KEYS_IRK, update_pending_id, NULL); } #endif if (evt->status) { /* * Here we are only interested in pending connection. */ if (IS_ENABLED(CONFIG_BT_PERIPHERAL) && evt->status == BT_HCI_ERR_ADV_TIMEOUT) { /* * Handle advertising timeout after high duty cycle * directed advertising. */ atomic_clear_bit(bt_dev.flags, BT_DEV_ADVERTISING); /* * There is no need to check ID address as only one * connection in slave role can be in pending state. */ conn = find_pending_connect(BT_HCI_ROLE_SLAVE, NULL); if (!conn) { BT_ERR("No pending slave connection"); return; } conn->err = evt->status; bt_conn_set_state(conn, BT_CONN_DISCONNECTED); goto done; } if (IS_ENABLED(CONFIG_BT_CENTRAL) && evt->status == BT_HCI_ERR_UNKNOWN_CONN_ID) { /* * Handle create connection cancel. * * There is no need to check ID address as only one * connection in master role can be in pending state. */ conn = find_pending_connect(BT_HCI_ROLE_MASTER, NULL); if (!conn) { BT_ERR("No pending master connection"); return; } conn->err = evt->status; le_conn_cancel_complete(conn); goto done; } BT_WARN("Unexpected status 0x%02x", evt->status); return; } /* Translate "enhanced" identity address type to normal one */ if (evt->peer_addr.type == BT_ADDR_LE_PUBLIC_ID || evt->peer_addr.type == BT_ADDR_LE_RANDOM_ID) { bt_addr_le_copy(&id_addr, &evt->peer_addr); id_addr.type -= BT_ADDR_LE_PUBLIC_ID; bt_addr_copy(&peer_addr.a, &evt->peer_rpa); peer_addr.type = BT_ADDR_LE_RANDOM; } else { u8_t id = evt->role == BT_HCI_ROLE_SLAVE ? bt_dev.adv_id : BT_ID_DEFAULT; bt_addr_le_copy(&id_addr, bt_lookup_id_addr(id, &evt->peer_addr)); bt_addr_le_copy(&peer_addr, &evt->peer_addr); } conn = find_pending_connect(evt->role, &id_addr); if (IS_ENABLED(CONFIG_BT_PERIPHERAL) && evt->role == BT_HCI_ROLE_SLAVE) { /* Clear advertising even if we are not able to add connection * object to keep host in sync with controller state */ atomic_clear_bit(bt_dev.flags, BT_DEV_ADVERTISING); } if (IS_ENABLED(CONFIG_BT_CENTRAL) && evt->role == BT_HCI_ROLE_MASTER) { /* Clear initiating even if we are not able to add connection * object to keep the host in sync with controller state. */ atomic_clear_bit(bt_dev.flags, BT_DEV_INITIATING); } if (!conn) { BT_ERR("Unable to add new conn for handle %u", handle); bt_hci_disconnect(handle, BT_HCI_ERR_MEM_CAPACITY_EXCEEDED); return; } conn->handle = handle; bt_addr_le_copy(&conn->le.dst, &id_addr); 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); conn->role = evt->role; conn->err = 0U; /* * 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. */ if (IS_ENABLED(CONFIG_BT_PERIPHERAL) && conn->role == BT_HCI_ROLE_SLAVE) { bt_addr_le_copy(&conn->le.init_addr, &peer_addr); if (IS_ENABLED(CONFIG_BT_PRIVACY) && bt_addr_cmp(&evt->local_rpa, BT_ADDR_ANY) != 0) { bt_addr_copy(&conn->le.resp_addr.a, &evt->local_rpa); conn->le.resp_addr.type = BT_ADDR_LE_RANDOM; } else { bt_addr_le_copy(&conn->le.resp_addr, &bt_dev.id_addr[conn->id]); } /* 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)) { bt_le_adv_resume(); } } if (IS_ENABLED(CONFIG_BT_CENTRAL) && conn->role == BT_HCI_ROLE_MASTER) { bt_addr_le_copy(&conn->le.resp_addr, &peer_addr); if (IS_ENABLED(CONFIG_BT_PRIVACY) && bt_addr_cmp(&evt->local_rpa, BT_ADDR_ANY) != 0) { bt_addr_copy(&conn->le.init_addr.a, &evt->local_rpa); conn->le.init_addr.type = BT_ADDR_LE_RANDOM; } else { bt_addr_le_copy(&conn->le.init_addr, &bt_dev.id_addr[conn->id]); } } bt_conn_set_state(conn, BT_CONN_CONNECTED); /* Start auto-initiated procedures */ conn_auto_initiate(conn); done: bt_conn_unref(conn); if (IS_ENABLED(CONFIG_BT_CENTRAL)) { bt_le_scan_update(false); } } static void le_enh_conn_complete(struct net_buf *buf) { enh_conn_complete((void *)buf->data); } static void le_legacy_conn_complete(struct net_buf *buf) { struct bt_hci_evt_le_conn_complete *evt = (void *)buf->data; struct bt_hci_evt_le_enh_conn_complete enh; BT_DBG("status 0x%02x role %u %s", evt->status, evt->role, bt_addr_le_str(&evt->peer_addr)); enh.status = evt->status; enh.handle = evt->handle; enh.role = evt->role; enh.interval = evt->interval; enh.latency = evt->latency; enh.supv_timeout = evt->supv_timeout; enh.clock_accuracy = evt->clock_accuracy; bt_addr_le_copy(&enh.peer_addr, &evt->peer_addr); if (IS_ENABLED(CONFIG_BT_PRIVACY)) { bt_addr_copy(&enh.local_rpa, &bt_dev.random_addr.a); } else { bt_addr_copy(&enh.local_rpa, BT_ADDR_ANY); } bt_addr_copy(&enh.peer_rpa, BT_ADDR_ANY); enh_conn_complete(&enh); } static void le_remote_feat_complete(struct net_buf *buf) { struct bt_hci_evt_le_remote_feat_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; } if (!evt->status) { memcpy(conn->le.features, evt->features, sizeof(conn->le.features)); } atomic_set_bit(conn->flags, BT_CONN_AUTO_FEATURE_EXCH); if (IS_ENABLED(CONFIG_BT_REMOTE_INFO) && !IS_ENABLED(CONFIG_BT_REMOTE_VERSION)) { notify_remote_info(conn); } /* Continue with auto-initiated procedures */ conn_auto_initiate(conn); bt_conn_unref(conn); } #if defined(CONFIG_BT_DATA_LEN_UPDATE) 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); /* TODO use those */ bt_conn_unref(conn); } #endif /* CONFIG_BT_DATA_LEN_UPDATE */ #if defined(CONFIG_BT_PHY_UPDATE) 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; } BT_DBG("PHY updated: status: 0x%02x, tx: %u, rx: %u", evt->status, evt->tx_phy, evt->rx_phy); if (!IS_ENABLED(CONFIG_BT_AUTO_PHY_UPDATE) || !atomic_test_and_clear_bit(conn->flags, BT_CONN_AUTO_PHY_UPDATE)) { goto done; } atomic_set_bit(conn->flags, BT_CONN_AUTO_PHY_COMPLETE); /* Continue with auto-initiated procedures */ conn_auto_initiate(conn); done: bt_conn_unref(conn); } #endif /* CONFIG_BT_PHY_UPDATE */ bool bt_le_conn_params_valid(const struct bt_le_conn_param *param) { /* All limits according to BT Core spec 5.0 [Vol 2, Part E, 7.8.12] */ if (param->interval_min > param->interval_max || param->interval_min < 6 || param->interval_max > 3200) { return false; } if (param->latency > 499) { return false; } if (param->timeout < 10 || param->timeout > 3200 || ((param->timeout * 4U) <= ((1 + param->latency) * param->interval_max))) { return false; } return true; } static void le_conn_param_neg_reply(u16_t handle, u8_t reason) { struct bt_hci_cp_le_conn_param_req_neg_reply *cp; struct net_buf *buf; buf = bt_hci_cmd_create(BT_HCI_OP_LE_CONN_PARAM_REQ_NEG_REPLY, sizeof(*cp)); if (!buf) { BT_ERR("Unable to allocate buffer"); return; } cp = net_buf_add(buf, sizeof(*cp)); cp->handle = sys_cpu_to_le16(handle); cp->reason = sys_cpu_to_le16(reason); bt_hci_cmd_send(BT_HCI_OP_LE_CONN_PARAM_REQ_NEG_REPLY, buf); } static int le_conn_param_req_reply(u16_t handle, const struct bt_le_conn_param *param) { struct bt_hci_cp_le_conn_param_req_reply *cp; struct net_buf *buf; buf = bt_hci_cmd_create(BT_HCI_OP_LE_CONN_PARAM_REQ_REPLY, sizeof(*cp)); if (!buf) { return -ENOBUFS; } cp = net_buf_add(buf, sizeof(*cp)); (void)memset(cp, 0, sizeof(*cp)); cp->handle = sys_cpu_to_le16(handle); 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); return bt_hci_cmd_send(BT_HCI_OP_LE_CONN_PARAM_REQ_REPLY, buf); } static void le_conn_param_req(struct net_buf *buf) { struct bt_hci_evt_le_conn_param_req *evt = (void *)buf->data; struct bt_le_conn_param param; struct bt_conn *conn; u16_t handle; handle = sys_le16_to_cpu(evt->handle); 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); conn = bt_conn_lookup_handle(handle); if (!conn) { BT_ERR("Unable to lookup conn for handle %u", handle); le_conn_param_neg_reply(handle, BT_HCI_ERR_UNKNOWN_CONN_ID); return; } if (!le_param_req(conn, ¶m)) { le_conn_param_neg_reply(handle, BT_HCI_ERR_INVALID_LL_PARAM); } else { le_conn_param_req_reply(handle, ¶m); } bt_conn_unref(conn); } static void le_conn_update_complete(struct net_buf *buf) { struct bt_hci_evt_le_conn_update_complete *evt = (void *)buf->data; struct bt_conn *conn; u16_t handle; handle = sys_le16_to_cpu(evt->handle); BT_DBG("status 0x%02x, handle %u", evt->status, handle); conn = bt_conn_lookup_handle(handle); if (!conn) { BT_ERR("Unable to lookup conn for handle %u", handle); return; } if (!evt->status) { conn->le.interval = 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); } else if (evt->status == BT_HCI_ERR_UNSUPP_REMOTE_FEATURE && conn->role == BT_HCI_ROLE_SLAVE && !atomic_test_and_set_bit(conn->flags, BT_CONN_SLAVE_PARAM_L2CAP)) { /* CPR not supported, let's try L2CAP CPUP instead */ struct bt_le_conn_param param; param.interval_min = conn->le.interval_min; param.interval_max = conn->le.interval_max; param.latency = conn->le.pending_latency; param.timeout = conn->le.pending_timeout; bt_l2cap_update_conn_param(conn, ¶m); } bt_conn_unref(conn); } #if defined(CONFIG_BT_CENTRAL) static void check_pending_conn(const bt_addr_le_t *id_addr, const bt_addr_le_t *addr, u8_t evtype) { struct bt_conn *conn; /* No connections are allowed during explicit scanning */ if (atomic_test_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN)) { return; } /* Return if event is not connectable */ if (evtype != BT_LE_ADV_IND && evtype != BT_LE_ADV_DIRECT_IND) { return; } conn = bt_conn_lookup_state_le(BT_ID_DEFAULT, id_addr, BT_CONN_CONNECT_SCAN); if (!conn) { return; } if (atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING) && set_le_scan_enable(BT_HCI_LE_SCAN_DISABLE)) { goto failed; } bt_addr_le_copy(&conn->le.resp_addr, addr); if (bt_le_create_conn(conn)) { goto failed; } bt_conn_set_state(conn, BT_CONN_CONNECT); bt_conn_unref(conn); return; failed: conn->err = BT_HCI_ERR_UNSPECIFIED; bt_conn_set_state(conn, BT_CONN_DISCONNECTED); bt_conn_unref(conn); bt_le_scan_update(false); } #endif /* CONFIG_BT_CENTRAL */ #if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL) 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_CMD_TEST(bt_dev.supported_commands, 10, 5)) { 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)); (void)memset(hbs, 0, sizeof(*hbs)); hbs->acl_mtu = sys_cpu_to_le16(CONFIG_BT_L2CAP_RX_MTU + sizeof(struct bt_l2cap_hdr)); hbs->acl_pkts = sys_cpu_to_le16(CONFIG_BT_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); } #endif /* CONFIG_BT_HCI_ACL_FLOW_CONTROL */ static void unpair(u8_t id, const bt_addr_le_t *addr) { struct bt_keys *keys = NULL; struct bt_conn *conn = bt_conn_lookup_addr_le(id, addr); if (conn) { /* Clear the conn->le.keys pointer since we'll invalidate it, * and don't want any subsequent code (like disconnected * callbacks) accessing it. */ if (conn->type == BT_CONN_TYPE_LE) { keys = conn->le.keys; conn->le.keys = NULL; } bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); bt_conn_unref(conn); } if (IS_ENABLED(CONFIG_BT_BREDR)) { /* LE Public may indicate BR/EDR as well */ if (addr->type == BT_ADDR_LE_PUBLIC) { bt_keys_link_key_clear_addr(&addr->a); } } if (IS_ENABLED(CONFIG_BT_SMP)) { if (!keys) { keys = bt_keys_find_addr(id, addr); } if (keys) { bt_keys_clear(keys); } } bt_gatt_clear(id, addr); } static void unpair_remote(const struct bt_bond_info *info, void *data) { u8_t *id = (u8_t *) data; unpair(*id, &info->addr); } int bt_unpair(u8_t id, const bt_addr_le_t *addr) { if (id >= CONFIG_BT_ID_MAX) { return -EINVAL; } if (!addr || !bt_addr_le_cmp(addr, BT_ADDR_LE_ANY)) { bt_foreach_bond(id, unpair_remote, &id); return 0; } unpair(id, addr); return 0; } #endif /* CONFIG_BT_CONN */ #if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR) static enum bt_security_err security_err_get(u8_t hci_err) { switch (hci_err) { case BT_HCI_ERR_SUCCESS: return BT_SECURITY_ERR_SUCCESS; case BT_HCI_ERR_AUTH_FAIL: return BT_SECURITY_ERR_AUTH_FAIL; case BT_HCI_ERR_PIN_OR_KEY_MISSING: return BT_SECURITY_ERR_PIN_OR_KEY_MISSING; case BT_HCI_ERR_PAIRING_NOT_SUPPORTED: return BT_SECURITY_ERR_PAIR_NOT_SUPPORTED; case BT_HCI_ERR_PAIRING_NOT_ALLOWED: return BT_SECURITY_ERR_PAIR_NOT_ALLOWED; case BT_HCI_ERR_INVALID_PARAM: return BT_SECURITY_ERR_INVALID_PARAM; default: return BT_SECURITY_ERR_UNSPECIFIED; } } static void reset_pairing(struct bt_conn *conn) { #if defined(CONFIG_BT_BREDR) if (conn->type == BT_CONN_TYPE_BR) { 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); } #endif /* CONFIG_BT_BREDR */ /* Reset required security level to current operational */ conn->required_sec_level = conn->sec_level; } #endif /* defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR) */ #if defined(CONFIG_BT_BREDR) static int reject_conn(const bt_addr_t *bdaddr, u8_t reason) { 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; } 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; } 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; } 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; } 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; } sco_conn->role = BT_HCI_ROLE_SLAVE; bt_conn_set_state(sco_conn, BT_CONN_CONNECT); bt_conn_unref(sco_conn); } 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) { bt_esco_conn_req(evt); 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); } static bool br_sufficient_key_size(struct bt_conn *conn) { struct bt_hci_cp_read_encryption_key_size *cp; struct bt_hci_rp_read_encryption_key_size *rp; struct net_buf *buf, *rsp; u8_t key_size; int err; buf = bt_hci_cmd_create(BT_HCI_OP_READ_ENCRYPTION_KEY_SIZE, sizeof(*cp)); if (!buf) { BT_ERR("Failed to allocate command buffer"); return false; } cp = net_buf_add(buf, sizeof(*cp)); cp->handle = sys_cpu_to_le16(conn->handle); err = bt_hci_cmd_send_sync(BT_HCI_OP_READ_ENCRYPTION_KEY_SIZE, buf, &rsp); if (err) { BT_ERR("Failed to read encryption key size (err %d)", err); return false; } if (rsp->len < sizeof(*rp)) { BT_ERR("Too small command complete for encryption key size"); net_buf_unref(rsp); return false; } rp = (void *)rsp->data; key_size = rp->key_size; net_buf_unref(rsp); BT_DBG("Encryption key size is %u", key_size); if (conn->sec_level == BT_SECURITY_L4) { return key_size == BT_HCI_ENCRYPTION_KEY_SIZE_MAX; } return key_size >= BT_HCI_ENCRYPTION_KEY_SIZE_MIN; } static bool update_sec_level_br(struct bt_conn *conn) { if (!conn->encrypt) { conn->sec_level = BT_SECURITY_L1; return true; } if (conn->br.link_key) { if (conn->br.link_key->flags & BT_LINK_KEY_AUTHENTICATED) { if (conn->encrypt == 0x02) { conn->sec_level = BT_SECURITY_L4; } else { conn->sec_level = BT_SECURITY_L3; } } else { conn->sec_level = BT_SECURITY_L2; } } else { BT_WARN("No BR/EDR link key found"); conn->sec_level = BT_SECURITY_L2; } if (!br_sufficient_key_size(conn)) { BT_ERR("Encryption key size is not sufficient"); bt_conn_disconnect(conn, BT_HCI_ERR_AUTH_FAIL); return false; } if (conn->required_sec_level > conn->sec_level) { BT_ERR("Failed to set required security level"); bt_conn_disconnect(conn, BT_HCI_ERR_AUTH_FAIL); return false; } return true; } 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; u16_t handle = sys_le16_to_cpu(evt->handle); 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); } static void conn_complete(struct net_buf *buf) { struct bt_hci_evt_conn_complete *evt = (void *)buf->data; struct bt_conn *conn; struct bt_hci_cp_read_remote_features *cp; u16_t handle = sys_le16_to_cpu(evt->handle); 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; conn->err = 0U; conn->encrypt = evt->encr_enabled; if (!update_sec_level_br(conn)) { bt_conn_unref(conn); return; } bt_conn_set_state(conn, BT_CONN_CONNECTED); bt_conn_unref(conn); 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); } 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) { struct bt_hci_evt_link_key_notify *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_DBG("%s, link type 0x%02x", bt_addr_str(&evt->bdaddr), evt->key_type); if (!conn->br.link_key) { conn->br.link_key = bt_keys_get_link_key(&evt->bdaddr); } if (!conn->br.link_key) { BT_ERR("Can't update keys for %s", bt_addr_str(&evt->bdaddr)); bt_conn_unref(conn); return; } /* clear any old Link Key flags */ conn->br.link_key->flags = 0U; switch (evt->key_type) { case BT_LK_COMBINATION: /* * 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)) { conn->br.link_key->flags |= BT_LINK_KEY_AUTHENTICATED; } memcpy(conn->br.link_key->val, evt->link_key, 16); break; case BT_LK_AUTH_COMBINATION_P192: 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) { atomic_set_bit(conn->flags, BT_CONN_BR_NOBOND); } memcpy(conn->br.link_key->val, evt->link_key, 16); break; case BT_LK_AUTH_COMBINATION_P256: conn->br.link_key->flags |= BT_LINK_KEY_AUTHENTICATED; /* fall through */ case BT_LK_UNAUTH_COMBINATION_P256: 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); } memcpy(conn->br.link_key->val, evt->link_key, 16); break; default: BT_WARN("Unsupported Link Key type %u", evt->key_type); (void)memset(conn->br.link_key->val, 0, sizeof(conn->br.link_key->val)); break; } 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); } static void link_key_reply(const bt_addr_t *bdaddr, const u8_t *lk) { 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; struct bt_conn *conn; BT_DBG("%s", bt_addr_str(&evt->bdaddr)); conn = bt_conn_lookup_addr_br(&evt->bdaddr); if (!conn) { BT_ERR("Can't find conn for %s", bt_addr_str(&evt->bdaddr)); link_key_neg_reply(&evt->bdaddr); return; } if (!conn->br.link_key) { conn->br.link_key = bt_keys_find_link_key(&evt->bdaddr); } if (!conn->br.link_key) { link_key_neg_reply(&evt->bdaddr); bt_conn_unref(conn); return; } /* * Enforce regenerate by controller stronger link key since found one * in database not covers requested security level. */ if (!(conn->br.link_key->flags & BT_LINK_KEY_AUTHENTICATED) && conn->required_sec_level > BT_SECURITY_L2) { link_key_neg_reply(&evt->bdaddr); bt_conn_unref(conn); return; } link_key_reply(&evt->bdaddr, conn->br.link_key->val); bt_conn_unref(conn); } static void io_capa_neg_reply(const bt_addr_t *bdaddr, const u8_t reason) { 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); } 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); if (evt->authentication > BT_HCI_GENERAL_BONDING_MITM) { BT_ERR("Invalid remote authentication requirements"); io_capa_neg_reply(&evt->bdaddr, BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL); return; } if (evt->capability > BT_IO_NO_INPUT_OUTPUT) { BT_ERR("Invalid remote io capability requirements"); io_capa_neg_reply(&evt->bdaddr, BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL); return; } 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; atomic_set_bit(conn->flags, BT_CONN_BR_PAIRING); bt_conn_unref(conn); } 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; struct bt_conn *conn; struct bt_hci_cp_io_capability_reply *cp; u8_t auth; 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; } resp_buf = bt_hci_cmd_create(BT_HCI_OP_IO_CAPABILITY_REPLY, sizeof(*cp)); if (!resp_buf) { BT_ERR("Out of command buffers"); bt_conn_unref(conn); return; } /* * 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); } cp = net_buf_add(resp_buf, sizeof(*cp)); bt_addr_copy(&cp->bdaddr, &evt->bdaddr); cp->capability = bt_conn_get_io_capa(); cp->authentication = auth; cp->oob_data = 0U; bt_hci_cmd_send_sync(BT_HCI_OP_IO_CAPABILITY_REPLY, resp_buf, NULL); bt_conn_unref(conn); } 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 0x%02x", 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; } bt_conn_ssp_auth_complete(conn, security_err_get(evt->status)); if (evt->status) { bt_conn_disconnect(conn, BT_HCI_ERR_AUTH_FAIL); } bt_conn_unref(conn); } 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); } 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); } 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); } struct discovery_priv { u16_t clock_offset; u8_t pscan_rep_mode; u8_t resolving; } __packed; static int request_name(const bt_addr_t *addr, u8_t pscan, u16_t offset) { 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 static bool eir_has_name(const u8_t *eir) { 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; } static void report_discovery_results(void) { bool resolving_names = false; int i; for (i = 0; i < discovery_results_count; i++) { struct discovery_priv *priv; priv = (struct discovery_priv *)&discovery_results[i]._priv; 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 = 1U; resolving_names = true; } if (resolving_names) { return; } 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; } 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"); } report_discovery_results(); } static struct bt_br_discovery_result *get_result_slot(const bt_addr_t *addr, s8_t rssi) { struct bt_br_discovery_result *result = NULL; 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]; } } /* Pick a new slot (if available) */ if (discovery_results_count < discovery_results_size) { bt_addr_copy(&discovery_results[discovery_results_count].addr, addr); return &discovery_results[discovery_results_count++]; } /* ignore if invalid RSSI */ if (rssi == 0xff) { return NULL; } /* * 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; } 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; } static void inquiry_result_with_rssi(struct net_buf *buf) { u8_t num_reports = net_buf_pull_u8(buf); if (!atomic_test_bit(bt_dev.flags, BT_DEV_INQUIRY)) { return; } BT_DBG("number of results: %u", num_reports); while (num_reports--) { struct bt_hci_evt_inquiry_result_with_rssi *evt; struct bt_br_discovery_result *result; struct discovery_priv *priv; if (buf->len < sizeof(*evt)) { BT_ERR("Unexpected end to buffer"); return; } evt = net_buf_pull_mem(buf, sizeof(*evt)); BT_DBG("%s rssi %d dBm", bt_addr_str(&evt->addr), evt->rssi); result = get_result_slot(&evt->addr, evt->rssi); if (!result) { return; } priv = (struct discovery_priv *)&result->_priv; priv->pscan_rep_mode = evt->pscan_rep_mode; priv->clock_offset = evt->clock_offset; memcpy(result->cod, evt->cod, 3); result->rssi = evt->rssi; /* we could reuse slot so make sure EIR is cleared */ (void)memset(result->eir, 0, sizeof(result->eir)); } } 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; struct discovery_priv *priv; if (!atomic_test_bit(bt_dev.flags, BT_DEV_INQUIRY)) { return; } BT_DBG("%s rssi %d dBm", bt_addr_str(&evt->addr), evt->rssi); result = get_result_slot(&evt->addr, evt->rssi); if (!result) { return; } priv = (struct discovery_priv *)&result->_priv; priv->pscan_rep_mode = evt->pscan_rep_mode; priv->clock_offset = evt->clock_offset; result->rssi = evt->rssi; memcpy(result->cod, evt->cod, 3); memcpy(result->eir, evt->eir, sizeof(result->eir)); } static void remote_name_request_complete(struct net_buf *buf) { 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; u8_t *eir; int i; result = get_result_slot(&evt->bdaddr, 0xff); if (!result) { return; } priv = (struct discovery_priv *)&result->_priv; priv->resolving = 0U; 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 */ name_len = strlen((const char *)evt->name); 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; priv = (struct discovery_priv *)&discovery_results[i]._priv; 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; } static void link_encr(const u16_t handle) { 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); } static void auth_complete(struct net_buf *buf) { struct bt_hci_evt_auth_complete *evt = (void *)buf->data; struct bt_conn *conn; u16_t handle = sys_le16_to_cpu(evt->handle); BT_DBG("status 0x%02x, 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) { 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); } reset_pairing(conn); } else { link_encr(handle); } bt_conn_unref(conn); } static void read_remote_features_complete(struct net_buf *buf) { struct bt_hci_evt_remote_features *evt = (void *)buf->data; u16_t handle = sys_le16_to_cpu(evt->handle); struct bt_hci_cp_read_remote_ext_features *cp; struct bt_conn *conn; BT_DBG("status 0x%02x 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) { goto done; } memcpy(conn->br.features[0], evt->features, sizeof(evt->features)); if (!BT_FEAT_EXT_FEATURES(conn->br.features)) { goto done; } buf = bt_hci_cmd_create(BT_HCI_OP_READ_REMOTE_EXT_FEATURES, sizeof(*cp)); if (!buf) { goto done; } /* 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); 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; u16_t handle = sys_le16_to_cpu(evt->handle); struct bt_conn *conn; BT_DBG("status 0x%02x 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); } 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 0x%02x 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); } #endif /* CONFIG_BT_BREDR */ #if defined(CONFIG_BT_SMP) static int le_set_privacy_mode(const bt_addr_le_t *addr, u8_t mode) { struct bt_hci_cp_le_set_privacy_mode cp; struct net_buf *buf; int err; /* Check if set privacy mode command is supported */ if (!BT_CMD_TEST(bt_dev.supported_commands, 39, 2)) { BT_WARN("Set privacy mode command is not supported"); return 0; } BT_DBG("addr %s mode 0x%02x", bt_addr_le_str(addr), mode); bt_addr_le_copy(&cp.id_addr, addr); cp.mode = mode; buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_PRIVACY_MODE, sizeof(cp)); if (!buf) { return -ENOBUFS; } net_buf_add_mem(buf, &cp, sizeof(cp)); err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_PRIVACY_MODE, buf, NULL); if (err) { return err; } return 0; } static int addr_res_enable(u8_t enable) { struct net_buf *buf; BT_DBG("%s", enable ? "enabled" : "disabled"); buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADDR_RES_ENABLE, 1); if (!buf) { return -ENOBUFS; } net_buf_add_u8(buf, enable); return bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_ADDR_RES_ENABLE, buf, NULL); } static int hci_id_add(const bt_addr_le_t *addr, u8_t val[16]) { struct bt_hci_cp_le_add_dev_to_rl *cp; struct net_buf *buf; BT_DBG("addr %s", bt_addr_le_str(addr)); buf = bt_hci_cmd_create(BT_HCI_OP_LE_ADD_DEV_TO_RL, sizeof(*cp)); if (!buf) { return -ENOBUFS; } cp = net_buf_add(buf, sizeof(*cp)); bt_addr_le_copy(&cp->peer_id_addr, addr); memcpy(cp->peer_irk, val, 16); #if defined(CONFIG_BT_PRIVACY) memcpy(cp->local_irk, bt_dev.irk, 16); #else (void)memset(cp->local_irk, 0, 16); #endif return bt_hci_cmd_send_sync(BT_HCI_OP_LE_ADD_DEV_TO_RL, buf, NULL); } void bt_id_add(struct bt_keys *keys) { bool adv_enabled; #if defined(CONFIG_BT_OBSERVER) bool scan_enabled; #endif /* CONFIG_BT_OBSERVER */ struct bt_conn *conn; int err; BT_DBG("addr %s", bt_addr_le_str(&keys->addr)); /* Nothing to be done if host-side resolving is used */ if (!bt_dev.le.rl_size || bt_dev.le.rl_entries > bt_dev.le.rl_size) { bt_dev.le.rl_entries++; return; } conn = bt_conn_lookup_state_le(BT_ID_DEFAULT, NULL, BT_CONN_CONNECT); if (conn) { atomic_set_bit(bt_dev.flags, BT_DEV_ID_PENDING); keys->flags |= BT_KEYS_ID_PENDING_ADD; bt_conn_unref(conn); return; } adv_enabled = atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING); if (adv_enabled) { set_advertise_enable(false); } #if defined(CONFIG_BT_OBSERVER) scan_enabled = atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING); if (scan_enabled) { set_le_scan_enable(BT_HCI_LE_SCAN_DISABLE); } #endif /* CONFIG_BT_OBSERVER */ /* If there are any existing entries address resolution will be on */ if (bt_dev.le.rl_entries) { err = addr_res_enable(BT_HCI_ADDR_RES_DISABLE); if (err) { BT_WARN("Failed to disable address resolution"); goto done; } } if (bt_dev.le.rl_entries == bt_dev.le.rl_size) { BT_WARN("Resolving list size exceeded. Switching to host."); err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_CLEAR_RL, NULL, NULL); if (err) { BT_ERR("Failed to clear resolution list"); goto done; } bt_dev.le.rl_entries++; goto done; } err = hci_id_add(&keys->addr, keys->irk.val); if (err) { BT_ERR("Failed to add IRK to controller"); goto done; } bt_dev.le.rl_entries++; /* * According to Core Spec. 5.0 Vol 1, Part A 5.4.5 Privacy Feature * * By default, network privacy mode is used when private addresses are * resolved and generated by the Controller, so advertising packets from * peer devices that contain private addresses will only be accepted. * By changing to the device privacy mode device is only concerned about * its privacy and will accept advertising packets from peer devices * that contain their identity address as well as ones that contain * a private address, even if the peer device has distributed its IRK in * the past. */ err = le_set_privacy_mode(&keys->addr, BT_HCI_LE_PRIVACY_MODE_DEVICE); if (err) { BT_ERR("Failed to set privacy mode"); goto done; } done: addr_res_enable(BT_HCI_ADDR_RES_ENABLE); #if defined(CONFIG_BT_OBSERVER) if (scan_enabled) { set_le_scan_enable(BT_HCI_LE_SCAN_ENABLE); } #endif /* CONFIG_BT_OBSERVER */ if (adv_enabled) { set_advertise_enable(true); } } static void keys_add_id(struct bt_keys *keys, void *data) { hci_id_add(&keys->addr, keys->irk.val); } void bt_id_del(struct bt_keys *keys) { struct bt_hci_cp_le_rem_dev_from_rl *cp; bool adv_enabled; #if defined(CONFIG_BT_OBSERVER) bool scan_enabled; #endif /* CONFIG_BT_OBSERVER */ struct bt_conn *conn; struct net_buf *buf; int err; BT_DBG("addr %s", bt_addr_le_str(&keys->addr)); if (!bt_dev.le.rl_size || bt_dev.le.rl_entries > bt_dev.le.rl_size + 1) { bt_dev.le.rl_entries--; return; } conn = bt_conn_lookup_state_le(BT_ID_DEFAULT, NULL, BT_CONN_CONNECT); if (conn) { atomic_set_bit(bt_dev.flags, BT_DEV_ID_PENDING); keys->flags |= BT_KEYS_ID_PENDING_DEL; bt_conn_unref(conn); return; } adv_enabled = atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING); if (adv_enabled) { set_advertise_enable(false); } #if defined(CONFIG_BT_OBSERVER) scan_enabled = atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING); if (scan_enabled) { set_le_scan_enable(BT_HCI_LE_SCAN_DISABLE); } #endif /* CONFIG_BT_OBSERVER */ err = addr_res_enable(BT_HCI_ADDR_RES_DISABLE); if (err) { BT_ERR("Disabling address resolution failed (err %d)", err); goto done; } /* We checked size + 1 earlier, so here we know we can fit again */ if (bt_dev.le.rl_entries > bt_dev.le.rl_size) { bt_dev.le.rl_entries--; keys->keys &= ~BT_KEYS_IRK; bt_keys_foreach(BT_KEYS_IRK, keys_add_id, NULL); goto done; } buf = bt_hci_cmd_create(BT_HCI_OP_LE_REM_DEV_FROM_RL, sizeof(*cp)); if (!buf) { goto done; } cp = net_buf_add(buf, sizeof(*cp)); bt_addr_le_copy(&cp->peer_id_addr, &keys->addr); err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_REM_DEV_FROM_RL, buf, NULL); if (err) { BT_ERR("Failed to remove IRK from controller"); goto done; } bt_dev.le.rl_entries--; done: /* Only re-enable if there are entries to do resolving with */ if (bt_dev.le.rl_entries) { addr_res_enable(BT_HCI_ADDR_RES_ENABLE); } #if defined(CONFIG_BT_OBSERVER) if (scan_enabled) { set_le_scan_enable(BT_HCI_LE_SCAN_ENABLE); } #endif /* CONFIG_BT_OBSERVER */ if (adv_enabled) { set_advertise_enable(true); } } static void update_sec_level(struct bt_conn *conn) { if (!conn->encrypt) { conn->sec_level = BT_SECURITY_L1; return; } if (conn->le.keys && (conn->le.keys->flags & BT_KEYS_AUTHENTICATED)) { if (conn->le.keys->flags & BT_KEYS_SC && conn->le.keys->enc_size == BT_SMP_MAX_ENC_KEY_SIZE) { conn->sec_level = BT_SECURITY_L4; } else { conn->sec_level = BT_SECURITY_L3; } } else { conn->sec_level = BT_SECURITY_L2; } if (conn->required_sec_level > conn->sec_level) { BT_ERR("Failed to set required security level"); bt_conn_disconnect(conn, BT_HCI_ERR_AUTH_FAIL); } } #endif /* CONFIG_BT_SMP */ #if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR) static void hci_encrypt_change(struct net_buf *buf) { struct bt_hci_evt_encrypt_change *evt = (void *)buf->data; u16_t handle = sys_le16_to_cpu(evt->handle); struct bt_conn *conn; BT_DBG("status 0x%02x handle %u encrypt 0x%02x", evt->status, handle, evt->encrypt); conn = bt_conn_lookup_handle(handle); if (!conn) { BT_ERR("Unable to look up conn with handle %u", handle); return; } if (evt->status) { reset_pairing(conn); bt_l2cap_encrypt_change(conn, evt->status); bt_conn_security_changed(conn, security_err_get(evt->status)); bt_conn_unref(conn); return; } conn->encrypt = evt->encrypt; #if defined(CONFIG_BT_SMP) if (conn->type == BT_CONN_TYPE_LE) { /* * 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); } update_sec_level(conn); } #endif /* CONFIG_BT_SMP */ #if defined(CONFIG_BT_BREDR) if (conn->type == BT_CONN_TYPE_BR) { if (!update_sec_level_br(conn)) { bt_conn_unref(conn); return; } if (IS_ENABLED(CONFIG_BT_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); } } } #endif /* CONFIG_BT_BREDR */ reset_pairing(conn); bt_l2cap_encrypt_change(conn, evt->status); bt_conn_security_changed(conn, BT_SECURITY_ERR_SUCCESS); bt_conn_unref(conn); } static void hci_encrypt_key_refresh_complete(struct net_buf *buf) { struct bt_hci_evt_encrypt_key_refresh_complete *evt = (void *)buf->data; struct bt_conn *conn; u16_t handle; handle = sys_le16_to_cpu(evt->handle); BT_DBG("status 0x%02x handle %u", evt->status, handle); conn = bt_conn_lookup_handle(handle); if (!conn) { BT_ERR("Unable to look up conn with handle %u", handle); return; } if (evt->status) { reset_pairing(conn); bt_l2cap_encrypt_change(conn, evt->status); bt_conn_security_changed(conn, security_err_get(evt->status)); bt_conn_unref(conn); return; } /* * Update keys with last pairing info for proper sec level update. * 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. */ #if defined(CONFIG_BT_SMP) if (conn->type == BT_CONN_TYPE_LE) { bt_smp_update_keys(conn); update_sec_level(conn); } #endif /* CONFIG_BT_SMP */ #if defined(CONFIG_BT_BREDR) if (conn->type == BT_CONN_TYPE_BR) { if (!update_sec_level_br(conn)) { bt_conn_unref(conn); return; } } #endif /* CONFIG_BT_BREDR */ reset_pairing(conn); bt_l2cap_encrypt_change(conn, evt->status); bt_conn_security_changed(conn, BT_SECURITY_ERR_SUCCESS); bt_conn_unref(conn); } #endif /* CONFIG_BT_SMP || CONFIG_BT_BREDR */ #if defined(CONFIG_BT_REMOTE_VERSION) static void bt_hci_evt_read_remote_version_complete(struct net_buf *buf) { struct bt_hci_evt_remote_version_info *evt; struct bt_conn *conn; evt = net_buf_pull_mem(buf, sizeof(*evt)); conn = bt_conn_lookup_handle(evt->handle); if (!conn) { BT_ERR("No connection for handle %u", evt->handle); return; } if (!evt->status) { conn->rv.version = evt->version; conn->rv.manufacturer = sys_le16_to_cpu(evt->manufacturer); conn->rv.subversion = sys_le16_to_cpu(evt->subversion); } atomic_set_bit(conn->flags, BT_CONN_AUTO_VERSION_INFO); if (IS_ENABLED(CONFIG_BT_REMOTE_INFO)) { /* Remote features is already present */ notify_remote_info(conn); } /* Continue with auto-initiated procedures */ conn_auto_initiate(conn); bt_conn_unref(conn); } #endif /* CONFIG_BT_REMOTE_VERSION */ #if defined(CONFIG_BT_SMP) static void le_ltk_neg_reply(u16_t handle) { struct bt_hci_cp_le_ltk_req_neg_reply *cp; struct net_buf *buf; buf = bt_hci_cmd_create(BT_HCI_OP_LE_LTK_REQ_NEG_REPLY, sizeof(*cp)); if (!buf) { BT_ERR("Out of command buffers"); return; } cp = net_buf_add(buf, sizeof(*cp)); cp->handle = sys_cpu_to_le16(handle); bt_hci_cmd_send(BT_HCI_OP_LE_LTK_REQ_NEG_REPLY, buf); } static void le_ltk_reply(u16_t handle, u8_t *ltk) { struct bt_hci_cp_le_ltk_req_reply *cp; struct net_buf *buf; buf = bt_hci_cmd_create(BT_HCI_OP_LE_LTK_REQ_REPLY, sizeof(*cp)); if (!buf) { BT_ERR("Out of command buffers"); return; } cp = net_buf_add(buf, sizeof(*cp)); cp->handle = sys_cpu_to_le16(handle); memcpy(cp->ltk, ltk, sizeof(cp->ltk)); bt_hci_cmd_send(BT_HCI_OP_LE_LTK_REQ_REPLY, buf); } static void le_ltk_request(struct net_buf *buf) { struct bt_hci_evt_le_ltk_request *evt = (void *)buf->data; struct bt_conn *conn; u16_t handle; u8_t ltk[16]; handle = sys_le16_to_cpu(evt->handle); BT_DBG("handle %u", handle); conn = bt_conn_lookup_handle(handle); if (!conn) { BT_ERR("Unable to lookup conn for handle %u", handle); return; } if (bt_smp_request_ltk(conn, evt->rand, evt->ediv, ltk)) { le_ltk_reply(handle, ltk); } else { le_ltk_neg_reply(handle); } bt_conn_unref(conn); } #endif /* CONFIG_BT_SMP */ #if defined(CONFIG_BT_ECC) static void le_pkey_complete(struct net_buf *buf) { struct bt_hci_evt_le_p256_public_key_complete *evt = (void *)buf->data; struct bt_pub_key_cb *cb; BT_DBG("status: 0x%02x", evt->status); atomic_clear_bit(bt_dev.flags, BT_DEV_PUB_KEY_BUSY); if (!evt->status) { memcpy(pub_key, evt->key, 64); atomic_set_bit(bt_dev.flags, BT_DEV_HAS_PUB_KEY); } for (cb = pub_key_cb; cb; cb = cb->_next) { cb->func(evt->status ? NULL : pub_key); } pub_key_cb = NULL; } static void le_dhkey_complete(struct net_buf *buf) { struct bt_hci_evt_le_generate_dhkey_complete *evt = (void *)buf->data; BT_DBG("status: 0x%02x", evt->status); if (dh_key_cb) { dh_key_cb(evt->status ? NULL : evt->dhkey); dh_key_cb = NULL; } } #endif /* CONFIG_BT_ECC */ static void hci_reset_complete(struct net_buf *buf) { u8_t status = buf->data[0]; atomic_t flags; BT_DBG("status 0x%02x", status); if (status) { return; } scan_dev_found_cb = NULL; #if defined(CONFIG_BT_BREDR) discovery_cb = NULL; discovery_results = NULL; discovery_results_size = 0; discovery_results_count = 0; #endif /* CONFIG_BT_BREDR */ flags = (atomic_get(bt_dev.flags) & BT_DEV_PERSISTENT_FLAGS); atomic_set(bt_dev.flags, flags); } static void hci_cmd_done(u16_t opcode, u8_t status, struct net_buf *buf) { BT_DBG("opcode 0x%04x status 0x%02x buf %p", opcode, status, buf); if (net_buf_pool_get(buf->pool_id) != &hci_cmd_pool) { BT_WARN("opcode 0x%04x pool id %u pool %p != &hci_cmd_pool %p", opcode, buf->pool_id, net_buf_pool_get(buf->pool_id), &hci_cmd_pool); return; } if (cmd(buf)->opcode != opcode) { BT_WARN("OpCode 0x%04x completed instead of expected 0x%04x", opcode, cmd(buf)->opcode); } if (cmd(buf)->state && !status) { struct cmd_state_set *update = cmd(buf)->state; atomic_set_bit_to(update->target, update->bit, update->val); } /* If the command was synchronous wake up bt_hci_cmd_send_sync() */ if (cmd(buf)->sync) { cmd(buf)->status = status; k_sem_give(cmd(buf)->sync); } } static void hci_cmd_complete(struct net_buf *buf) { struct bt_hci_evt_cmd_complete *evt; u8_t status, ncmd; u16_t opcode; evt = net_buf_pull_mem(buf, sizeof(*evt)); ncmd = evt->ncmd; opcode = sys_le16_to_cpu(evt->opcode); BT_DBG("opcode 0x%04x", opcode); /* All command return parameters have a 1-byte status in the * beginning, so we can safely make this generalization. */ status = buf->data[0]; hci_cmd_done(opcode, status, buf); /* Allow next command to be sent */ if (ncmd) { k_sem_give(&bt_dev.ncmd_sem); } } static void hci_cmd_status(struct net_buf *buf) { struct bt_hci_evt_cmd_status *evt; u16_t opcode; u8_t ncmd; evt = net_buf_pull_mem(buf, sizeof(*evt)); opcode = sys_le16_to_cpu(evt->opcode); ncmd = evt->ncmd; BT_DBG("opcode 0x%04x", opcode); hci_cmd_done(opcode, evt->status, buf); /* Allow next command to be sent */ if (ncmd) { k_sem_give(&bt_dev.ncmd_sem); } } #if defined(CONFIG_BT_OBSERVER) static int start_le_scan(u8_t scan_type, u16_t interval, u16_t window) { struct bt_hci_cp_le_set_scan_param set_param; struct net_buf *buf; int err; (void)memset(&set_param, 0, sizeof(set_param)); set_param.scan_type = scan_type; /* for the rest parameters apply default values according to * spec 4.2, vol2, part E, 7.8.10 */ set_param.interval = sys_cpu_to_le16(interval); set_param.window = sys_cpu_to_le16(window); if (IS_ENABLED(CONFIG_BT_WHITELIST) && atomic_test_bit(bt_dev.flags, BT_DEV_SCAN_WL)) { set_param.filter_policy = BT_HCI_LE_SCAN_FP_USE_WHITELIST; } else { set_param.filter_policy = BT_HCI_LE_SCAN_FP_NO_WHITELIST; } if (IS_ENABLED(CONFIG_BT_PRIVACY)) { err = le_set_private_addr(BT_ID_DEFAULT); if (err) { return err; } if (BT_FEAT_LE_PRIVACY(bt_dev.le.features)) { set_param.addr_type = BT_HCI_OWN_ADDR_RPA_OR_RANDOM; } else { set_param.addr_type = BT_ADDR_LE_RANDOM; } } else { set_param.addr_type = bt_dev.id_addr[0].type; /* Use NRPA unless identity has been explicitly requested * (through Kconfig), or if there is no advertising ongoing. */ if (!IS_ENABLED(CONFIG_BT_SCAN_WITH_IDENTITY) && !atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING)) { err = le_set_private_addr(BT_ID_DEFAULT); if (err) { return err; } set_param.addr_type = BT_ADDR_LE_RANDOM; } else if (IS_ENABLED(CONFIG_BT_SCAN_WITH_IDENTITY) && set_param.addr_type == BT_ADDR_LE_RANDOM) { /* If scanning with Identity Address we must set the * random identity address for both active and passive * scanner in order to receive adv reports that are * directed towards this identity. */ err = set_random_address(&bt_dev.id_addr[0].a); if (err) { return err; } } } buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_SCAN_PARAM, sizeof(set_param)); if (!buf) { return -ENOBUFS; } net_buf_add_mem(buf, &set_param, sizeof(set_param)); bt_hci_cmd_send(BT_HCI_OP_LE_SET_SCAN_PARAM, buf); err = set_le_scan_enable(BT_HCI_LE_SCAN_ENABLE); if (err) { return err; } atomic_set_bit_to(bt_dev.flags, BT_DEV_ACTIVE_SCAN, scan_type == BT_HCI_LE_SCAN_ACTIVE); return 0; } int bt_le_scan_update(bool fast_scan) { if (atomic_test_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN)) { return 0; } if (atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING)) { int err; err = set_le_scan_enable(BT_HCI_LE_SCAN_DISABLE); if (err) { return err; } } if (IS_ENABLED(CONFIG_BT_CENTRAL)) { u16_t interval, window; struct bt_conn *conn; /* don't restart scan if we have pending connection */ conn = bt_conn_lookup_state_le(BT_ID_DEFAULT, NULL, BT_CONN_CONNECT); if (conn) { bt_conn_unref(conn); return 0; } conn = bt_conn_lookup_state_le(BT_ID_DEFAULT, NULL, BT_CONN_CONNECT_SCAN); if (!conn) { return 0; } atomic_set_bit(bt_dev.flags, BT_DEV_SCAN_FILTER_DUP); bt_conn_unref(conn); if (fast_scan) { interval = BT_GAP_SCAN_FAST_INTERVAL; window = BT_GAP_SCAN_FAST_WINDOW; } else { interval = CONFIG_BT_BACKGROUND_SCAN_INTERVAL; window = CONFIG_BT_BACKGROUND_SCAN_WINDOW; } return start_le_scan(BT_HCI_LE_SCAN_PASSIVE, interval, window); } return 0; } void bt_data_parse(struct net_buf_simple *ad, bool (*func)(struct bt_data *data, void *user_data), void *user_data) { while (ad->len > 1) { struct bt_data data; u8_t len; len = net_buf_simple_pull_u8(ad); if (len == 0U) { /* Early termination */ return; } if (len > ad->len) { BT_WARN("Malformed data"); return; } data.type = net_buf_simple_pull_u8(ad); data.data_len = len - 1; data.data = ad->data; if (!func(&data, user_data)) { return; } net_buf_simple_pull(ad, len - 1); } } static void le_adv_report(struct net_buf *buf) { u8_t num_reports = net_buf_pull_u8(buf); struct bt_hci_evt_le_advertising_info *info; BT_DBG("Adv number of reports %u", num_reports); while (num_reports--) { struct bt_le_scan_cb *cb; struct net_buf_simple_state state; struct bt_le_scan_recv_info adv_info; bt_addr_le_t id_addr; s8_t rssi; if (buf->len < sizeof(*info)) { BT_ERR("Unexpected end of buffer"); break; } info = net_buf_pull_mem(buf, sizeof(*info)); rssi = info->data[info->length]; if (!IS_ENABLED(CONFIG_BT_PRIVACY) && !IS_ENABLED(CONFIG_BT_SCAN_WITH_IDENTITY) && atomic_test_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN) && info->evt_type == BT_LE_ADV_DIRECT_IND) { BT_DBG("Dropped direct adv report"); continue; } BT_DBG("%s event %u, len %u, rssi %d dBm", bt_addr_le_str(&info->addr), info->evt_type, info->length, rssi); if (info->addr.type == BT_ADDR_LE_PUBLIC_ID || info->addr.type == BT_ADDR_LE_RANDOM_ID) { bt_addr_le_copy(&id_addr, &info->addr); id_addr.type -= BT_ADDR_LE_PUBLIC_ID; } else { bt_addr_le_copy(&id_addr, bt_lookup_id_addr(BT_ID_DEFAULT, &info->addr)); } adv_info.addr = &id_addr; adv_info.adv_type = info->evt_type; adv_info.rssi = rssi; if (scan_dev_found_cb) { net_buf_simple_save(&buf->b, &state); buf->len = info->length; scan_dev_found_cb(&id_addr, rssi, info->evt_type, &buf->b); net_buf_simple_restore(&buf->b, &state); } SYS_SLIST_FOR_EACH_CONTAINER(&scan_cbs, cb, node) { net_buf_simple_save(&buf->b, &state); buf->len = info->length; cb->recv(&adv_info, &buf->b); net_buf_simple_restore(&buf->b, &state); } #if defined(CONFIG_BT_CENTRAL) check_pending_conn(&id_addr, &info->addr, info->evt_type); #endif /* CONFIG_BT_CENTRAL */ net_buf_pull(buf, info->length + sizeof(rssi)); } } #endif /* CONFIG_BT_OBSERVER */ int bt_hci_get_conn_handle(const struct bt_conn *conn, u16_t *conn_handle) { if (conn->state != BT_CONN_CONNECTED) { return -ENOTCONN; } *conn_handle = conn->handle; return 0; } #if defined(CONFIG_BT_HCI_VS_EVT_USER) int bt_hci_register_vnd_evt_cb(bt_hci_vnd_evt_cb_t cb) { hci_vnd_evt_cb = cb; return 0; } #endif /* CONFIG_BT_HCI_VS_EVT_USER */ static void hci_vendor_event(struct net_buf *buf) { bool handled = false; #if defined(CONFIG_BT_HCI_VS_EVT_USER) if (hci_vnd_evt_cb) { struct net_buf_simple_state state; net_buf_simple_save(&buf->b, &state); handled = hci_vnd_evt_cb(&buf->b); net_buf_simple_restore(&buf->b, &state); } #endif /* CONFIG_BT_HCI_VS_EVT_USER */ if (IS_ENABLED(CONFIG_BT_HCI_VS_EXT) && !handled) { /* do nothing at present time */ BT_WARN("Unhandled vendor-specific event: %s", bt_hex(buf->data, buf->len)); } } static const struct event_handler meta_events[] = { #if defined(CONFIG_BT_OBSERVER) EVENT_HANDLER(BT_HCI_EVT_LE_ADVERTISING_REPORT, le_adv_report, sizeof(struct bt_hci_evt_le_advertising_report)), #endif /* CONFIG_BT_OBSERVER */ #if defined(CONFIG_BT_CONN) EVENT_HANDLER(BT_HCI_EVT_LE_CONN_COMPLETE, le_legacy_conn_complete, sizeof(struct bt_hci_evt_le_conn_complete)), EVENT_HANDLER(BT_HCI_EVT_LE_ENH_CONN_COMPLETE, le_enh_conn_complete, sizeof(struct bt_hci_evt_le_enh_conn_complete)), EVENT_HANDLER(BT_HCI_EVT_LE_CONN_UPDATE_COMPLETE, le_conn_update_complete, sizeof(struct bt_hci_evt_le_conn_update_complete)), EVENT_HANDLER(BT_HCI_EV_LE_REMOTE_FEAT_COMPLETE, le_remote_feat_complete, sizeof(struct bt_hci_evt_le_remote_feat_complete)), EVENT_HANDLER(BT_HCI_EVT_LE_CONN_PARAM_REQ, le_conn_param_req, sizeof(struct bt_hci_evt_le_conn_param_req)), #if defined(CONFIG_BT_DATA_LEN_UPDATE) EVENT_HANDLER(BT_HCI_EVT_LE_DATA_LEN_CHANGE, le_data_len_change, sizeof(struct bt_hci_evt_le_data_len_change)), #endif /* CONFIG_BT_DATA_LEN_UPDATE */ #if defined(CONFIG_BT_PHY_UPDATE) EVENT_HANDLER(BT_HCI_EVT_LE_PHY_UPDATE_COMPLETE, le_phy_update_complete, sizeof(struct bt_hci_evt_le_phy_update_complete)), #endif /* CONFIG_BT_PHY_UPDATE */ #endif /* CONFIG_BT_CONN */ #if defined(CONFIG_BT_SMP) EVENT_HANDLER(BT_HCI_EVT_LE_LTK_REQUEST, le_ltk_request, sizeof(struct bt_hci_evt_le_ltk_request)), #endif /* CONFIG_BT_SMP */ #if defined(CONFIG_BT_ECC) EVENT_HANDLER(BT_HCI_EVT_LE_P256_PUBLIC_KEY_COMPLETE, le_pkey_complete, sizeof(struct bt_hci_evt_le_p256_public_key_complete)), EVENT_HANDLER(BT_HCI_EVT_LE_GENERATE_DHKEY_COMPLETE, le_dhkey_complete, sizeof(struct bt_hci_evt_le_generate_dhkey_complete)), #endif /* CONFIG_BT_SMP */ }; static void hci_le_meta_event(struct net_buf *buf) { struct bt_hci_evt_le_meta_event *evt; evt = net_buf_pull_mem(buf, sizeof(*evt)); BT_DBG("subevent 0x%02x", evt->subevent); handle_event(evt->subevent, buf, meta_events, ARRAY_SIZE(meta_events)); } static const struct event_handler normal_events[] = { EVENT_HANDLER(BT_HCI_EVT_VENDOR, hci_vendor_event, sizeof(struct bt_hci_evt_vs)), EVENT_HANDLER(BT_HCI_EVT_LE_META_EVENT, hci_le_meta_event, sizeof(struct bt_hci_evt_le_meta_event)), #if defined(CONFIG_BT_BREDR) EVENT_HANDLER(BT_HCI_EVT_CONN_REQUEST, conn_req, sizeof(struct bt_hci_evt_conn_request)), EVENT_HANDLER(BT_HCI_EVT_CONN_COMPLETE, conn_complete, sizeof(struct bt_hci_evt_conn_complete)), EVENT_HANDLER(BT_HCI_EVT_PIN_CODE_REQ, pin_code_req, sizeof(struct bt_hci_evt_pin_code_req)), EVENT_HANDLER(BT_HCI_EVT_LINK_KEY_NOTIFY, link_key_notify, sizeof(struct bt_hci_evt_link_key_notify)), EVENT_HANDLER(BT_HCI_EVT_LINK_KEY_REQ, link_key_req, sizeof(struct bt_hci_evt_link_key_req)), EVENT_HANDLER(BT_HCI_EVT_IO_CAPA_RESP, io_capa_resp, sizeof(struct bt_hci_evt_io_capa_resp)), EVENT_HANDLER(BT_HCI_EVT_IO_CAPA_REQ, io_capa_req, sizeof(struct bt_hci_evt_io_capa_req)), EVENT_HANDLER(BT_HCI_EVT_SSP_COMPLETE, ssp_complete, sizeof(struct bt_hci_evt_ssp_complete)), EVENT_HANDLER(BT_HCI_EVT_USER_CONFIRM_REQ, user_confirm_req, sizeof(struct bt_hci_evt_user_confirm_req)), EVENT_HANDLER(BT_HCI_EVT_USER_PASSKEY_NOTIFY, user_passkey_notify, sizeof(struct bt_hci_evt_user_passkey_notify)), EVENT_HANDLER(BT_HCI_EVT_USER_PASSKEY_REQ, user_passkey_req, sizeof(struct bt_hci_evt_user_passkey_req)), EVENT_HANDLER(BT_HCI_EVT_INQUIRY_COMPLETE, inquiry_complete, sizeof(struct bt_hci_evt_inquiry_complete)), EVENT_HANDLER(BT_HCI_EVT_INQUIRY_RESULT_WITH_RSSI, inquiry_result_with_rssi, sizeof(struct bt_hci_evt_inquiry_result_with_rssi)), EVENT_HANDLER(BT_HCI_EVT_EXTENDED_INQUIRY_RESULT, extended_inquiry_result, sizeof(struct bt_hci_evt_extended_inquiry_result)), EVENT_HANDLER(BT_HCI_EVT_REMOTE_NAME_REQ_COMPLETE, remote_name_request_complete, sizeof(struct bt_hci_evt_remote_name_req_complete)), EVENT_HANDLER(BT_HCI_EVT_AUTH_COMPLETE, auth_complete, sizeof(struct bt_hci_evt_auth_complete)), EVENT_HANDLER(BT_HCI_EVT_REMOTE_FEATURES, read_remote_features_complete, sizeof(struct bt_hci_evt_remote_features)), EVENT_HANDLER(BT_HCI_EVT_REMOTE_EXT_FEATURES, read_remote_ext_features_complete, sizeof(struct bt_hci_evt_remote_ext_features)), EVENT_HANDLER(BT_HCI_EVT_ROLE_CHANGE, role_change, sizeof(struct bt_hci_evt_role_change)), EVENT_HANDLER(BT_HCI_EVT_SYNC_CONN_COMPLETE, synchronous_conn_complete, sizeof(struct bt_hci_evt_sync_conn_complete)), #endif /* CONFIG_BT_BREDR */ #if defined(CONFIG_BT_CONN) EVENT_HANDLER(BT_HCI_EVT_DISCONN_COMPLETE, hci_disconn_complete, sizeof(struct bt_hci_evt_disconn_complete)), #endif /* CONFIG_BT_CONN */ #if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR) EVENT_HANDLER(BT_HCI_EVT_ENCRYPT_CHANGE, hci_encrypt_change, sizeof(struct bt_hci_evt_encrypt_change)), EVENT_HANDLER(BT_HCI_EVT_ENCRYPT_KEY_REFRESH_COMPLETE, hci_encrypt_key_refresh_complete, sizeof(struct bt_hci_evt_encrypt_key_refresh_complete)), #endif /* CONFIG_BT_SMP || CONFIG_BT_BREDR */ #if defined(CONFIG_BT_REMOTE_VERSION) EVENT_HANDLER(BT_HCI_EVT_REMOTE_VERSION_INFO, bt_hci_evt_read_remote_version_complete, sizeof(struct bt_hci_evt_remote_version_info)), #endif /* CONFIG_BT_REMOTE_VERSION */ }; static void hci_event(struct net_buf *buf) { struct bt_hci_evt_hdr *hdr; BT_ASSERT(buf->len >= sizeof(*hdr)); hdr = net_buf_pull_mem(buf, sizeof(*hdr)); BT_DBG("event 0x%02x", hdr->evt); BT_ASSERT(!bt_hci_evt_is_prio(hdr->evt)); handle_event(hdr->evt, buf, normal_events, ARRAY_SIZE(normal_events)); net_buf_unref(buf); } static void send_cmd(void) { struct net_buf *buf; int err; /* 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); } } static void process_events(struct k_poll_event *ev, int count) { BT_DBG("count %d", count); for (; count; ev++, count--) { BT_DBG("ev->state %u", ev->state); 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(); } else if (IS_ENABLED(CONFIG_BT_CONN)) { struct bt_conn *conn; if (ev->tag == BT_EVENT_CONN_TX_QUEUE) { conn = CONTAINER_OF(ev->fifo, struct bt_conn, tx_queue); bt_conn_process_tx(conn); } } break; case K_POLL_STATE_NOT_READY: break; default: BT_WARN("Unexpected k_poll event state %u", ev->state); break; } } } #if defined(CONFIG_BT_CONN) /* command FIFO + conn_change signal + MAX_CONN */ #define EV_COUNT (2 + CONFIG_BT_MAX_CONN) #else /* command FIFO */ #define EV_COUNT 1 #endif 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), }; BT_DBG("Started"); while (1) { int ev_count, err; events[0].state = K_POLL_STATE_NOT_READY; ev_count = 1; if (IS_ENABLED(CONFIG_BT_CONN)) { ev_count += bt_conn_prepare_events(&events[1]); } 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(); } } static void read_local_ver_complete(struct net_buf *buf) { struct bt_hci_rp_read_local_version_info *rp = (void *)buf->data; BT_DBG("status 0x%02x", rp->status); bt_dev.hci_version = rp->hci_version; bt_dev.hci_revision = sys_le16_to_cpu(rp->hci_revision); bt_dev.lmp_version = rp->lmp_version; bt_dev.lmp_subversion = sys_le16_to_cpu(rp->lmp_subversion); bt_dev.manufacturer = sys_le16_to_cpu(rp->manufacturer); } static void read_le_features_complete(struct net_buf *buf) { struct bt_hci_rp_le_read_local_features *rp = (void *)buf->data; BT_DBG("status 0x%02x", rp->status); memcpy(bt_dev.le.features, rp->features, sizeof(bt_dev.le.features)); } #if defined(CONFIG_BT_BREDR) static void read_buffer_size_complete(struct net_buf *buf) { struct bt_hci_rp_read_buffer_size *rp = (void *)buf->data; u16_t pkts; BT_DBG("status 0x%02x", rp->status); bt_dev.br.mtu = sys_le16_to_cpu(rp->acl_max_len); pkts = sys_le16_to_cpu(rp->acl_max_num); BT_DBG("ACL BR/EDR buffers: pkts %u mtu %u", pkts, bt_dev.br.mtu); k_sem_init(&bt_dev.br.pkts, pkts, pkts); } #elif defined(CONFIG_BT_CONN) static void read_buffer_size_complete(struct net_buf *buf) { struct bt_hci_rp_read_buffer_size *rp = (void *)buf->data; u16_t pkts; BT_DBG("status 0x%02x", rp->status); /* If LE-side has buffers we can ignore the BR/EDR values */ if (bt_dev.le.mtu) { return; } bt_dev.le.mtu = sys_le16_to_cpu(rp->acl_max_len); pkts = sys_le16_to_cpu(rp->acl_max_num); BT_DBG("ACL BR/EDR buffers: pkts %u mtu %u", pkts, bt_dev.le.mtu); k_sem_init(&bt_dev.le.pkts, pkts, pkts); } #endif #if defined(CONFIG_BT_CONN) static void le_read_buffer_size_complete(struct net_buf *buf) { struct bt_hci_rp_le_read_buffer_size *rp = (void *)buf->data; BT_DBG("status 0x%02x", rp->status); bt_dev.le.mtu = sys_le16_to_cpu(rp->le_max_len); if (!bt_dev.le.mtu) { return; } BT_DBG("ACL LE buffers: pkts %u mtu %u", rp->le_max_num, bt_dev.le.mtu); k_sem_init(&bt_dev.le.pkts, rp->le_max_num, rp->le_max_num); } #endif static void read_supported_commands_complete(struct net_buf *buf) { struct bt_hci_rp_read_supported_commands *rp = (void *)buf->data; BT_DBG("status 0x%02x", rp->status); memcpy(bt_dev.supported_commands, rp->commands, sizeof(bt_dev.supported_commands)); /* * Report "LE Read Local P-256 Public Key" and "LE Generate DH Key" as * supported if TinyCrypt ECC is used for emulation. */ if (IS_ENABLED(CONFIG_BT_TINYCRYPT_ECC)) { bt_dev.supported_commands[34] |= 0x02; bt_dev.supported_commands[34] |= 0x04; } } static void read_local_features_complete(struct net_buf *buf) { struct bt_hci_rp_read_local_features *rp = (void *)buf->data; BT_DBG("status 0x%02x", rp->status); memcpy(bt_dev.features[0], rp->features, sizeof(bt_dev.features[0])); } 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 0x%02x", rp->status); bt_dev.le.states = sys_get_le64(rp->le_states); } #if defined(CONFIG_BT_SMP) static void le_read_resolving_list_size_complete(struct net_buf *buf) { struct bt_hci_rp_le_read_rl_size *rp = (void *)buf->data; BT_DBG("Resolving List size %u", rp->rl_size); bt_dev.le.rl_size = rp->rl_size; } #endif /* defined(CONFIG_BT_SMP) */ static int common_init(void) { struct net_buf *rsp; int err; if (!(bt_dev.drv->quirks & BT_QUIRK_NO_RESET)) { /* 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); } /* 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); /* Read Local Version Information */ err = bt_hci_cmd_send_sync(BT_HCI_OP_READ_LOCAL_VERSION_INFO, NULL, &rsp); if (err) { return err; } read_local_ver_complete(rsp); net_buf_unref(rsp); /* 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); if (IS_ENABLED(CONFIG_BT_HOST_CRYPTO)) { /* Initialize the PRNG so that it is safe to use it later * on in the initialization process. */ err = prng_init(); if (err) { return err; } } #if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL) err = set_flow_control(); if (err) { return err; } #endif /* CONFIG_BT_HCI_ACL_FLOW_CONTROL */ return 0; } static int le_set_event_mask(void) { struct bt_hci_cp_le_set_event_mask *cp_mask; struct net_buf *buf; u64_t mask = 0U; /* 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_BT_CONN)) { if (IS_ENABLED(CONFIG_BT_SMP) && BT_FEAT_LE_PRIVACY(bt_dev.le.features)) { mask |= BT_EVT_MASK_LE_ENH_CONN_COMPLETE; } else { 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; } if (IS_ENABLED(CONFIG_BT_DATA_LEN_UPDATE) && BT_FEAT_LE_DLE(bt_dev.le.features)) { mask |= BT_EVT_MASK_LE_DATA_LEN_CHANGE; } if (IS_ENABLED(CONFIG_BT_PHY_UPDATE) && (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; } } if (IS_ENABLED(CONFIG_BT_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 (IS_ENABLED(CONFIG_BT_ECC) && (BT_CMD_TEST(bt_dev.supported_commands, 34, 1)) && (BT_CMD_TEST(bt_dev.supported_commands, 34, 2))) { 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); } static int le_init(void) { struct bt_hci_cp_write_le_host_supp *cp_le; struct net_buf *buf, *rsp; int err; /* For now we only support LE capable controllers */ if (!BT_FEAT_LE(bt_dev.features)) { BT_ERR("Non-LE capable controller detected!"); return -ENODEV; } /* Read Low Energy Supported Features */ err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_READ_LOCAL_FEATURES, NULL, &rsp); if (err) { return err; } read_le_features_complete(rsp); net_buf_unref(rsp); #if defined(CONFIG_BT_CONN) /* Read LE Buffer Size */ err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_READ_BUFFER_SIZE, NULL, &rsp); if (err) { return err; } le_read_buffer_size_complete(rsp); net_buf_unref(rsp); #endif if (BT_FEAT_BREDR(bt_dev.features)) { buf = bt_hci_cmd_create(BT_HCI_OP_LE_WRITE_LE_HOST_SUPP, sizeof(*cp_le)); if (!buf) { return -ENOBUFS; } cp_le = net_buf_add(buf, sizeof(*cp_le)); /* Explicitly enable LE for dual-mode controllers */ 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; } } /* 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); } if (IS_ENABLED(CONFIG_BT_CONN) && IS_ENABLED(CONFIG_BT_DATA_LEN_UPDATE) && BT_FEAT_LE_DLE(bt_dev.le.features)) { struct bt_hci_cp_le_write_default_data_len *cp; struct bt_hci_rp_le_read_max_data_len *rp; 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; } } #if defined(CONFIG_BT_SMP) if (BT_FEAT_LE_PRIVACY(bt_dev.le.features)) { #if defined(CONFIG_BT_PRIVACY) struct bt_hci_cp_le_set_rpa_timeout *cp; buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_RPA_TIMEOUT, sizeof(*cp)); if (!buf) { return -ENOBUFS; } cp = net_buf_add(buf, sizeof(*cp)); cp->rpa_timeout = sys_cpu_to_le16(CONFIG_BT_RPA_TIMEOUT); err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_RPA_TIMEOUT, buf, NULL); if (err) { return err; } #endif /* defined(CONFIG_BT_PRIVACY) */ err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_READ_RL_SIZE, NULL, &rsp); if (err) { return err; } le_read_resolving_list_size_complete(rsp); net_buf_unref(rsp); } #endif return le_set_event_mask(); } #if defined(CONFIG_BT_BREDR) 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; } void device_supported_pkt_type(void) { /* Device supported features and sco packet types */ if (BT_FEAT_HV2_PKT(bt_dev.features)) { bt_dev.br.esco_pkt_type |= (HCI_PKT_TYPE_ESCO_HV2); } if (BT_FEAT_HV3_PKT(bt_dev.features)) { bt_dev.br.esco_pkt_type |= (HCI_PKT_TYPE_ESCO_HV3); } if (BT_FEAT_LMP_ESCO_CAPABLE(bt_dev.features)) { bt_dev.br.esco_pkt_type |= (HCI_PKT_TYPE_ESCO_EV3); } if (BT_FEAT_EV4_PKT(bt_dev.features)) { bt_dev.br.esco_pkt_type |= (HCI_PKT_TYPE_ESCO_EV4); } if (BT_FEAT_EV5_PKT(bt_dev.features)) { bt_dev.br.esco_pkt_type |= (HCI_PKT_TYPE_ESCO_EV5); } if (BT_FEAT_2EV3_PKT(bt_dev.features)) { bt_dev.br.esco_pkt_type |= (HCI_PKT_TYPE_ESCO_2EV3); } if (BT_FEAT_3EV3_PKT(bt_dev.features)) { bt_dev.br.esco_pkt_type |= (HCI_PKT_TYPE_ESCO_3EV3); } if (BT_FEAT_3SLOT_PKT(bt_dev.features)) { bt_dev.br.esco_pkt_type |= (HCI_PKT_TYPE_ESCO_2EV5 | HCI_PKT_TYPE_ESCO_3EV5); } } static int br_init(void) { struct net_buf *buf; struct bt_hci_cp_write_ssp_mode *ssp_cp; struct bt_hci_cp_write_inquiry_mode *inq_cp; struct bt_hci_write_local_name *name_cp; int err; /* Read extended local features */ if (BT_FEAT_EXT_FEATURES(bt_dev.features)) { err = read_ext_features(); if (err) { return err; } } /* Add local supported packet types to bt_dev */ device_supported_pkt_type(); /* Get BR/EDR buffer size */ err = bt_hci_cmd_send_sync(BT_HCI_OP_READ_BUFFER_SIZE, NULL, &buf); if (err) { return err; } read_buffer_size_complete(buf); net_buf_unref(buf); /* Set SSP mode */ buf = bt_hci_cmd_create(BT_HCI_OP_WRITE_SSP_MODE, sizeof(*ssp_cp)); if (!buf) { return -ENOBUFS; } ssp_cp = net_buf_add(buf, sizeof(*ssp_cp)); ssp_cp->mode = 0x01; err = bt_hci_cmd_send_sync(BT_HCI_OP_WRITE_SSP_MODE, buf, NULL); if (err) { return err; } /* 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; } /* 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)); strncpy((char *)name_cp->local_name, CONFIG_BT_DEVICE_NAME, sizeof(name_cp->local_name)); err = bt_hci_cmd_send_sync(BT_HCI_OP_WRITE_LOCAL_NAME, buf, NULL); if (err) { return err; } /* Set page timeout*/ buf = bt_hci_cmd_create(BT_HCI_OP_WRITE_PAGE_TIMEOUT, sizeof(u16_t)); if (!buf) { return -ENOBUFS; } net_buf_add_le16(buf, CONFIG_BT_PAGE_TIMEOUT); err = bt_hci_cmd_send_sync(BT_HCI_OP_WRITE_PAGE_TIMEOUT, buf, NULL); if (err) { return err; } /* Enable BR/EDR SC if supported */ if (BT_FEAT_SC(bt_dev.features)) { 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; } } return 0; } #else static int br_init(void) { #if defined(CONFIG_BT_CONN) struct net_buf *rsp; int err; if (bt_dev.le.mtu) { return 0; } /* Use BR/EDR buffer size if LE reports zero buffers */ err = bt_hci_cmd_send_sync(BT_HCI_OP_READ_BUFFER_SIZE, NULL, &rsp); if (err) { return err; } read_buffer_size_complete(rsp); net_buf_unref(rsp); #endif /* CONFIG_BT_CONN */ return 0; } #endif static int set_event_mask(void) { struct bt_hci_cp_set_event_mask *ev; struct net_buf *buf; u64_t mask = 0U; buf = bt_hci_cmd_create(BT_HCI_OP_SET_EVENT_MASK, sizeof(*ev)); if (!buf) { return -ENOBUFS; } ev = net_buf_add(buf, sizeof(*ev)); if (IS_ENABLED(CONFIG_BT_BREDR)) { /* Since we require LE support, we can count on a * Bluetooth 4.0 feature set */ 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; if (IS_ENABLED(CONFIG_BT_CONN)) { mask |= BT_EVT_MASK_DISCONN_COMPLETE; mask |= BT_EVT_MASK_REMOTE_VERSION_INFO; } if (IS_ENABLED(CONFIG_BT_SMP) && BT_FEAT_LE_ENCR(bt_dev.le.features)) { mask |= BT_EVT_MASK_ENCRYPT_CHANGE; mask |= BT_EVT_MASK_ENCRYPT_KEY_REFRESH_COMPLETE; } sys_put_le64(mask, ev->events); return bt_hci_cmd_send_sync(BT_HCI_OP_SET_EVENT_MASK, buf, NULL); } 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; } static u8_t bt_read_public_addr(bt_addr_le_t *addr) { struct bt_hci_rp_read_bd_addr *rp; struct net_buf *rsp; int err; /* Read Bluetooth Address */ err = bt_hci_cmd_send_sync(BT_HCI_OP_READ_BD_ADDR, NULL, &rsp); if (err) { BT_WARN("Failed to read public address"); return 0U; } rp = (void *)rsp->data; if (!bt_addr_cmp(&rp->bdaddr, BT_ADDR_ANY) || !bt_addr_cmp(&rp->bdaddr, BT_ADDR_NONE)) { BT_DBG("Controller has no public address"); net_buf_unref(rsp); return 0U; } bt_addr_copy(&addr->a, &rp->bdaddr); addr->type = BT_ADDR_LE_PUBLIC; net_buf_unref(rsp); return 1U; } #if defined(CONFIG_BT_DEBUG) static const char *ver_str(u8_t ver) { const char * const str[] = { "1.0b", "1.1", "1.2", "2.0", "2.1", "3.0", "4.0", "4.1", "4.2", "5.0", "5.1", "5.2" }; if (ver < ARRAY_SIZE(str)) { return str[ver]; } return "unknown"; } static void bt_dev_show_info(void) { int i; BT_INFO("Identity%s: %s", bt_dev.id_count > 1 ? "[0]" : "", bt_addr_le_str(&bt_dev.id_addr[0])); for (i = 1; i < bt_dev.id_count; i++) { BT_INFO("Identity[%d]: %s", i, bt_addr_le_str(&bt_dev.id_addr[i])); } 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 bt_dev_show_info(void) { } #endif /* CONFIG_BT_DEBUG */ #if defined(CONFIG_BT_HCI_VS_EXT) #if defined(CONFIG_BT_DEBUG) static const char *vs_hw_platform(u16_t platform) { static const char * const plat_str[] = { "reserved", "Intel Corporation", "Nordic Semiconductor", "NXP Semiconductors" }; if (platform < ARRAY_SIZE(plat_str)) { return plat_str[platform]; } return "unknown"; } static const char *vs_hw_variant(u16_t platform, u16_t variant) { static const char * const nordic_str[] = { "reserved", "nRF51x", "nRF52x", "nRF53x" }; if (platform != BT_HCI_VS_HW_PLAT_NORDIC) { return "unknown"; } if (variant < ARRAY_SIZE(nordic_str)) { return nordic_str[variant]; } return "unknown"; } static const char *vs_fw_variant(u8_t variant) { static const char * const var_str[] = { "Standard Bluetooth controller", "Vendor specific controller", "Firmware loader", "Rescue image", }; if (variant < ARRAY_SIZE(var_str)) { return var_str[variant]; } return "unknown"; } #endif /* CONFIG_BT_DEBUG */ static void hci_vs_init(void) { union { struct bt_hci_rp_vs_read_version_info *info; struct bt_hci_rp_vs_read_supported_commands *cmds; struct bt_hci_rp_vs_read_supported_features *feat; } rp; struct net_buf *rsp; int err; /* If heuristics is enabled, try to guess HCI VS support by looking * at the HCI version and identity address. We haven't set any addresses * at this point. So we need to read the public address. */ if (IS_ENABLED(CONFIG_BT_HCI_VS_EXT_DETECT)) { bt_addr_le_t addr; if ((bt_dev.hci_version < BT_HCI_VERSION_5_0) || bt_read_public_addr(&addr)) { BT_WARN("Controller doesn't seem to support " "Zephyr vendor HCI"); return; } } err = bt_hci_cmd_send_sync(BT_HCI_OP_VS_READ_VERSION_INFO, NULL, &rsp); if (err) { BT_WARN("Vendor HCI extensions not available"); return; } if (IS_ENABLED(CONFIG_BT_HCI_VS_EXT_DETECT) && rsp->len != sizeof(struct bt_hci_rp_vs_read_version_info)) { BT_WARN("Invalid Vendor HCI extensions"); net_buf_unref(rsp); return; } #if defined(CONFIG_BT_DEBUG) rp.info = (void *)rsp->data; BT_INFO("HW Platform: %s (0x%04x)", vs_hw_platform(sys_le16_to_cpu(rp.info->hw_platform)), sys_le16_to_cpu(rp.info->hw_platform)); BT_INFO("HW Variant: %s (0x%04x)", vs_hw_variant(sys_le16_to_cpu(rp.info->hw_platform), sys_le16_to_cpu(rp.info->hw_variant)), sys_le16_to_cpu(rp.info->hw_variant)); BT_INFO("Firmware: %s (0x%02x) Version %u.%u Build %u", vs_fw_variant(rp.info->fw_variant), rp.info->fw_variant, rp.info->fw_version, sys_le16_to_cpu(rp.info->fw_revision), sys_le32_to_cpu(rp.info->fw_build)); #endif /* CONFIG_BT_DEBUG */ net_buf_unref(rsp); err = bt_hci_cmd_send_sync(BT_HCI_OP_VS_READ_SUPPORTED_COMMANDS, NULL, &rsp); if (err) { BT_WARN("Failed to read supported vendor commands"); return; } if (IS_ENABLED(CONFIG_BT_HCI_VS_EXT_DETECT) && rsp->len != sizeof(struct bt_hci_rp_vs_read_supported_commands)) { BT_WARN("Invalid Vendor HCI extensions"); net_buf_unref(rsp); return; } rp.cmds = (void *)rsp->data; memcpy(bt_dev.vs_commands, rp.cmds->commands, BT_DEV_VS_CMDS_MAX); net_buf_unref(rsp); if (BT_VS_CMD_SUP_FEAT(bt_dev.vs_commands)) { err = bt_hci_cmd_send_sync(BT_HCI_OP_VS_READ_SUPPORTED_FEATURES, NULL, &rsp); if (err) { BT_WARN("Failed to read supported vendor features"); return; } if (IS_ENABLED(CONFIG_BT_HCI_VS_EXT_DETECT) && rsp->len != sizeof(struct bt_hci_rp_vs_read_supported_features)) { BT_WARN("Invalid Vendor HCI extensions"); net_buf_unref(rsp); return; } rp.feat = (void *)rsp->data; memcpy(bt_dev.vs_features, rp.feat->features, BT_DEV_VS_FEAT_MAX); net_buf_unref(rsp); } } #endif /* CONFIG_BT_HCI_VS_EXT */ static int hci_init(void) { int err; err = common_init(); if (err) { return err; } err = le_init(); if (err) { return err; } if (BT_FEAT_BREDR(bt_dev.features)) { err = br_init(); if (err) { return err; } } else if (IS_ENABLED(CONFIG_BT_BREDR)) { BT_ERR("Non-BR/EDR controller detected"); return -EIO; } err = set_event_mask(); if (err) { return err; } #if defined(CONFIG_BT_HCI_VS_EXT) hci_vs_init(); #endif if (!IS_ENABLED(CONFIG_BT_SETTINGS) && !bt_dev.id_count) { BT_DBG("No user identity. Trying to set public."); bt_setup_public_id_addr(); } if (!IS_ENABLED(CONFIG_BT_SETTINGS) && !bt_dev.id_count) { BT_DBG("No public address. Trying to set static random."); err = bt_setup_random_id_addr(); if (err) { BT_ERR("Unable to set identity address"); return err; } /* The passive scanner just sends a dummy address type in the * command. If the first activity does this, and the dummy type * is a random address, it needs a valid value, even though it's * not actually used. */ err = set_random_address(&bt_dev.id_addr[0].a); if (err) { BT_ERR("Unable to set random address"); return err; } } return 0; } int bt_send(struct net_buf *buf) { BT_DBG("buf %p len %u type %u", buf, buf->len, bt_buf_get_type(buf)); bt_monitor_send(bt_monitor_opcode(buf), buf->data, buf->len); if (IS_ENABLED(CONFIG_BT_TINYCRYPT_ECC)) { return bt_hci_ecc_send(buf); } return bt_dev.drv->send(buf); } 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); switch (bt_buf_get_type(buf)) { #if defined(CONFIG_BT_CONN) case BT_BUF_ACL_IN: #if defined(CONFIG_BT_RECV_IS_RX_THREAD) hci_acl(buf); #else net_buf_put(&bt_dev.rx_queue, buf); #endif return 0; #endif /* BT_CONN */ case BT_BUF_EVT: #if defined(CONFIG_BT_RECV_IS_RX_THREAD) hci_event(buf); #else net_buf_put(&bt_dev.rx_queue, buf); #endif return 0; default: BT_ERR("Invalid buf type %u", bt_buf_get_type(buf)); net_buf_unref(buf); return -EINVAL; } } static const struct event_handler prio_events[] = { EVENT_HANDLER(BT_HCI_EVT_CMD_COMPLETE, hci_cmd_complete, sizeof(struct bt_hci_evt_cmd_complete)), EVENT_HANDLER(BT_HCI_EVT_CMD_STATUS, hci_cmd_status, sizeof(struct bt_hci_evt_cmd_status)), #if defined(CONFIG_BT_CONN) EVENT_HANDLER(BT_HCI_EVT_DATA_BUF_OVERFLOW, hci_data_buf_overflow, sizeof(struct bt_hci_evt_data_buf_overflow)), EVENT_HANDLER(BT_HCI_EVT_NUM_COMPLETED_PACKETS, hci_num_completed_packets, sizeof(struct bt_hci_evt_num_completed_packets)), #endif /* CONFIG_BT_CONN */ }; int bt_recv_prio(struct net_buf *buf) { struct bt_hci_evt_hdr *hdr; 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)); hdr = net_buf_pull_mem(buf, sizeof(*hdr)); BT_ASSERT(bt_hci_evt_is_prio(hdr->evt)); handle_event(hdr->evt, buf, prio_events, ARRAY_SIZE(prio_events)); net_buf_unref(buf); return 0; } int bt_hci_driver_register(const struct bt_hci_driver *drv) { if (bt_dev.drv) { return -EALREADY; } if (!drv->open || !drv->send) { return -EINVAL; } bt_dev.drv = drv; BT_DBG("Registered %s", drv->name ? drv->name : ""); bt_monitor_new_index(BT_MONITOR_TYPE_PRIMARY, drv->bus, BT_ADDR_ANY, drv->name ? drv->name : "bt0"); return 0; } void bt_finalize_init(void) { atomic_set_bit(bt_dev.flags, BT_DEV_READY); if (IS_ENABLED(CONFIG_BT_OBSERVER)) { bt_le_scan_update(false); } bt_dev_show_info(); } static int bt_init(void) { int err; err = hci_init(); if (err) { return err; } if (IS_ENABLED(CONFIG_BT_CONN)) { err = bt_conn_init(); if (err) { return err; } } #if defined(CONFIG_BT_PRIVACY) k_delayed_work_init(&bt_dev.rpa_update, rpa_timeout); #endif if (IS_ENABLED(CONFIG_BT_SETTINGS)) { if (!bt_dev.id_count) { BT_INFO("No ID address. App must call settings_load()"); return 0; } atomic_set_bit(bt_dev.flags, BT_DEV_PRESET_ID); } bt_finalize_init(); return 0; } static void init_work(struct k_work *work) { int err; err = bt_init(); if (ready_cb) { ready_cb(err); } } #if !defined(CONFIG_BT_RECV_IS_RX_THREAD) static void hci_rx_thread(void) { struct net_buf *buf; BT_DBG("started"); while (1) { BT_DBG("calling fifo_get_wait"); buf = net_buf_get(&bt_dev.rx_queue, K_FOREVER); BT_DBG("buf %p type %u len %u", buf, bt_buf_get_type(buf), buf->len); switch (bt_buf_get_type(buf)) { #if defined(CONFIG_BT_CONN) case BT_BUF_ACL_IN: hci_acl(buf); break; #endif /* CONFIG_BT_CONN */ case BT_BUF_EVT: hci_event(buf); break; default: BT_ERR("Unknown buf type %u", bt_buf_get_type(buf)); net_buf_unref(buf); break; } /* Make sure we don't hog the CPU if the rx_queue never * gets empty. */ k_yield(); } } #endif /* !CONFIG_BT_RECV_IS_RX_THREAD */ int bt_enable(bt_ready_cb_t cb) { int err; if (!bt_dev.drv) { BT_ERR("No HCI driver registered"); return -ENODEV; } if (atomic_test_and_set_bit(bt_dev.flags, BT_DEV_ENABLE)) { return -EALREADY; } if (IS_ENABLED(CONFIG_BT_SETTINGS)) { err = bt_settings_init(); if (err) { return err; } } else { bt_set_name(CONFIG_BT_DEVICE_NAME); } ready_cb = cb; /* TX thread */ k_thread_create(&tx_thread_data, tx_thread_stack, K_THREAD_STACK_SIZEOF(tx_thread_stack), hci_tx_thread, NULL, NULL, NULL, K_PRIO_COOP(CONFIG_BT_HCI_TX_PRIO), 0, K_NO_WAIT); k_thread_name_set(&tx_thread_data, "BT TX"); #if !defined(CONFIG_BT_RECV_IS_RX_THREAD) /* RX thread */ k_thread_create(&rx_thread_data, rx_thread_stack, K_THREAD_STACK_SIZEOF(rx_thread_stack), (k_thread_entry_t)hci_rx_thread, NULL, NULL, NULL, K_PRIO_COOP(CONFIG_BT_RX_PRIO), 0, K_NO_WAIT); k_thread_name_set(&rx_thread_data, "BT RX"); #endif if (IS_ENABLED(CONFIG_BT_TINYCRYPT_ECC)) { bt_hci_ecc_init(); } err = bt_dev.drv->open(); if (err) { BT_ERR("HCI driver open failed (%d)", err); return err; } bt_monitor_send(BT_MONITOR_OPEN_INDEX, NULL, 0); if (!cb) { return bt_init(); } k_work_submit(&bt_dev.init); return 0; } struct bt_ad { const struct bt_data *data; size_t len; }; static int set_ad(u16_t hci_op, const struct bt_ad *ad, size_t ad_len) { struct bt_hci_cp_le_set_adv_data *set_data; struct net_buf *buf; int c, i; buf = bt_hci_cmd_create(hci_op, sizeof(*set_data)); if (!buf) { return -ENOBUFS; } set_data = net_buf_add(buf, sizeof(*set_data)); (void)memset(set_data, 0, sizeof(*set_data)); for (c = 0; c < ad_len; c++) { const struct bt_data *data = ad[c].data; for (i = 0; i < ad[c].len; i++) { int len = data[i].data_len; u8_t type = data[i].type; /* Check if ad fit in the remaining buffer */ if (set_data->len + len + 2 > 31) { len = 31 - (set_data->len + 2); if (type != BT_DATA_NAME_COMPLETE || !len) { net_buf_unref(buf); BT_ERR("Too big advertising data"); return -EINVAL; } type = BT_DATA_NAME_SHORTENED; } set_data->data[set_data->len++] = len + 1; set_data->data[set_data->len++] = type; memcpy(&set_data->data[set_data->len], data[i].data, len); set_data->len += len; } } return bt_hci_cmd_send_sync(hci_op, buf, NULL); } int bt_set_name(const char *name) { #if defined(CONFIG_BT_DEVICE_NAME_DYNAMIC) size_t len = strlen(name); int err; if (len >= sizeof(bt_dev.name)) { return -ENOMEM; } if (!strcmp(bt_dev.name, name)) { return 0; } strncpy(bt_dev.name, name, sizeof(bt_dev.name)); /* Update advertising name if in use */ if (atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING_NAME)) { struct bt_data data[] = { BT_DATA(BT_DATA_NAME_COMPLETE, name, strlen(name)) }; struct bt_ad sd = { data, ARRAY_SIZE(data) }; set_ad(BT_HCI_OP_LE_SET_SCAN_RSP_DATA, &sd, 1); } if (IS_ENABLED(CONFIG_BT_SETTINGS)) { err = settings_save_one("bt/name", bt_dev.name, len); if (err) { BT_WARN("Unable to store name"); } } return 0; #else return -ENOMEM; #endif } const char *bt_get_name(void) { #if defined(CONFIG_BT_DEVICE_NAME_DYNAMIC) return bt_dev.name; #else return CONFIG_BT_DEVICE_NAME; #endif } int bt_set_id_addr(const bt_addr_le_t *addr) { bt_addr_le_t non_const_addr; if (atomic_test_bit(bt_dev.flags, BT_DEV_READY)) { BT_ERR("Setting identity not allowed after bt_enable()"); return -EBUSY; } bt_addr_le_copy(&non_const_addr, addr); return bt_id_create(&non_const_addr, NULL); } void bt_id_get(bt_addr_le_t *addrs, size_t *count) { size_t to_copy = MIN(*count, bt_dev.id_count); memcpy(addrs, bt_dev.id_addr, to_copy * sizeof(bt_addr_le_t)); *count = to_copy; } static int id_find(const bt_addr_le_t *addr) { u8_t id; for (id = 0U; id < bt_dev.id_count; id++) { if (!bt_addr_le_cmp(addr, &bt_dev.id_addr[id])) { return id; } } return -ENOENT; } static void id_create(u8_t id, bt_addr_le_t *addr, u8_t *irk) { if (addr && bt_addr_le_cmp(addr, BT_ADDR_LE_ANY)) { bt_addr_le_copy(&bt_dev.id_addr[id], addr); } else { bt_addr_le_t new_addr; do { bt_addr_le_create_static(&new_addr); /* Make sure we didn't generate a duplicate */ } while (id_find(&new_addr) >= 0); bt_addr_le_copy(&bt_dev.id_addr[id], &new_addr); if (addr) { bt_addr_le_copy(addr, &bt_dev.id_addr[id]); } } #if defined(CONFIG_BT_PRIVACY) { u8_t zero_irk[16] = { 0 }; if (irk && memcmp(irk, zero_irk, 16)) { memcpy(&bt_dev.irk[id], irk, 16); } else { bt_rand(&bt_dev.irk[id], 16); if (irk) { memcpy(irk, &bt_dev.irk[id], 16); } } } #endif /* Only store if stack was already initialized. Before initialization * we don't know the flash content, so it's potentially harmful to * try to write anything there. */ if (IS_ENABLED(CONFIG_BT_SETTINGS) && atomic_test_bit(bt_dev.flags, BT_DEV_READY)) { bt_settings_save_id(); } } int bt_id_create(bt_addr_le_t *addr, u8_t *irk) { int new_id; if (addr && bt_addr_le_cmp(addr, BT_ADDR_LE_ANY)) { if (addr->type != BT_ADDR_LE_RANDOM || !BT_ADDR_IS_STATIC(&addr->a)) { BT_ERR("Only static random identity address supported"); return -EINVAL; } if (id_find(addr) >= 0) { return -EALREADY; } } if (!IS_ENABLED(CONFIG_BT_PRIVACY) && irk) { return -EINVAL; } if (bt_dev.id_count == ARRAY_SIZE(bt_dev.id_addr)) { return -ENOMEM; } new_id = bt_dev.id_count++; id_create(new_id, addr, irk); return new_id; } int bt_id_reset(u8_t id, bt_addr_le_t *addr, u8_t *irk) { if (addr && bt_addr_le_cmp(addr, BT_ADDR_LE_ANY)) { if (addr->type != BT_ADDR_LE_RANDOM || !BT_ADDR_IS_STATIC(&addr->a)) { BT_ERR("Only static random identity address supported"); return -EINVAL; } if (id_find(addr) >= 0) { return -EALREADY; } } if (!IS_ENABLED(CONFIG_BT_PRIVACY) && irk) { return -EINVAL; } if (id == BT_ID_DEFAULT || id >= bt_dev.id_count) { return -EINVAL; } if (id == bt_dev.adv_id && atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING)) { return -EBUSY; } if (IS_ENABLED(CONFIG_BT_CONN) && bt_addr_le_cmp(&bt_dev.id_addr[id], BT_ADDR_LE_ANY)) { int err; err = bt_unpair(id, NULL); if (err) { return err; } } id_create(id, addr, irk); return id; } int bt_id_delete(u8_t id) { if (id == BT_ID_DEFAULT || id >= bt_dev.id_count) { return -EINVAL; } if (!bt_addr_le_cmp(&bt_dev.id_addr[id], BT_ADDR_LE_ANY)) { return -EALREADY; } if (id == bt_dev.adv_id && atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING)) { return -EBUSY; } if (IS_ENABLED(CONFIG_BT_CONN)) { int err; err = bt_unpair(id, NULL); if (err) { return err; } } #if defined(CONFIG_BT_PRIVACY) (void)memset(bt_dev.irk[id], 0, 16); #endif bt_addr_le_copy(&bt_dev.id_addr[id], BT_ADDR_LE_ANY); if (id == bt_dev.id_count - 1) { bt_dev.id_count--; } if (IS_ENABLED(CONFIG_BT_SETTINGS) && atomic_test_bit(bt_dev.flags, BT_DEV_READY)) { bt_settings_save_id(); } return 0; } #if defined(CONFIG_BT_PRIVACY) static void bt_read_identity_root(u8_t *ir) { /* Invalid IR */ memset(ir, 0, 16); #if defined(CONFIG_BT_HCI_VS_EXT) struct bt_hci_rp_vs_read_key_hierarchy_roots *rp; struct net_buf *rsp; int err; if (!BT_VS_CMD_READ_KEY_ROOTS(bt_dev.vs_commands)) { return; } err = bt_hci_cmd_send_sync(BT_HCI_OP_VS_READ_KEY_HIERARCHY_ROOTS, NULL, &rsp); if (err) { BT_WARN("Failed to read identity root"); return; } if (IS_ENABLED(CONFIG_BT_HCI_VS_EXT_DETECT) && rsp->len != sizeof(struct bt_hci_rp_vs_read_key_hierarchy_roots)) { BT_WARN("Invalid Vendor HCI extensions"); net_buf_unref(rsp); return; } rp = (void *)rsp->data; memcpy(ir, rp->ir, 16); net_buf_unref(rsp); #endif /* defined(CONFIG_BT_HCI_VS_EXT) */ } #endif /* defined(CONFIG_BT_PRIVACY) */ void bt_setup_public_id_addr(void) { bt_addr_le_t addr; u8_t *irk = NULL; bt_dev.id_count = bt_read_public_addr(&addr); if (!bt_dev.id_count) { return; } #if defined(CONFIG_BT_PRIVACY) u8_t ir_irk[16]; u8_t ir[16]; bt_read_identity_root(ir); if (!bt_smp_irk_get(ir, ir_irk)) { irk = ir_irk; } else if (IS_ENABLED(CONFIG_BT_SETTINGS)) { atomic_set_bit(bt_dev.flags, BT_DEV_STORE_ID); } #endif /* defined(CONFIG_BT_PRIVACY) */ id_create(BT_ID_DEFAULT, &addr, irk); } #if defined(CONFIG_BT_HCI_VS_EXT) u8_t bt_read_static_addr(struct bt_hci_vs_static_addr addrs[], u8_t size) { struct bt_hci_rp_vs_read_static_addrs *rp; struct net_buf *rsp; int err, i; u8_t cnt; if (!BT_VS_CMD_READ_STATIC_ADDRS(bt_dev.vs_commands)) { BT_WARN("Read Static Addresses command not available"); return 0; } err = bt_hci_cmd_send_sync(BT_HCI_OP_VS_READ_STATIC_ADDRS, NULL, &rsp); if (err) { BT_WARN("Failed to read static addresses"); return 0; } if (IS_ENABLED(CONFIG_BT_HCI_VS_EXT_DETECT) && rsp->len < sizeof(struct bt_hci_rp_vs_read_static_addrs)) { BT_WARN("Invalid Vendor HCI extensions"); net_buf_unref(rsp); return 0; } rp = (void *)rsp->data; cnt = MIN(rp->num_addrs, size); if (IS_ENABLED(CONFIG_BT_HCI_VS_EXT_DETECT) && rsp->len != (sizeof(struct bt_hci_rp_vs_read_static_addrs) + rp->num_addrs * sizeof(struct bt_hci_vs_static_addr))) { BT_WARN("Invalid Vendor HCI extensions"); net_buf_unref(rsp); return 0; } for (i = 0; i < cnt; i++) { memcpy(&addrs[i], rp->a, sizeof(struct bt_hci_vs_static_addr)); } net_buf_unref(rsp); if (!cnt) { BT_WARN("No static addresses stored in controller"); } return cnt; } #endif /* CONFIG_BT_HCI_VS_EXT */ int bt_setup_random_id_addr(void) { #if defined(CONFIG_BT_HCI_VS_EXT) || defined(CONFIG_BT_CTLR) /* Only read the addresses if the user has not already configured one or * more identities (!bt_dev.id_count). */ if (!bt_dev.id_count) { struct bt_hci_vs_static_addr addrs[CONFIG_BT_ID_MAX]; bt_dev.id_count = bt_read_static_addr(addrs, CONFIG_BT_ID_MAX); if (bt_dev.id_count) { for (u8_t i = 0; i < bt_dev.id_count; i++) { bt_addr_le_t addr; u8_t *irk = NULL; #if defined(CONFIG_BT_PRIVACY) u8_t ir_irk[16]; if (!bt_smp_irk_get(addrs[i].ir, ir_irk)) { irk = ir_irk; } else if (IS_ENABLED(CONFIG_BT_SETTINGS)) { atomic_set_bit(bt_dev.flags, BT_DEV_STORE_ID); } #endif /* CONFIG_BT_PRIVACY */ bt_addr_copy(&addr.a, &addrs[i].bdaddr); addr.type = BT_ADDR_LE_RANDOM; id_create(i, &addr, irk); } return 0; } } #endif /* defined(CONFIG_BT_HCI_VS_EXT) || defined(CONFIG_BT_CTLR) */ if (IS_ENABLED(CONFIG_BT_PRIVACY) && IS_ENABLED(CONFIG_BT_SETTINGS)) { atomic_set_bit(bt_dev.flags, BT_DEV_STORE_ID); } return bt_id_create(NULL, NULL); } bool bt_addr_le_is_bonded(u8_t id, const bt_addr_le_t *addr) { if (IS_ENABLED(CONFIG_BT_SMP)) { struct bt_keys *keys = bt_keys_find_addr(id, addr); /* if there are any keys stored then device is bonded */ return keys && keys->keys; } else { return false; } } static bool valid_adv_param(const struct bt_le_adv_param *param, bool dir_adv) { if (param->id >= bt_dev.id_count || !bt_addr_le_cmp(&bt_dev.id_addr[param->id], BT_ADDR_LE_ANY)) { return false; } if (!(param->options & BT_LE_ADV_OPT_CONNECTABLE)) { /* * 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. */ if (bt_dev.hci_version < BT_HCI_VERSION_5_0 && param->interval_min < 0x00a0) { return false; } } if ((param->options & BT_LE_ADV_OPT_DIR_MODE_LOW_DUTY) || !dir_adv) { if (param->interval_min > param->interval_max || param->interval_min < 0x0020 || param->interval_max > 0x4000) { return false; } } return true; } static inline bool ad_has_name(const struct bt_data *ad, size_t ad_len) { int i; for (i = 0; i < ad_len; i++) { if (ad[i].type == BT_DATA_NAME_COMPLETE || ad[i].type == BT_DATA_NAME_SHORTENED) { return true; } } return false; } static int le_adv_update(const struct bt_data *ad, size_t ad_len, const struct bt_data *sd, size_t sd_len, bool connectable, bool use_name) { struct bt_ad d[2] = {}; struct bt_data data; int err; d[0].data = ad; d[0].len = ad_len; err = set_ad(BT_HCI_OP_LE_SET_ADV_DATA, d, 1); if (err) { return err; } d[0].data = sd; d[0].len = sd_len; if (use_name) { const char *name; if (sd) { /* Cannot use name if name is already set */ if (ad_has_name(sd, sd_len)) { return -EINVAL; } } name = bt_get_name(); data = (struct bt_data)BT_DATA( BT_DATA_NAME_COMPLETE, name, strlen(name)); d[1].data = &data; d[1].len = 1; } /* * We need to set SCAN_RSP when enabling advertising type that * allows for Scan Requests. * * If any data 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. */ if (d[0].data || d[1].data || connectable) { err = set_ad(BT_HCI_OP_LE_SET_SCAN_RSP_DATA, d, 2); if (err) { return err; } } return 0; } int bt_le_adv_update_data(const struct bt_data *ad, size_t ad_len, const struct bt_data *sd, size_t sd_len) { bool connectable, use_name; if (!atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING)) { return -EAGAIN; } connectable = atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING_CONNECTABLE); use_name = atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING_NAME); return le_adv_update(ad, ad_len, sd, sd_len, connectable, use_name); } int bt_le_adv_start_internal(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, const bt_addr_le_t *peer) { struct bt_hci_cp_le_set_adv_param set_param; const bt_addr_le_t *id_addr; struct bt_conn *conn = NULL; struct net_buf *buf; bool dir_adv = (peer != NULL); int err = 0; if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) { return -EAGAIN; } if (!valid_adv_param(param, dir_adv)) { return -EINVAL; } if (atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING)) { return -EALREADY; } if (!bt_le_adv_random_addr_check(param)) { return -EINVAL; } (void)memset(&set_param, 0, sizeof(set_param)); 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; if (bt_dev.adv_id != param->id) { atomic_clear_bit(bt_dev.flags, BT_DEV_RPA_VALID); } #if defined(CONFIG_BT_WHITELIST) if ((param->options & BT_LE_ADV_OPT_FILTER_SCAN_REQ) && (param->options & BT_LE_ADV_OPT_FILTER_CONN)) { set_param.filter_policy = BT_LE_ADV_FP_WHITELIST_BOTH; } else if (param->options & BT_LE_ADV_OPT_FILTER_SCAN_REQ) { set_param.filter_policy = BT_LE_ADV_FP_WHITELIST_SCAN_REQ; } else if (param->options & BT_LE_ADV_OPT_FILTER_CONN) { set_param.filter_policy = BT_LE_ADV_FP_WHITELIST_CONN_IND; } else { #else { #endif /* defined(CONFIG_BT_WHITELIST) */ set_param.filter_policy = BT_LE_ADV_FP_NO_WHITELIST; } /* Set which local identity address we're advertising with */ bt_dev.adv_id = param->id; id_addr = &bt_dev.id_addr[param->id]; if (param->options & BT_LE_ADV_OPT_CONNECTABLE) { if (IS_ENABLED(CONFIG_BT_PRIVACY) && !(param->options & BT_LE_ADV_OPT_USE_IDENTITY)) { err = le_set_private_addr(param->id); if (err) { return err; } if (BT_FEAT_LE_PRIVACY(bt_dev.le.features)) { set_param.own_addr_type = BT_HCI_OWN_ADDR_RPA_OR_RANDOM; } else { 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 (id_addr->type == BT_ADDR_LE_RANDOM) { err = set_random_address(&id_addr->a); if (err) { return err; } } set_param.own_addr_type = id_addr->type; } if (dir_adv) { if (param->options & BT_LE_ADV_OPT_DIR_MODE_LOW_DUTY) { set_param.type = BT_LE_ADV_DIRECT_IND_LOW_DUTY; } else { set_param.type = BT_LE_ADV_DIRECT_IND; } bt_addr_le_copy(&set_param.direct_addr, peer); if (IS_ENABLED(CONFIG_BT_SMP) && !IS_ENABLED(CONFIG_BT_PRIVACY) && BT_FEAT_LE_PRIVACY(bt_dev.le.features) && (param->options & BT_LE_ADV_OPT_DIR_ADDR_RPA)) { /* This will not use RPA for our own address * since we have set zeroed out the local IRK. */ set_param.own_addr_type |= BT_HCI_OWN_ADDR_RPA_MASK; } } else { set_param.type = BT_LE_ADV_IND; } } else { if (param->options & BT_LE_ADV_OPT_USE_IDENTITY) { if (id_addr->type == BT_ADDR_LE_RANDOM) { err = set_random_address(&id_addr->a); } set_param.own_addr_type = id_addr->type; } else { #if defined(CONFIG_BT_OBSERVER) bool scan_enabled = false; /* If active scan with NRPA is ongoing refresh NRPA */ if (!IS_ENABLED(CONFIG_BT_PRIVACY) && !IS_ENABLED(CONFIG_BT_SCAN_WITH_IDENTITY) && atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING) && atomic_test_bit(bt_dev.flags, BT_DEV_ACTIVE_SCAN)) { scan_enabled = true; set_le_scan_enable(false); } #endif /* defined(CONFIG_BT_OBSERVER) */ err = le_set_private_addr(param->id); set_param.own_addr_type = BT_ADDR_LE_RANDOM; #if defined(CONFIG_BT_OBSERVER) if (scan_enabled) { set_le_scan_enable(true); } #endif /* defined(CONFIG_BT_OBSERVER) */ } if (err) { return err; } if (sd || (param->options & BT_LE_ADV_OPT_USE_NAME)) { set_param.type = BT_LE_ADV_SCAN_IND; } else { set_param.type = BT_LE_ADV_NONCONN_IND; } } buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADV_PARAM, sizeof(set_param)); if (!buf) { return -ENOBUFS; } net_buf_add_mem(buf, &set_param, sizeof(set_param)); err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_ADV_PARAM, buf, NULL); if (err) { return err; } if (!dir_adv) { err = le_adv_update(ad, ad_len, sd, sd_len, param->options & BT_LE_ADV_OPT_CONNECTABLE, param->options & BT_LE_ADV_OPT_USE_NAME); if (err) { return err; } if (IS_ENABLED(CONFIG_BT_PERIPHERAL) && param->options & BT_LE_ADV_OPT_CONNECTABLE) { conn = bt_conn_add_le(param->id, BT_ADDR_LE_NONE); if (!conn) { return -ENOMEM; } bt_conn_set_state(conn, BT_CONN_CONNECT_ADV); } } err = set_advertise_enable(true); if (err) { BT_ERR("Failed to start advertiser"); if (IS_ENABLED(CONFIG_BT_PERIPHERAL) && conn) { bt_conn_set_state(conn, BT_CONN_DISCONNECTED); bt_conn_unref(conn); } return err; } if (IS_ENABLED(CONFIG_BT_PERIPHERAL) && conn) { /* If undirected connectable advertiser we have created a * connection object that we don't yet give to the application. * Since we don't give the application a reference to manage in * this case, we need to release this reference here */ bt_conn_unref(conn); } atomic_set_bit_to(bt_dev.flags, BT_DEV_KEEP_ADVERTISING, !(param->options & BT_LE_ADV_OPT_ONE_TIME)); atomic_set_bit_to(bt_dev.flags, BT_DEV_ADVERTISING_NAME, param->options & BT_LE_ADV_OPT_USE_NAME); atomic_set_bit_to(bt_dev.flags, BT_DEV_ADVERTISING_CONNECTABLE, param->options & BT_LE_ADV_OPT_CONNECTABLE); atomic_set_bit_to(bt_dev.flags, BT_DEV_ADVERTISING_IDENTITY, param->options & BT_LE_ADV_OPT_USE_IDENTITY); return 0; } 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) { if (param->options & BT_LE_ADV_OPT_DIR_MODE_LOW_DUTY) { return -EINVAL; } return bt_le_adv_start_internal(param, ad, ad_len, sd, sd_len, NULL); } int bt_le_adv_stop(void) { int err; /* Make sure advertising is not re-enabled later even if it's not * currently enabled (i.e. BT_DEV_ADVERTISING is not set). */ atomic_clear_bit(bt_dev.flags, BT_DEV_KEEP_ADVERTISING); if (!atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING)) { return 0; } if (IS_ENABLED(CONFIG_BT_PERIPHERAL)) { struct bt_conn *conn; conn = bt_conn_lookup_state_le(bt_dev.adv_id, BT_ADDR_LE_NONE, BT_CONN_CONNECT_ADV); if (conn) { bt_conn_set_state(conn, BT_CONN_DISCONNECTED); bt_conn_unref(conn); } conn = bt_conn_lookup_state_le(bt_dev.adv_id, NULL, BT_CONN_CONNECT_DIR_ADV); if (conn) { bt_conn_set_state(conn, BT_CONN_DISCONNECTED); bt_conn_unref(conn); } } err = set_advertise_enable(false); if (err) { return err; } #if defined(CONFIG_BT_OBSERVER) if (!IS_ENABLED(CONFIG_BT_PRIVACY) && !IS_ENABLED(CONFIG_BT_SCAN_WITH_IDENTITY)) { /* If scan is ongoing set back NRPA */ if (atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING)) { set_le_scan_enable(BT_HCI_LE_SCAN_DISABLE); le_set_private_addr(bt_dev.adv_id); set_le_scan_enable(BT_HCI_LE_SCAN_ENABLE); } } #endif /* defined(CONFIG_BT_OBSERVER) */ return 0; } #if defined(CONFIG_BT_PERIPHERAL) void bt_le_adv_resume(void) { struct bt_conn *adv_conn; int err; BT_ASSERT(atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING_CONNECTABLE)); adv_conn = bt_conn_add_le(bt_dev.adv_id, BT_ADDR_LE_NONE); if (!adv_conn) { return; } bt_conn_set_state(adv_conn, BT_CONN_CONNECT_ADV); if (IS_ENABLED(CONFIG_BT_PRIVACY) && !atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING_IDENTITY)) { le_set_private_addr(bt_dev.adv_id); } err = set_advertise_enable(true); if (err) { bt_conn_set_state(adv_conn, BT_CONN_DISCONNECTED); } /* Since we don't give the application a reference to manage in * this case, we need to release this reference here. */ bt_conn_unref(adv_conn); } #endif /* defined(CONFIG_BT_PERIPHERAL) */ #if defined(CONFIG_BT_OBSERVER) 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; } if (param->filter_dup & ~(BT_LE_SCAN_FILTER_DUPLICATE | BT_LE_SCAN_FILTER_WHITELIST)) { return false; } 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; } int bt_le_scan_start(const struct bt_le_scan_param *param, bt_le_scan_cb_t cb) { int err; if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) { return -EAGAIN; } /* Check that the parameters have valid values */ if (!valid_le_scan_param(param)) { return -EINVAL; } if (param->type && !bt_le_scan_random_addr_check()) { return -EINVAL; } /* Return if active scan is already enabled */ if (atomic_test_and_set_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN)) { return -EALREADY; } if (atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING)) { err = set_le_scan_enable(BT_HCI_LE_SCAN_DISABLE); if (err) { atomic_clear_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN); return err; } } atomic_set_bit_to(bt_dev.flags, BT_DEV_SCAN_FILTER_DUP, param->filter_dup & BT_LE_SCAN_FILTER_DUPLICATE); #if defined(CONFIG_BT_WHITELIST) atomic_set_bit_to(bt_dev.flags, BT_DEV_SCAN_WL, param->filter_dup & BT_LE_SCAN_FILTER_WHITELIST); #endif /* defined(CONFIG_BT_WHITELIST) */ err = start_le_scan(param->type, param->interval, param->window); if (err) { atomic_clear_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN); return err; } scan_dev_found_cb = cb; return 0; } int bt_le_scan_stop(void) { /* Return if active scanning is already disabled */ if (!atomic_test_and_clear_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN)) { return -EALREADY; } scan_dev_found_cb = NULL; return bt_le_scan_update(false); } void bt_le_scan_cb_register(struct bt_le_scan_cb *cb) { sys_slist_append(&scan_cbs, &cb->node); } #endif /* CONFIG_BT_OBSERVER */ #if defined(CONFIG_BT_WHITELIST) int bt_le_whitelist_add(const bt_addr_le_t *addr) { struct bt_hci_cp_le_add_dev_to_wl *cp; struct net_buf *buf; int err; if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) { return -EAGAIN; } buf = bt_hci_cmd_create(BT_HCI_OP_LE_ADD_DEV_TO_WL, sizeof(*cp)); if (!buf) { return -ENOBUFS; } cp = net_buf_add(buf, sizeof(*cp)); bt_addr_le_copy(&cp->addr, addr); err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_ADD_DEV_TO_WL, buf, NULL); if (err) { BT_ERR("Failed to add device to whitelist"); return err; } return 0; } int bt_le_whitelist_rem(const bt_addr_le_t *addr) { struct bt_hci_cp_le_rem_dev_from_wl *cp; struct net_buf *buf; int err; if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) { return -EAGAIN; } buf = bt_hci_cmd_create(BT_HCI_OP_LE_REM_DEV_FROM_WL, sizeof(*cp)); if (!buf) { return -ENOBUFS; } cp = net_buf_add(buf, sizeof(*cp)); bt_addr_le_copy(&cp->addr, addr); err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_REM_DEV_FROM_WL, buf, NULL); if (err) { BT_ERR("Failed to remove device from whitelist"); return err; } return 0; } int bt_le_whitelist_clear(void) { int err; if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) { return -EAGAIN; } err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_CLEAR_WL, NULL, NULL); if (err) { BT_ERR("Failed to clear whitelist"); return err; } return 0; } #endif /* defined(CONFIG_BT_WHITELIST) */ int bt_le_set_chan_map(u8_t chan_map[5]) { struct bt_hci_cp_le_set_host_chan_classif *cp; struct net_buf *buf; if (!IS_ENABLED(CONFIG_BT_CENTRAL)) { return -ENOTSUP; } if (!BT_CMD_TEST(bt_dev.supported_commands, 27, 3)) { BT_WARN("Set Host Channel Classification command is " "not supported"); return -ENOTSUP; } buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_HOST_CHAN_CLASSIF, sizeof(*cp)); if (!buf) { return -ENOBUFS; } cp = net_buf_add(buf, sizeof(*cp)); memcpy(&cp->ch_map[0], &chan_map[0], 4); cp->ch_map[4] = chan_map[4] & BIT_MASK(5); return bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_HOST_CHAN_CLASSIF, buf, NULL); } struct net_buf *bt_buf_get_rx(enum bt_buf_type type, s32_t timeout) { struct net_buf *buf; __ASSERT(type == BT_BUF_EVT || type == BT_BUF_ACL_IN, "Invalid buffer type requested"); #if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL) if (type == BT_BUF_EVT) { buf = net_buf_alloc(&hci_rx_pool, timeout); } else { buf = net_buf_alloc(&acl_in_pool, timeout); } #else buf = net_buf_alloc(&hci_rx_pool, timeout); #endif if (buf) { net_buf_reserve(buf, BT_BUF_RESERVE); bt_buf_set_type(buf, type); } return buf; } struct net_buf *bt_buf_get_cmd_complete(s32_t timeout) { 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 = 0U; net_buf_reserve(buf, BT_BUF_RESERVE); return buf; } return bt_buf_get_rx(BT_BUF_EVT, timeout); } struct net_buf *bt_buf_get_evt(u8_t evt, bool discardable, s32_t timeout) { switch (evt) { #if defined(CONFIG_BT_CONN) case BT_HCI_EVT_NUM_COMPLETED_PACKETS: { struct net_buf *buf; buf = net_buf_alloc(&num_complete_pool, timeout); if (buf) { net_buf_reserve(buf, BT_BUF_RESERVE); bt_buf_set_type(buf, BT_BUF_EVT); } return buf; } #endif /* CONFIG_BT_CONN */ case BT_HCI_EVT_CMD_COMPLETE: case BT_HCI_EVT_CMD_STATUS: return bt_buf_get_cmd_complete(timeout); default: #if defined(CONFIG_BT_DISCARDABLE_BUF_COUNT) if (discardable) { struct net_buf *buf; buf = net_buf_alloc(&discardable_pool, timeout); if (buf) { net_buf_reserve(buf, BT_BUF_RESERVE); bt_buf_set_type(buf, BT_BUF_EVT); } return buf; } #endif /* CONFIG_BT_DISCARDABLE_BUF_COUNT */ return bt_buf_get_rx(BT_BUF_EVT, timeout); } } #if defined(CONFIG_BT_BREDR) static int br_start_inquiry(const struct bt_br_discovery_param *param) { const u8_t iac[3] = { 0x33, 0x8b, 0x9e }; 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)); cp->length = param->length; cp->num_rsp = 0xff; /* we limit discovery only by time */ memcpy(cp->lap, iac, 3); if (param->limited) { cp->lap[0] = 0x00; } return bt_hci_cmd_send_sync(BT_HCI_OP_INQUIRY, buf, NULL); } 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; } 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(""); if (!valid_br_discov_param(param, cnt)) { return -EINVAL; } if (atomic_test_bit(bt_dev.flags, BT_DEV_INQUIRY)) { return -EALREADY; } err = br_start_inquiry(param); if (err) { return err; } atomic_set_bit(bt_dev.flags, BT_DEV_INQUIRY); (void)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; int i; 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; } for (i = 0; i < discovery_results_count; i++) { struct discovery_priv *priv; struct bt_hci_cp_remote_name_cancel *cp; struct net_buf *buf; priv = (struct discovery_priv *)&discovery_results[i]._priv; 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); } 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; } static int write_scan_enable(u8_t scan) { 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; } net_buf_add_u8(buf, scan); err = bt_hci_cmd_send_sync(BT_HCI_OP_WRITE_SCAN_ENABLE, buf, NULL); if (err) { return err; } atomic_set_bit_to(bt_dev.flags, BT_DEV_ISCAN, (scan & BT_BREDR_SCAN_INQUIRY)); atomic_set_bit_to(bt_dev.flags, BT_DEV_PSCAN, (scan & BT_BREDR_SCAN_PAGE)); return 0; } int bt_br_set_connectable(bool enable) { if (enable) { if (atomic_test_bit(bt_dev.flags, BT_DEV_PSCAN)) { return -EALREADY; } else { return write_scan_enable(BT_BREDR_SCAN_PAGE); } } else { if (!atomic_test_bit(bt_dev.flags, BT_DEV_PSCAN)) { return -EALREADY; } else { return write_scan_enable(BT_BREDR_SCAN_DISABLED); } } } int bt_br_set_discoverable(bool enable) { 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; } return write_scan_enable(BT_BREDR_SCAN_INQUIRY | BT_BREDR_SCAN_PAGE); } else { if (!atomic_test_bit(bt_dev.flags, BT_DEV_ISCAN)) { return -EALREADY; } return write_scan_enable(BT_BREDR_SCAN_PAGE); } } #endif /* CONFIG_BT_BREDR */ #if defined(CONFIG_BT_ECC) int bt_pub_key_gen(struct bt_pub_key_cb *new_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_CMD_TEST(bt_dev.supported_commands, 34, 1) || !BT_CMD_TEST(bt_dev.supported_commands, 34, 2)) { BT_WARN("ECC HCI commands not available"); return -ENOTSUP; } new_cb->_next = pub_key_cb; pub_key_cb = new_cb; if (atomic_test_and_set_bit(bt_dev.flags, BT_DEV_PUB_KEY_BUSY)) { return 0; } atomic_clear_bit(bt_dev.flags, BT_DEV_HAS_PUB_KEY); err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_P256_PUBLIC_KEY, NULL, NULL); if (err) { BT_ERR("Sending LE P256 Public Key command failed"); atomic_clear_bit(bt_dev.flags, BT_DEV_PUB_KEY_BUSY); pub_key_cb = NULL; return err; } return 0; } const u8_t *bt_pub_key_get(void) { if (atomic_test_bit(bt_dev.flags, BT_DEV_HAS_PUB_KEY)) { return pub_key; } return NULL; } int bt_dh_key_gen(const u8_t remote_pk[64], bt_dh_key_cb_t cb) { 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; } #endif /* CONFIG_BT_ECC */ #if defined(CONFIG_BT_BREDR) int bt_br_oob_get_local(struct bt_br_oob *oob) { bt_addr_copy(&oob->addr, &bt_dev.id_addr[0].a); return 0; } #endif /* CONFIG_BT_BREDR */ int bt_le_oob_get_local(u8_t id, struct bt_le_oob *oob) { int err; if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) { return -EAGAIN; } if (id >= CONFIG_BT_ID_MAX) { return -EINVAL; } if (IS_ENABLED(CONFIG_BT_PRIVACY) && !(atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING) && atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING_IDENTITY) && bt_dev.adv_id == id && bt_dev.id_addr[id].type == BT_ADDR_LE_RANDOM)) { if (IS_ENABLED(CONFIG_BT_CENTRAL) && atomic_test_bit(bt_dev.flags, BT_DEV_INITIATING)) { struct bt_conn *conn; conn = bt_conn_lookup_state_le(BT_ID_DEFAULT, NULL, BT_CONN_CONNECT_SCAN); if (conn) { /* Cannot set new RPA while creating * connections. */ bt_conn_unref(conn); return -EINVAL; } } if (atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING) && atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING_IDENTITY) && (bt_dev.id_addr[id].type == BT_ADDR_LE_RANDOM)) { /* Cannot set a new RPA address while advertising with * random static identity address for a different * identity. */ return -EINVAL; } if (IS_ENABLED(CONFIG_BT_OBSERVER) && id != BT_ID_DEFAULT && (atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING) || atomic_test_bit(bt_dev.flags, BT_DEV_INITIATING))) { /* Cannot switch identity of scanner or initiator */ return -EINVAL; } /* Invalidate RPA so a new one is generated */ atomic_clear_bit(bt_dev.flags, BT_DEV_RPA_VALID); le_update_private_addr(); bt_addr_le_copy(&oob->addr, &bt_dev.random_addr); } else { bt_addr_le_copy(&oob->addr, &bt_dev.id_addr[id]); } if (IS_ENABLED(CONFIG_BT_SMP) && !IS_ENABLED(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY)) { err = bt_smp_le_oob_generate_sc_data(&oob->le_sc_data); if (err) { return err; } } return 0; } #if defined(CONFIG_BT_SMP) #if !defined(CONFIG_BT_SMP_SC_PAIR_ONLY) int bt_le_oob_set_legacy_tk(struct bt_conn *conn, const u8_t *tk) { return bt_smp_le_oob_set_tk(conn, tk); } #endif /* !defined(CONFIG_BT_SMP_SC_PAIR_ONLY) */ #if !defined(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY) int bt_le_oob_set_sc_data(struct bt_conn *conn, const struct bt_le_oob_sc_data *oobd_local, const struct bt_le_oob_sc_data *oobd_remote) { if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) { return -EAGAIN; } return bt_smp_le_oob_set_sc_data(conn, oobd_local, oobd_remote); } int bt_le_oob_get_sc_data(struct bt_conn *conn, const struct bt_le_oob_sc_data **oobd_local, const struct bt_le_oob_sc_data **oobd_remote) { if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) { return -EAGAIN; } return bt_smp_le_oob_get_sc_data(conn, oobd_local, oobd_remote); } #endif /* !defined(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY) */ #endif /* defined(CONFIG_BT_SMP) */