Compare commits
57 Commits
v2.7.6
...
v1.13-bran
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ec4e86f5cc | ||
|
|
84ae2f11ed | ||
|
|
5a0f7e44f1 | ||
|
|
da38403f9d | ||
|
|
7e7886782f | ||
|
|
07537107a8 | ||
|
|
210c27e370 | ||
|
|
3637202c53 | ||
|
|
a4d57234fc | ||
|
|
734ee4e57f | ||
|
|
3769030f87 | ||
|
|
bb07b4d3fb | ||
|
|
82de097f20 | ||
|
|
00d62fbd68 | ||
|
|
e1f52c2800 | ||
|
|
8f53d5ebe7 | ||
|
|
3517f9b2ef | ||
|
|
c8ad2089ea | ||
|
|
ebf9699f5b | ||
|
|
623e8c2d17 | ||
|
|
791b2bd83d | ||
|
|
335f231921 | ||
|
|
5b35b4568d | ||
|
|
0a599e9283 | ||
|
|
1f242b21fa | ||
|
|
78fdefecb6 | ||
|
|
5892a68041 | ||
|
|
31cdde8ca3 | ||
|
|
da62735763 | ||
|
|
f58ce51c2f | ||
|
|
308d2c0468 | ||
|
|
b79952c39d | ||
|
|
da5b22595f | ||
|
|
036bc5fbc0 | ||
|
|
791dad637d | ||
|
|
9ffc9825b4 | ||
|
|
e934506635 | ||
|
|
a7814a6e1d | ||
|
|
eb1f5804b2 | ||
|
|
ecda5c74a7 | ||
|
|
1310603c5f | ||
|
|
cdf6458122 | ||
|
|
1c361f130c | ||
|
|
6f1300d246 | ||
|
|
cb2476ccd3 | ||
|
|
1b50ccab05 | ||
|
|
732f1ac0b5 | ||
|
|
9e429e8e2d | ||
|
|
00cd24110a | ||
|
|
736e124671 | ||
|
|
7531653139 | ||
|
|
d50095351b | ||
|
|
346a9f0710 | ||
|
|
e9c6e4d2f3 | ||
|
|
85667eda09 | ||
|
|
c32b5872b8 | ||
|
|
cd4d2d67ee |
@@ -209,7 +209,7 @@ struct bt_conn *bt_conn_create_le(const bt_addr_le_t *peer,
|
||||
*
|
||||
* @return Zero on success or error code otherwise.
|
||||
*/
|
||||
int bt_le_set_auto_conn(bt_addr_le_t *addr,
|
||||
int bt_le_set_auto_conn(const bt_addr_le_t *addr,
|
||||
const struct bt_le_conn_param *param);
|
||||
|
||||
/** @brief Initiate directed advertising to a remote device
|
||||
@@ -386,6 +386,18 @@ struct bt_conn_cb {
|
||||
*/
|
||||
void bt_conn_cb_register(struct bt_conn_cb *cb);
|
||||
|
||||
/** Enable/disable bonding.
|
||||
*
|
||||
* Set/clear the Bonding flag in the Authentication Requirements of
|
||||
* SMP Pairing Request/Response data.
|
||||
* The initial value of this flag depends on BT_BONDABLE Kconfig setting.
|
||||
* For the vast majority of applications calling this function shouldn't be
|
||||
* needed.
|
||||
*
|
||||
* @param enable Value allowing/disallowing to be bondable.
|
||||
*/
|
||||
void bt_set_bondable(bool enable);
|
||||
|
||||
/** @def BT_PASSKEY_INVALID
|
||||
*
|
||||
* Special passkey value that can be used to disable a previously
|
||||
|
||||
39
include/bluetooth/controller.h
Normal file
39
include/bluetooth/controller.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/** @file
|
||||
* @brief Bluetooth subsystem controller APIs.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2018 Codecoup
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef ZEPHYR_INCLUDE_BLUETOOTH_CONTROLLER_H_
|
||||
#define ZEPHYR_INCLUDE_BLUETOOTH_CONTROLLER_H_
|
||||
|
||||
/**
|
||||
* @brief Bluetooth Controller
|
||||
* @defgroup bt_ctrl Bluetooth Controller
|
||||
* @ingroup bluetooth
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @brief Set public address for controller
|
||||
*
|
||||
* Should be called before bt_enable().
|
||||
*
|
||||
* @param addr Public address
|
||||
*/
|
||||
void bt_ctlr_set_public_addr(const u8_t *addr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* ZEPHYR_INCLUDE_BLUETOOTH_CONTROLLER_H_ */
|
||||
@@ -240,6 +240,10 @@ struct bt_l2cap_server {
|
||||
* @param chan Pointer to received the allocated channel
|
||||
*
|
||||
* @return 0 in case of success or negative value in case of error.
|
||||
* Possible return values:
|
||||
* -ENOMEM if no available space for new channel.
|
||||
* -EACCES if application did not authorize the connection.
|
||||
* -EPERM if encryption key size is too short.
|
||||
*/
|
||||
int (*accept)(struct bt_conn *conn, struct bt_l2cap_chan **chan);
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ static struct k_thread tx_thread_data;
|
||||
NET_BUF_POOL_DEFINE(cmd_tx_pool, CONFIG_BT_HCI_CMD_COUNT, CMD_BUF_SIZE,
|
||||
BT_BUF_USER_DATA_MIN, NULL);
|
||||
|
||||
#if defined(CONFIG_BT_CTLR)
|
||||
#if defined(CONFIG_BT_CTLR_TX_BUFFER_SIZE)
|
||||
#define BT_L2CAP_MTU (CONFIG_BT_CTLR_TX_BUFFER_SIZE - BT_L2CAP_HDR_SIZE)
|
||||
#else
|
||||
#define BT_L2CAP_MTU 65 /* 64-byte public key + opcode */
|
||||
|
||||
@@ -25,8 +25,8 @@ CONFIG_BT_BROADCASTER=y
|
||||
|
||||
CONFIG_BT_CTLR_LE_ENC=n
|
||||
CONFIG_BT_CTLR_LE_PING=n
|
||||
CONFIG_BT_CTLR_DATA_LENGTH=n
|
||||
CONFIG_BT_CTLR_PHY=n
|
||||
CONFIG_BT_DATA_LEN_UPDATE=n
|
||||
CONFIG_BT_PHY_UPDATE=n
|
||||
CONFIG_BT_CTLR_CHAN_SEL_2=n
|
||||
CONFIG_BT_CTLR_MIN_USED_CHAN=n
|
||||
CONFIG_BT_CTLR_ADV_EXT=n
|
||||
|
||||
@@ -15,8 +15,8 @@ CONFIG_BT_BROADCASTER=y
|
||||
CONFIG_BT_CTLR_DUP_FILTER_LEN=0
|
||||
CONFIG_BT_CTLR_LE_ENC=n
|
||||
CONFIG_BT_CTLR_LE_PING=n
|
||||
CONFIG_BT_CTLR_DATA_LENGTH=n
|
||||
CONFIG_BT_CTLR_PHY=n
|
||||
CONFIG_BT_DATA_LEN_UPDATE=n
|
||||
CONFIG_BT_PHY_UPDATE=n
|
||||
CONFIG_BT_CTLR_CHAN_SEL_2=n
|
||||
CONFIG_BT_CTLR_MIN_USED_CHAN=n
|
||||
CONFIG_BT_CTLR_ADV_EXT=n
|
||||
|
||||
@@ -24,8 +24,8 @@ CONFIG_BT_BROADCASTER=y
|
||||
|
||||
CONFIG_BT_CTLR_LE_ENC=n
|
||||
CONFIG_BT_CTLR_LE_PING=n
|
||||
CONFIG_BT_CTLR_DATA_LENGTH=n
|
||||
CONFIG_BT_CTLR_PHY=n
|
||||
CONFIG_BT_DATA_LEN_UPDATE=n
|
||||
CONFIG_BT_PHY_UPDATE=n
|
||||
CONFIG_BT_CTLR_CHAN_SEL_2=n
|
||||
CONFIG_BT_CTLR_MIN_USED_CHAN=n
|
||||
CONFIG_BT_CTLR_ADV_EXT=n
|
||||
|
||||
@@ -11,8 +11,8 @@ CONFIG_BT_CTLR_DUP_FILTER_LEN=0
|
||||
|
||||
CONFIG_BT_CTLR_LE_ENC=n
|
||||
CONFIG_BT_CTLR_LE_PING=n
|
||||
CONFIG_BT_CTLR_DATA_LENGTH=n
|
||||
CONFIG_BT_CTLR_PHY=n
|
||||
CONFIG_BT_DATA_LEN_UPDATE=n
|
||||
CONFIG_BT_PHY_UPDATE=n
|
||||
CONFIG_BT_CTLR_CHAN_SEL_2=n
|
||||
CONFIG_BT_CTLR_MIN_USED_CHAN=n
|
||||
CONFIG_BT_CTLR_ADV_EXT=n
|
||||
|
||||
@@ -19,8 +19,8 @@ CONFIG_BT_BROADCASTER=y
|
||||
CONFIG_BT_CTLR_DUP_FILTER_LEN=0
|
||||
CONFIG_BT_CTLR_LE_ENC=n
|
||||
CONFIG_BT_CTLR_LE_PING=n
|
||||
CONFIG_BT_CTLR_DATA_LENGTH=n
|
||||
CONFIG_BT_CTLR_PHY=n
|
||||
CONFIG_BT_DATA_LEN_UPDATE=n
|
||||
CONFIG_BT_PHY_UPDATE=n
|
||||
CONFIG_BT_CTLR_CHAN_SEL_2=n
|
||||
CONFIG_BT_CTLR_MIN_USED_CHAN=n
|
||||
CONFIG_BT_CTLR_ADV_EXT=n
|
||||
|
||||
@@ -16,8 +16,8 @@ CONFIG_BT_BROADCASTER=y
|
||||
CONFIG_BT_CTLR_DUP_FILTER_LEN=0
|
||||
CONFIG_BT_CTLR_LE_ENC=n
|
||||
CONFIG_BT_CTLR_LE_PING=n
|
||||
CONFIG_BT_CTLR_DATA_LENGTH=n
|
||||
CONFIG_BT_CTLR_PHY=n
|
||||
CONFIG_BT_DATA_LEN_UPDATE=n
|
||||
CONFIG_BT_PHY_UPDATE=n
|
||||
CONFIG_BT_CTLR_CHAN_SEL_2=n
|
||||
CONFIG_BT_CTLR_MIN_USED_CHAN=n
|
||||
CONFIG_BT_CTLR_ADV_EXT=n
|
||||
|
||||
@@ -85,6 +85,18 @@ config BT_OBSERVER
|
||||
|
||||
endmenu
|
||||
|
||||
config BT_PHY_UPDATE
|
||||
bool "PHY Update"
|
||||
default y
|
||||
help
|
||||
Enable support for Bluetooth 5.0 PHY Update Procedure.
|
||||
|
||||
config BT_DATA_LEN_UPDATE
|
||||
bool "Data Length Update"
|
||||
default y
|
||||
help
|
||||
Enable support for Bluetooth v4.2 LE Data Length Update procedure.
|
||||
|
||||
config BT_CONN
|
||||
# Virtual/hidden option
|
||||
bool
|
||||
|
||||
@@ -8,12 +8,22 @@
|
||||
|
||||
if BT_HCI
|
||||
|
||||
config BT_HCI_VS
|
||||
bool "Zephyr HCI Vendor-Specific Commands"
|
||||
default y
|
||||
help
|
||||
Enable support for the Zephyr HCI Vendor-Specific Commmands in the
|
||||
Host and/or Controller. This enables Set Version Information,
|
||||
Supported Commands, Supported Features vendor commands.
|
||||
|
||||
config BT_HCI_VS_EXT
|
||||
bool "Zephyr HCI Vendor-Specific Extensions"
|
||||
depends on BT_HCI_VS
|
||||
default y
|
||||
help
|
||||
Enable support for the Zephyr HCI Vendor-Specific Extensions in the
|
||||
Host and/or Controller.
|
||||
Host and/or Controller. This enables Write BD_ADDR, Read Build Info,
|
||||
Read Static Addresses and Read Key Hierarchy Roots vendor commands.
|
||||
|
||||
config BT_HCI_VS_EXT_DETECT
|
||||
bool "Use heuristics to guess HCI vendor extensions support in advance"
|
||||
|
||||
@@ -11,12 +11,14 @@
|
||||
|
||||
#include <zephyr.h>
|
||||
|
||||
#if defined(CONFIG_BT_HCI_HOST)
|
||||
/* The Bluetooth subsystem requires the Tx thread to execute at higher priority
|
||||
* than the Rx thread as the Tx thread needs to process the acknowledgements
|
||||
* before new Rx data is processed. This is a necessity to correctly detect
|
||||
* transaction violations in ATT and SMP protocols.
|
||||
*/
|
||||
BUILD_ASSERT(CONFIG_BT_HCI_TX_PRIO < CONFIG_BT_RX_PRIO);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BT_CTLR)
|
||||
/* The Bluetooth Controller's priority receive thread priority shall be higher
|
||||
|
||||
@@ -243,11 +243,10 @@ config BT_CTLR_EXT_SCAN_FP
|
||||
in the Controller.
|
||||
|
||||
config BT_CTLR_DATA_LENGTH
|
||||
bool "Data Length Update"
|
||||
# Hidden option to enable support for Bluetooth v4.2 LE Data Length
|
||||
bool
|
||||
depends on BT_DATA_LEN_UPDATE
|
||||
default y if SOC_SERIES_NRF52X
|
||||
help
|
||||
Enable support for Bluetooth v4.2 LE Data Length Update procedure in
|
||||
the Controller.
|
||||
|
||||
config BT_CTLR_DATA_LENGTH_MAX
|
||||
int "Maximum data length supported"
|
||||
@@ -259,11 +258,11 @@ config BT_CTLR_DATA_LENGTH_MAX
|
||||
Set the maximum data length of PDU supported in the Controller.
|
||||
|
||||
config BT_CTLR_PHY
|
||||
bool "PHY Update"
|
||||
# Hidden option to enable support for Bluetooth 5.0 PHY Update
|
||||
# Procedure in the Controller.
|
||||
bool
|
||||
depends on BT_PHY_UPDATE
|
||||
default y if SOC_SERIES_NRF52X
|
||||
help
|
||||
Enable support for Bluetooth 5.0 PHY Update Procedure in the
|
||||
Controller.
|
||||
|
||||
endif # BT_CONN
|
||||
|
||||
|
||||
@@ -76,8 +76,8 @@ static u64_t event_mask_page_2 = DEFAULT_EVENT_MASK_PAGE_2;
|
||||
static u64_t le_event_mask = DEFAULT_LE_EVENT_MASK;
|
||||
|
||||
#if defined(CONFIG_BT_CONN)
|
||||
static void le_conn_complete(u8_t status, struct radio_le_conn_cmplt *radio_cc,
|
||||
u16_t handle, struct net_buf *buf);
|
||||
static void le_conn_complete(struct pdu_data *pdu_data, u16_t handle,
|
||||
struct net_buf *buf);
|
||||
#endif /* CONFIG_BT_CONN */
|
||||
|
||||
static void evt_create(struct net_buf *buf, u8_t evt, u8_t len)
|
||||
@@ -1008,32 +1008,16 @@ static void le_create_connection(struct net_buf *buf, struct net_buf **evt)
|
||||
*evt = cmd_status((!status) ? 0x00 : BT_HCI_ERR_CMD_DISALLOWED);
|
||||
}
|
||||
|
||||
static void le_create_conn_cancel(struct net_buf *buf, struct net_buf **evt)
|
||||
static void le_create_conn_cancel(struct net_buf *buf, struct net_buf **evt,
|
||||
void **node_rx)
|
||||
{
|
||||
struct bt_hci_evt_cc_status *ccst;
|
||||
struct net_buf *cc;
|
||||
u8_t cmd_status;
|
||||
u32_t status;
|
||||
|
||||
status = ll_connect_disable();
|
||||
cmd_status = status ? BT_HCI_ERR_CMD_DISALLOWED : 0x00;
|
||||
|
||||
if (!cmd_status) {
|
||||
*evt = bt_buf_get_rx(BT_BUF_EVT, K_FOREVER);
|
||||
le_conn_complete(BT_HCI_ERR_UNKNOWN_CONN_ID, NULL, 0x0000,
|
||||
*evt);
|
||||
if ((*evt)->len) {
|
||||
ccst = cmd_complete(&cc, sizeof(*ccst));
|
||||
ccst->status = cmd_status;
|
||||
bt_recv_prio(cc);
|
||||
return;
|
||||
} else {
|
||||
net_buf_unref(*evt);
|
||||
}
|
||||
}
|
||||
status = ll_connect_disable(node_rx);
|
||||
|
||||
ccst = cmd_complete(evt, sizeof(*ccst));
|
||||
ccst->status = cmd_status;
|
||||
ccst->status = (!status) ? 0x00 : BT_HCI_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
static void le_set_host_chan_classif(struct net_buf *buf, struct net_buf **evt)
|
||||
@@ -1132,18 +1116,21 @@ static void le_conn_update(struct net_buf *buf, struct net_buf **evt)
|
||||
{
|
||||
struct hci_cp_le_conn_update *cmd = (void *)buf->data;
|
||||
u16_t supervision_timeout;
|
||||
u16_t conn_interval_min;
|
||||
u16_t conn_interval_max;
|
||||
u16_t conn_latency;
|
||||
u32_t status;
|
||||
u16_t handle;
|
||||
|
||||
handle = sys_le16_to_cpu(cmd->handle);
|
||||
conn_interval_min = sys_le16_to_cpu(cmd->conn_interval_min);
|
||||
conn_interval_max = sys_le16_to_cpu(cmd->conn_interval_max);
|
||||
conn_latency = sys_le16_to_cpu(cmd->conn_latency);
|
||||
supervision_timeout = sys_le16_to_cpu(cmd->supervision_timeout);
|
||||
|
||||
status = ll_conn_update(handle, 0, 0, conn_interval_max,
|
||||
conn_latency, supervision_timeout);
|
||||
status = ll_conn_update(handle, 0, 0, conn_interval_min,
|
||||
conn_interval_max, conn_latency,
|
||||
supervision_timeout);
|
||||
|
||||
*evt = cmd_status(status);
|
||||
}
|
||||
@@ -1153,6 +1140,7 @@ static void le_conn_param_req_reply(struct net_buf *buf, struct net_buf **evt)
|
||||
{
|
||||
struct bt_hci_cp_le_conn_param_req_reply *cmd = (void *)buf->data;
|
||||
struct bt_hci_rp_le_conn_param_req_reply *rp;
|
||||
u16_t interval_min;
|
||||
u16_t interval_max;
|
||||
u16_t latency;
|
||||
u16_t timeout;
|
||||
@@ -1160,12 +1148,13 @@ static void le_conn_param_req_reply(struct net_buf *buf, struct net_buf **evt)
|
||||
u16_t handle;
|
||||
|
||||
handle = sys_le16_to_cpu(cmd->handle);
|
||||
interval_min = sys_le16_to_cpu(cmd->interval_min);
|
||||
interval_max = sys_le16_to_cpu(cmd->interval_max);
|
||||
latency = sys_le16_to_cpu(cmd->latency);
|
||||
timeout = sys_le16_to_cpu(cmd->timeout);
|
||||
|
||||
status = ll_conn_update(handle, 2, 0, interval_max, latency,
|
||||
timeout);
|
||||
status = ll_conn_update(handle, 2, 0, interval_min, interval_max,
|
||||
latency, timeout);
|
||||
|
||||
rp = cmd_complete(evt, sizeof(*rp));
|
||||
rp->status = status;
|
||||
@@ -1181,7 +1170,7 @@ static void le_conn_param_req_neg_reply(struct net_buf *buf,
|
||||
u16_t handle;
|
||||
|
||||
handle = sys_le16_to_cpu(cmd->handle);
|
||||
status = ll_conn_update(handle, 2, cmd->reason, 0, 0, 0);
|
||||
status = ll_conn_update(handle, 2, cmd->reason, 0, 0, 0, 0);
|
||||
|
||||
rp = cmd_complete(evt, sizeof(*rp));
|
||||
rp->status = status;
|
||||
@@ -1513,7 +1502,7 @@ static void le_enh_tx_test(struct net_buf *buf, struct net_buf **evt)
|
||||
#endif /* CONFIG_BT_CTLR_DTM_HCI */
|
||||
|
||||
static int controller_cmd_handle(u16_t ocf, struct net_buf *cmd,
|
||||
struct net_buf **evt)
|
||||
struct net_buf **evt, void **node_rx)
|
||||
{
|
||||
switch (ocf) {
|
||||
case BT_OCF(BT_HCI_OP_LE_SET_EVENT_MASK):
|
||||
@@ -1601,7 +1590,7 @@ static int controller_cmd_handle(u16_t ocf, struct net_buf *cmd,
|
||||
break;
|
||||
|
||||
case BT_OCF(BT_HCI_OP_LE_CREATE_CONN_CANCEL):
|
||||
le_create_conn_cancel(cmd, evt);
|
||||
le_create_conn_cancel(cmd, evt, node_rx);
|
||||
break;
|
||||
|
||||
case BT_OCF(BT_HCI_OP_LE_SET_HOST_CHAN_CLASSIF):
|
||||
@@ -1741,6 +1730,7 @@ static int controller_cmd_handle(u16_t ocf, struct net_buf *cmd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_HCI_VS)
|
||||
static void vs_read_version_info(struct net_buf *buf, struct net_buf **evt)
|
||||
{
|
||||
struct bt_hci_rp_vs_read_version_info *rp;
|
||||
@@ -1951,6 +1941,31 @@ static int vendor_cmd_handle(u16_t ocf, struct net_buf *cmd,
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_BT_HCI_VS_EXT)
|
||||
uint8_t bt_read_static_addr(bt_addr_le_t *addr)
|
||||
{
|
||||
#if defined(CONFIG_SOC_FAMILY_NRF)
|
||||
if (((NRF_FICR->DEVICEADDR[0] != UINT32_MAX) ||
|
||||
((NRF_FICR->DEVICEADDR[1] & UINT16_MAX) != UINT16_MAX)) &&
|
||||
(NRF_FICR->DEVICEADDRTYPE & 0x01)) {
|
||||
sys_put_le32(NRF_FICR->DEVICEADDR[0], &addr->a.val[0]);
|
||||
sys_put_le16(NRF_FICR->DEVICEADDR[1], &addr->a.val[4]);
|
||||
|
||||
/* The FICR value is a just a random number, with no knowledge
|
||||
* of the Bluetooth Specification requirements for random
|
||||
* static addresses.
|
||||
*/
|
||||
BT_ADDR_SET_STATIC(&addr->a);
|
||||
|
||||
addr->type = BT_ADDR_LE_RANDOM;
|
||||
return 1;
|
||||
}
|
||||
#endif /* CONFIG_SOC_FAMILY_NRF */
|
||||
return 0;
|
||||
}
|
||||
#endif /* !CONFIG_BT_HCI_VS_EXT */
|
||||
|
||||
static void data_buf_overflow(struct net_buf **buf)
|
||||
{
|
||||
@@ -1967,7 +1982,7 @@ static void data_buf_overflow(struct net_buf **buf)
|
||||
ep->link_type = BT_OVERFLOW_LINK_ACL;
|
||||
}
|
||||
|
||||
struct net_buf *hci_cmd_handle(struct net_buf *cmd)
|
||||
struct net_buf *hci_cmd_handle(struct net_buf *cmd, void **node_rx)
|
||||
{
|
||||
struct bt_hci_evt_cc_status *ccst;
|
||||
struct bt_hci_cmd_hdr *chdr;
|
||||
@@ -2007,11 +2022,13 @@ struct net_buf *hci_cmd_handle(struct net_buf *cmd)
|
||||
err = status_cmd_handle(ocf, cmd, &evt);
|
||||
break;
|
||||
case BT_OGF_LE:
|
||||
err = controller_cmd_handle(ocf, cmd, &evt);
|
||||
err = controller_cmd_handle(ocf, cmd, &evt, node_rx);
|
||||
break;
|
||||
#if defined(CONFIG_BT_HCI_VS)
|
||||
case BT_OGF_VS:
|
||||
err = vendor_cmd_handle(ocf, cmd, &evt);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
err = -EINVAL;
|
||||
break;
|
||||
@@ -2379,10 +2396,12 @@ static void le_scan_req_received(struct pdu_data *pdu_data, u8_t *b,
|
||||
#endif /* CONFIG_BT_CTLR_SCAN_REQ_NOTIFY */
|
||||
|
||||
#if defined(CONFIG_BT_CONN)
|
||||
static void le_conn_complete(u8_t status, struct radio_le_conn_cmplt *radio_cc,
|
||||
u16_t handle, struct net_buf *buf)
|
||||
static void le_conn_complete(struct pdu_data *pdu_data, u16_t handle,
|
||||
struct net_buf *buf)
|
||||
{
|
||||
struct radio_le_conn_cmplt *radio_cc = (void *)pdu_data;
|
||||
struct bt_hci_evt_le_conn_complete *lecc;
|
||||
u8_t status = radio_cc->status;
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_PRIVACY)
|
||||
if (!status) {
|
||||
@@ -2506,7 +2525,7 @@ static void le_conn_update_complete(struct pdu_data *pdu_data, u16_t handle,
|
||||
return;
|
||||
}
|
||||
|
||||
radio_cu = (void *)pdu_data->lldata;
|
||||
radio_cu = (void *)pdu_data;
|
||||
|
||||
sep = meta_evt(buf, BT_HCI_EVT_LE_CONN_UPDATE_COMPLETE, sizeof(*sep));
|
||||
|
||||
@@ -2564,7 +2583,7 @@ static void le_chan_sel_algo(struct pdu_data *pdu_data, u16_t handle,
|
||||
return;
|
||||
}
|
||||
|
||||
radio_le_chan_sel_algo = (void *)pdu_data->lldata;
|
||||
radio_le_chan_sel_algo = (void *)pdu_data;
|
||||
|
||||
sep = meta_evt(buf, BT_HCI_EVT_LE_CHAN_SEL_ALGO, sizeof(*sep));
|
||||
|
||||
@@ -2580,7 +2599,7 @@ static void le_phy_upd_complete(struct pdu_data *pdu_data, u16_t handle,
|
||||
struct bt_hci_evt_le_phy_update_complete *sep;
|
||||
struct radio_le_phy_upd_cmplt *radio_le_phy_upd_cmplt;
|
||||
|
||||
radio_le_phy_upd_cmplt = (void *)pdu_data->lldata;
|
||||
radio_le_phy_upd_cmplt = (void *)pdu_data;
|
||||
|
||||
if (!(event_mask & BT_EVT_MASK_LE_META_EVENT) ||
|
||||
!(le_event_mask & BT_EVT_MASK_LE_PHY_UPDATE_COMPLETE)) {
|
||||
@@ -2632,12 +2651,7 @@ static void encode_control(struct radio_pdu_node_rx *node_rx,
|
||||
|
||||
#if defined(CONFIG_BT_CONN)
|
||||
case NODE_RX_TYPE_CONNECTION:
|
||||
{
|
||||
struct radio_le_conn_cmplt *cc;
|
||||
|
||||
cc = (void *)pdu_data->lldata;
|
||||
le_conn_complete(cc->status, cc, handle, buf);
|
||||
}
|
||||
le_conn_complete(pdu_data, handle, buf);
|
||||
break;
|
||||
|
||||
case NODE_RX_TYPE_TERMINATE:
|
||||
@@ -2809,7 +2823,7 @@ static void le_conn_param_req(struct pdu_data *pdu_data, u16_t handle,
|
||||
if (!(event_mask & BT_EVT_MASK_LE_META_EVENT) ||
|
||||
!(le_event_mask & BT_EVT_MASK_LE_CONN_PARAM_REQ)) {
|
||||
/* event masked, reject the conn param req */
|
||||
ll_conn_update(handle, 2, BT_HCI_ERR_UNSUPP_REMOTE_FEATURE,
|
||||
ll_conn_update(handle, 2, BT_HCI_ERR_UNSUPP_REMOTE_FEATURE, 0,
|
||||
0, 0, 0);
|
||||
|
||||
return;
|
||||
|
||||
@@ -348,17 +348,17 @@ static void recv_thread(void *p1, void *p2, void *p3)
|
||||
|
||||
static int cmd_handle(struct net_buf *buf)
|
||||
{
|
||||
struct bt_hci_evt_hdr *hdr;
|
||||
void *node_rx = NULL;
|
||||
struct net_buf *evt;
|
||||
|
||||
evt = hci_cmd_handle(buf);
|
||||
evt = hci_cmd_handle(buf, &node_rx);
|
||||
if (evt) {
|
||||
hdr = (void *)evt->data;
|
||||
BT_DBG("Replying with event of %u bytes", evt->len);
|
||||
if (unlikely(!bt_hci_evt_is_prio(hdr->evt))) {
|
||||
bt_recv(evt);
|
||||
} else {
|
||||
bt_recv_prio(evt);
|
||||
bt_recv_prio(evt);
|
||||
|
||||
if (node_rx) {
|
||||
BT_DBG("RX node enqueue");
|
||||
k_fifo_put(&recv_fifo, node_rx);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ extern atomic_t hci_state_mask;
|
||||
#endif /* CONFIG_SOC_FAMILY_NRF */
|
||||
|
||||
void hci_init(struct k_poll_signal *signal_host_buf);
|
||||
struct net_buf *hci_cmd_handle(struct net_buf *cmd);
|
||||
struct net_buf *hci_cmd_handle(struct net_buf *cmd, void **node_rx);
|
||||
void hci_evt_encode(struct radio_pdu_node_rx *node_rx, struct net_buf *buf);
|
||||
s8_t hci_get_class(struct radio_pdu_node_rx *node_rx);
|
||||
#if defined(CONFIG_BT_CONN)
|
||||
|
||||
@@ -54,10 +54,9 @@ u32_t ll_create_connection(u16_t scan_interval, u16_t scan_window,
|
||||
u8_t *p_peer_addr, u8_t own_addr_type,
|
||||
u16_t interval, u16_t latency,
|
||||
u16_t timeout);
|
||||
u32_t ll_connect_disable(void);
|
||||
u32_t ll_conn_update(u16_t handle, u8_t cmd, u8_t status,
|
||||
u16_t interval, u16_t latency,
|
||||
u16_t timeout);
|
||||
u32_t ll_connect_disable(void **node_rx);
|
||||
u32_t ll_conn_update(u16_t handle, u8_t cmd, u8_t status, u16_t interval_min,
|
||||
u16_t interval_max, u16_t latency, u16_t timeout);
|
||||
u32_t ll_chm_update(u8_t *chm);
|
||||
u32_t ll_chm_get(u16_t handle, u8_t *chm);
|
||||
u32_t ll_enc_req_send(u16_t handle, u8_t *rand, u8_t *ediv,
|
||||
|
||||
@@ -167,6 +167,7 @@ static struct {
|
||||
u8_t volatile ticker_id_prepare;
|
||||
u8_t volatile ticker_id_event;
|
||||
u8_t volatile ticker_id_stop;
|
||||
u8_t volatile ticker_id_upd;
|
||||
|
||||
enum role volatile role;
|
||||
enum state state;
|
||||
@@ -250,10 +251,12 @@ static u16_t const gc_lookup_ppm[] = { 500, 250, 150, 100, 75, 50, 30, 20 };
|
||||
|
||||
static void common_init(void);
|
||||
static void ticker_success_assert(u32_t status, void *params);
|
||||
static void ticker_update_adv_assert(u32_t status, void *params);
|
||||
static void ticker_stop_adv_assert(u32_t status, void *params);
|
||||
static void ticker_stop_scan_assert(u32_t status, void *params);
|
||||
static void ticker_update_adv_assert(u32_t status, void *params);
|
||||
static void ticker_update_slave_assert(u32_t status, void *params);
|
||||
static void ticker_stop_slave_assert(u32_t status, void *params);
|
||||
static void ticker_start_slave_assert(u32_t status, void *params);
|
||||
static void event_inactive(u32_t ticks_at_expire, u32_t remainder,
|
||||
u16_t lazy, void *context);
|
||||
|
||||
@@ -300,8 +303,8 @@ static u8_t conn_update(struct connection *conn, struct pdu_data *pdu_data_rx);
|
||||
static u32_t conn_update_req(struct connection *conn);
|
||||
#endif /* CONFIG_BT_CTLR_XTAL_ADVANCED && CONFIG_BT_CTLR_SCHED_ADVANCED */
|
||||
|
||||
static u32_t chan_map_update(struct connection *conn,
|
||||
struct pdu_data *pdu_data_rx);
|
||||
static u8_t chan_map_update(struct connection *conn,
|
||||
struct pdu_data *pdu_data_rx);
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_PHY)
|
||||
static inline u8_t phy_upd_ind_recv(struct radio_pdu_node_rx *node_rx,
|
||||
@@ -715,15 +718,6 @@ static inline void isr_radio_state_tx(void)
|
||||
break;
|
||||
|
||||
case ROLE_MASTER:
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_CONN_RSSI)
|
||||
if (_radio.packet_counter == 0) {
|
||||
radio_rssi_measure();
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_CONN_RSSI */
|
||||
|
||||
/* fall thru */
|
||||
|
||||
case ROLE_SLAVE:
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_PHY)
|
||||
@@ -753,6 +747,13 @@ static inline void isr_radio_state_tx(void)
|
||||
|
||||
radio_tmr_hcto_configure(hcto);
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_CONN_RSSI)
|
||||
if ((_radio.role == ROLE_MASTER) &&
|
||||
(_radio.packet_counter == 0)) {
|
||||
radio_rssi_measure();
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_CONN_RSSI */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_GPIO_LNA_PIN)
|
||||
#if defined(CONFIG_BT_CTLR_PHY)
|
||||
radio_gpio_pa_lna_enable(radio_tmr_tifs_base_get() +
|
||||
@@ -961,7 +962,6 @@ static inline u32_t isr_rx_adv(u8_t devmatch_ok, u8_t devmatch_id,
|
||||
((_radio.fc_ena == 0) || (_radio.fc_req == _radio.fc_ack)) &&
|
||||
(_radio.advertiser.conn)) {
|
||||
struct radio_le_conn_cmplt *radio_le_conn_cmplt;
|
||||
struct pdu_data *pdu_data;
|
||||
struct connection *conn;
|
||||
u32_t ticks_slot_offset;
|
||||
u32_t conn_interval_us;
|
||||
@@ -1033,8 +1033,7 @@ static inline u32_t isr_rx_adv(u8_t devmatch_ok, u8_t devmatch_id,
|
||||
node_rx->hdr.type = NODE_RX_TYPE_CONNECTION;
|
||||
|
||||
/* prepare connection complete structure */
|
||||
pdu_data = (void *)node_rx->pdu_data;
|
||||
radio_le_conn_cmplt = (void *)pdu_data->lldata;
|
||||
radio_le_conn_cmplt = (void *)node_rx->pdu_data;
|
||||
radio_le_conn_cmplt->status = 0x00;
|
||||
radio_le_conn_cmplt->role = 0x01;
|
||||
#if defined(CONFIG_BT_CTLR_PRIVACY)
|
||||
@@ -1090,8 +1089,7 @@ static inline u32_t isr_rx_adv(u8_t devmatch_ok, u8_t devmatch_id,
|
||||
node_rx->hdr.handle = conn->handle;
|
||||
node_rx->hdr.type = NODE_RX_TYPE_CHAN_SEL_ALGO;
|
||||
|
||||
pdu_data = (void *)node_rx->pdu_data;
|
||||
le_chan_sel_algo = (void *)pdu_data->lldata;
|
||||
le_chan_sel_algo = (void *)node_rx->pdu_data;
|
||||
|
||||
if (pdu_adv->chan_sel) {
|
||||
u16_t aa_ls =
|
||||
@@ -1353,7 +1351,7 @@ static inline u32_t isr_rx_scan(u8_t devmatch_ok, u8_t devmatch_id,
|
||||
struct radio_le_conn_cmplt *radio_le_conn_cmplt;
|
||||
struct radio_pdu_node_rx *node_rx;
|
||||
struct pdu_adv *pdu_adv_tx;
|
||||
struct pdu_data *pdu_data;
|
||||
u8_t pdu_adv_rx_chan_sel;
|
||||
struct connection *conn;
|
||||
u32_t ticks_slot_offset;
|
||||
u32_t conn_interval_us;
|
||||
@@ -1386,6 +1384,11 @@ static inline u32_t isr_rx_scan(u8_t devmatch_ok, u8_t devmatch_id,
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_CTLR_CHAN_SEL_2)) {
|
||||
pdu_adv_tx->chan_sel = 1;
|
||||
|
||||
/* backup, as Rx-ed buffer is used to enqueue
|
||||
* connection message.
|
||||
*/
|
||||
pdu_adv_rx_chan_sel = pdu_adv_rx->chan_sel;
|
||||
} else {
|
||||
pdu_adv_tx->chan_sel = 0;
|
||||
}
|
||||
@@ -1498,8 +1501,7 @@ static inline u32_t isr_rx_scan(u8_t devmatch_ok, u8_t devmatch_id,
|
||||
node_rx->hdr.type = NODE_RX_TYPE_CONNECTION;
|
||||
|
||||
/* prepare connection complete structure */
|
||||
pdu_data = (void *)node_rx->pdu_data;
|
||||
radio_le_conn_cmplt = (void *)pdu_data->lldata;
|
||||
radio_le_conn_cmplt = (void *)node_rx->pdu_data;
|
||||
radio_le_conn_cmplt->status = 0x00;
|
||||
radio_le_conn_cmplt->role = 0x00;
|
||||
#if defined(CONFIG_BT_CTLR_PRIVACY)
|
||||
@@ -1555,10 +1557,9 @@ static inline u32_t isr_rx_scan(u8_t devmatch_ok, u8_t devmatch_id,
|
||||
node_rx->hdr.handle = conn->handle;
|
||||
node_rx->hdr.type = NODE_RX_TYPE_CHAN_SEL_ALGO;
|
||||
|
||||
pdu_data = (void *)node_rx->pdu_data;
|
||||
le_chan_sel_algo = (void *)pdu_data->lldata;
|
||||
le_chan_sel_algo = (void *)node_rx->pdu_data;
|
||||
|
||||
if (pdu_adv_rx->chan_sel) {
|
||||
if (pdu_adv_rx_chan_sel) {
|
||||
u16_t aa_ls =
|
||||
((u16_t)conn->access_addr[1] << 8) |
|
||||
conn->access_addr[0];
|
||||
@@ -1839,7 +1840,7 @@ static inline u8_t isr_rx_conn_pkt_ack(struct pdu_data *pdu_data_tx,
|
||||
(_radio.conn_curr->llcp_length.state ==
|
||||
LLCP_LENGTH_STATE_ACK_WAIT)){
|
||||
/* pause data packet tx */
|
||||
_radio.conn_curr->pause_tx = 1;
|
||||
_radio.conn_curr->llcp_length.pause_tx = 1;
|
||||
|
||||
/* wait for response */
|
||||
_radio.conn_curr->llcp_length.state =
|
||||
@@ -1944,7 +1945,8 @@ isr_rx_conn_pkt_ctrl_rej_conn_upd(struct radio_pdu_node_rx *node_rx,
|
||||
|
||||
conn->llcp.conn_upd.win_size = 1;
|
||||
conn->llcp.conn_upd.win_offset_us = 0;
|
||||
conn->llcp.conn_upd.interval = conn->llcp_conn_param.interval;
|
||||
conn->llcp.conn_upd.interval =
|
||||
conn->llcp_conn_param.interval_max;
|
||||
conn->llcp.conn_upd.latency = conn->llcp_conn_param.latency;
|
||||
conn->llcp.conn_upd.timeout = conn->llcp_conn_param.timeout;
|
||||
/* conn->llcp.conn_upd.instant = 0; */
|
||||
@@ -1955,29 +1957,26 @@ isr_rx_conn_pkt_ctrl_rej_conn_upd(struct radio_pdu_node_rx *node_rx,
|
||||
|
||||
return;
|
||||
}
|
||||
/* Same Procedure or Different Procedure Collision */
|
||||
|
||||
/* If not same procedure, stop procedure timeout, else
|
||||
* continue timer until phy upd ind is received.
|
||||
*/
|
||||
/* FIXME: handle unsupported LL parameters error */
|
||||
else if (rej_ext_ind->error_code != BT_HCI_ERR_LL_PROC_COLLISION) {
|
||||
/* update to next ticks offsets */
|
||||
if (conn->role) {
|
||||
conn->slave.ticks_to_offset =
|
||||
conn->llcp_conn_param.ticks_to_offset_next;
|
||||
}
|
||||
}
|
||||
|
||||
if (conn->llcp_conn_param.state == LLCP_CPR_STATE_RSP_WAIT) {
|
||||
LL_ASSERT(_radio.conn_upd == conn);
|
||||
|
||||
/* reset mutex */
|
||||
_radio.conn_upd = NULL;
|
||||
|
||||
/* Procedure complete */
|
||||
conn->llcp_conn_param.ack =
|
||||
conn->llcp_conn_param.req;
|
||||
conn->llcp_conn_param.ack = conn->llcp_conn_param.req;
|
||||
|
||||
/* Stop procedure timeout */
|
||||
conn->procedure_expire = 0;
|
||||
|
||||
/* update to next ticks offsets */
|
||||
if (conn->role) {
|
||||
conn->slave.ticks_to_offset =
|
||||
conn->llcp_conn_param.ticks_to_offset_next;
|
||||
}
|
||||
}
|
||||
|
||||
/* skip event generation if not cmd initiated */
|
||||
@@ -1989,8 +1988,7 @@ isr_rx_conn_pkt_ctrl_rej_conn_upd(struct radio_pdu_node_rx *node_rx,
|
||||
node_rx->hdr.type = NODE_RX_TYPE_CONN_UPDATE;
|
||||
|
||||
/* prepare connection update complete structure */
|
||||
pdu_data_rx = (void *)node_rx->pdu_data;
|
||||
cp = (void *)pdu_data_rx->lldata;
|
||||
cp = (void *)pdu_data_rx;
|
||||
cp->status = rej_ext_ind->error_code;
|
||||
cp->interval = conn->conn_interval;
|
||||
cp->latency = conn->latency;
|
||||
@@ -2017,11 +2015,9 @@ isr_rx_conn_pkt_ctrl_rej_dle(struct radio_pdu_node_rx *node_rx,
|
||||
|
||||
/* Procedure complete */
|
||||
conn->llcp_length.ack = conn->llcp_length.req;
|
||||
conn->llcp_length.pause_tx = 0;
|
||||
conn->procedure_expire = 0;
|
||||
|
||||
/* Resume data packet tx */
|
||||
conn->pause_tx = 0;
|
||||
|
||||
/* prepare length rsp structure */
|
||||
pdu_data_rx->len = offsetof(struct pdu_data_llctrl,
|
||||
length_rsp) +
|
||||
@@ -2084,7 +2080,7 @@ isr_rx_conn_pkt_ctrl_rej_phy_upd(struct radio_pdu_node_rx *node_rx,
|
||||
/* generate phy update complete event with error code */
|
||||
node_rx->hdr.type = NODE_RX_TYPE_PHY_UPDATE;
|
||||
|
||||
p = (void *)pdu_data_rx->lldata;
|
||||
p = (void *)pdu_data_rx;
|
||||
p->status = rej_ext_ind->error_code;
|
||||
p->tx = _radio.conn_curr->phy_tx;
|
||||
p->rx = _radio.conn_curr->phy_rx;
|
||||
@@ -2295,11 +2291,9 @@ static inline u8_t isr_rx_conn_pkt_ctrl_dle(struct pdu_data *pdu_data_rx,
|
||||
/* Procedure complete */
|
||||
_radio.conn_curr->llcp_length.ack =
|
||||
_radio.conn_curr->llcp_length.req;
|
||||
_radio.conn_curr->llcp_length.pause_tx = 0;
|
||||
_radio.conn_curr->procedure_expire = 0;
|
||||
|
||||
/* resume data packet tx */
|
||||
_radio.conn_curr->pause_tx = 0;
|
||||
|
||||
/* No change in effective octets or time */
|
||||
if (eff_tx_octets == _radio.conn_curr->max_tx_octets &&
|
||||
#if defined(CONFIG_BT_CTLR_PHY)
|
||||
@@ -2453,17 +2447,21 @@ isr_rx_conn_pkt_ctrl(struct radio_pdu_node_rx *node_rx, u8_t *rx_enqueue)
|
||||
break;
|
||||
|
||||
case PDU_DATA_LLCTRL_TYPE_CHAN_MAP_IND:
|
||||
{
|
||||
u8_t err;
|
||||
|
||||
if (!_radio.conn_curr->role ||
|
||||
!pdu_len_cmp(PDU_DATA_LLCTRL_TYPE_CHAN_MAP_IND,
|
||||
pdu_data_rx->len)) {
|
||||
goto isr_rx_conn_unknown_rsp_send;
|
||||
}
|
||||
|
||||
if (chan_map_update(_radio.conn_curr, pdu_data_rx)) {
|
||||
_radio.conn_curr->llcp_terminate.reason_peer =
|
||||
BT_HCI_ERR_INSTANT_PASSED;
|
||||
err = chan_map_update(_radio.conn_curr, pdu_data_rx);
|
||||
if (err) {
|
||||
_radio.conn_curr->llcp_terminate.reason_peer = err;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case PDU_DATA_LLCTRL_TYPE_TERMINATE_IND:
|
||||
if (!pdu_len_cmp(PDU_DATA_LLCTRL_TYPE_TERMINATE_IND,
|
||||
@@ -2769,7 +2767,10 @@ isr_rx_conn_pkt_ctrl(struct radio_pdu_node_rx *node_rx, u8_t *rx_enqueue)
|
||||
|
||||
/* save parameters to be used to select offset
|
||||
*/
|
||||
conn->llcp_conn_param.interval = cpr->interval_min;
|
||||
conn->llcp_conn_param.interval_min =
|
||||
cpr->interval_min;
|
||||
conn->llcp_conn_param.interval_max =
|
||||
cpr->interval_max;
|
||||
conn->llcp_conn_param.latency = cpr->latency;
|
||||
conn->llcp_conn_param.timeout = cpr->timeout;
|
||||
conn->llcp_conn_param.preferred_periodicity =
|
||||
@@ -2786,7 +2787,7 @@ isr_rx_conn_pkt_ctrl(struct radio_pdu_node_rx *node_rx, u8_t *rx_enqueue)
|
||||
/* enqueue the conn param req, if parameters
|
||||
* changed, else respond.
|
||||
*/
|
||||
if ((conn->llcp_conn_param.interval !=
|
||||
if ((conn->llcp_conn_param.interval_max !=
|
||||
conn->conn_interval) ||
|
||||
(conn->llcp_conn_param.latency !=
|
||||
conn->latency) ||
|
||||
@@ -2849,7 +2850,8 @@ isr_rx_conn_pkt_ctrl(struct radio_pdu_node_rx *node_rx, u8_t *rx_enqueue)
|
||||
/* resp to be generated by app, for now save
|
||||
* parameters
|
||||
*/
|
||||
conn->llcp_conn_param.interval = cpr->interval_min;
|
||||
conn->llcp_conn_param.interval_min = cpr->interval_min;
|
||||
conn->llcp_conn_param.interval_max = cpr->interval_max;
|
||||
conn->llcp_conn_param.latency = cpr->latency;
|
||||
conn->llcp_conn_param.timeout = cpr->timeout;
|
||||
conn->llcp_conn_param.preferred_periodicity =
|
||||
@@ -2866,7 +2868,7 @@ isr_rx_conn_pkt_ctrl(struct radio_pdu_node_rx *node_rx, u8_t *rx_enqueue)
|
||||
/* enqueue the conn param req, if parameters changed,
|
||||
* else respond
|
||||
*/
|
||||
if ((conn->llcp_conn_param.interval !=
|
||||
if ((conn->llcp_conn_param.interval_max !=
|
||||
conn->conn_interval) ||
|
||||
(conn->llcp_conn_param.latency != conn->latency) ||
|
||||
(RADIO_CONN_EVENTS(conn->llcp_conn_param.timeout *
|
||||
@@ -2932,7 +2934,8 @@ isr_rx_conn_pkt_ctrl(struct radio_pdu_node_rx *node_rx, u8_t *rx_enqueue)
|
||||
|
||||
/* save parameters to be used to select offset
|
||||
*/
|
||||
conn->llcp_conn_param.interval = cpr->interval_min;
|
||||
conn->llcp_conn_param.interval_min = cpr->interval_min;
|
||||
conn->llcp_conn_param.interval_max = cpr->interval_max;
|
||||
conn->llcp_conn_param.latency = cpr->latency;
|
||||
conn->llcp_conn_param.timeout = cpr->timeout;
|
||||
conn->llcp_conn_param.preferred_periodicity =
|
||||
@@ -3008,7 +3011,7 @@ isr_rx_conn_pkt_ctrl(struct radio_pdu_node_rx *node_rx, u8_t *rx_enqueue)
|
||||
conn->llcp.conn_upd.win_size = 1;
|
||||
conn->llcp.conn_upd.win_offset_us = 0;
|
||||
conn->llcp.conn_upd.interval =
|
||||
conn->llcp_conn_param.interval;
|
||||
conn->llcp_conn_param.interval_max;
|
||||
conn->llcp.conn_upd.latency =
|
||||
conn->llcp_conn_param.latency;
|
||||
conn->llcp.conn_upd.timeout =
|
||||
@@ -3040,8 +3043,7 @@ isr_rx_conn_pkt_ctrl(struct radio_pdu_node_rx *node_rx, u8_t *rx_enqueue)
|
||||
node_rx->hdr.type = NODE_RX_TYPE_CONN_UPDATE;
|
||||
|
||||
/* prepare connection update complete structure */
|
||||
pdu_data_rx = (void *)node_rx->pdu_data;
|
||||
cp = (void *)pdu_data_rx->lldata;
|
||||
cp = (void *)pdu_data_rx;
|
||||
cp->status = BT_HCI_ERR_UNSUPP_REMOTE_FEATURE;
|
||||
cp->interval = conn->conn_interval;
|
||||
cp->latency = conn->latency;
|
||||
@@ -3057,9 +3059,7 @@ isr_rx_conn_pkt_ctrl(struct radio_pdu_node_rx *node_rx, u8_t *rx_enqueue)
|
||||
/* Procedure complete */
|
||||
_radio.conn_curr->llcp_length.ack =
|
||||
_radio.conn_curr->llcp_length.req;
|
||||
|
||||
/* resume data packet tx */
|
||||
_radio.conn_curr->pause_tx = 0;
|
||||
_radio.conn_curr->llcp_length.pause_tx = 0;
|
||||
|
||||
/* propagate the data length procedure to
|
||||
* host
|
||||
@@ -3085,7 +3085,7 @@ isr_rx_conn_pkt_ctrl(struct radio_pdu_node_rx *node_rx, u8_t *rx_enqueue)
|
||||
/* generate phy update complete event */
|
||||
node_rx->hdr.type = NODE_RX_TYPE_PHY_UPDATE;
|
||||
|
||||
p = (void *)pdu_data_rx->lldata;
|
||||
p = (void *)pdu_data_rx;
|
||||
p->status = 0;
|
||||
p->tx = _radio.conn_curr->phy_tx;
|
||||
p->rx = _radio.conn_curr->phy_rx;
|
||||
@@ -4463,6 +4463,14 @@ static void ticker_success_assert(u32_t status, void *params)
|
||||
LL_ASSERT(status == TICKER_STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
static void ticker_update_adv_assert(u32_t status, void *params)
|
||||
{
|
||||
ARG_UNUSED(params);
|
||||
|
||||
LL_ASSERT((status == TICKER_STATUS_SUCCESS) ||
|
||||
(_radio.ticker_id_stop == RADIO_TICKER_ID_ADV));
|
||||
}
|
||||
|
||||
static void ticker_stop_adv_assert(u32_t status, void *params)
|
||||
{
|
||||
ARG_UNUSED(params);
|
||||
@@ -4513,20 +4521,27 @@ static void ticker_stop_scan_assert(u32_t status, void *params)
|
||||
}
|
||||
}
|
||||
|
||||
static void ticker_update_adv_assert(u32_t status, void *params)
|
||||
{
|
||||
ARG_UNUSED(params);
|
||||
|
||||
LL_ASSERT((status == TICKER_STATUS_SUCCESS) ||
|
||||
(_radio.ticker_id_stop == RADIO_TICKER_ID_ADV));
|
||||
}
|
||||
|
||||
static void ticker_update_slave_assert(u32_t status, void *params)
|
||||
{
|
||||
u8_t ticker_id = (u32_t)params & 0xFF;
|
||||
|
||||
LL_ASSERT((status == TICKER_STATUS_SUCCESS) ||
|
||||
(_radio.ticker_id_stop == ticker_id));
|
||||
(_radio.ticker_id_stop == ticker_id) ||
|
||||
(_radio.ticker_id_upd == ticker_id));
|
||||
}
|
||||
|
||||
static void ticker_stop_slave_assert(u32_t status, void *params)
|
||||
{
|
||||
LL_ASSERT(status == TICKER_STATUS_SUCCESS);
|
||||
|
||||
_radio.ticker_id_upd = (u8_t)((u32_t)params & 0xFF);
|
||||
}
|
||||
|
||||
static void ticker_start_slave_assert(u32_t status, void *params)
|
||||
{
|
||||
LL_ASSERT(status == TICKER_STATUS_SUCCESS);
|
||||
|
||||
_radio.ticker_id_upd = 0;
|
||||
}
|
||||
|
||||
static void mayfly_radio_active(void *params)
|
||||
@@ -4886,9 +4901,15 @@ static void mayfly_xtal_stop_calc(void *params)
|
||||
|
||||
/* Compensate for next ticker in reduced prepare */
|
||||
if (hdr_next->ticks_xtal_to_start & XON_BITMASK) {
|
||||
ticks_to_expire -=
|
||||
(hdr_next->ticks_xtal_to_start &
|
||||
~XON_BITMASK) - ticks_prepare_to_start_next;
|
||||
u32_t ticks_reduced = (hdr_next->ticks_xtal_to_start &
|
||||
~XON_BITMASK) -
|
||||
ticks_prepare_to_start_next;
|
||||
|
||||
if (ticks_to_expire > ticks_reduced) {
|
||||
ticks_to_expire -= ticks_reduced;
|
||||
} else {
|
||||
ticks_to_expire = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* If beyond the xtal threshold reset to normal the next prepare,
|
||||
@@ -5356,7 +5377,8 @@ static void mayfly_sched_free_win_offset_calc(void *params)
|
||||
}
|
||||
|
||||
sched_free_win_offset_calc(conn, 0, ticks_to_offset_next,
|
||||
conn->llcp_conn_param.interval, &offset_max,
|
||||
conn->llcp_conn_param.interval_max,
|
||||
&offset_max,
|
||||
(u8_t *)conn->llcp_conn_param.pdu_win_offset0);
|
||||
}
|
||||
|
||||
@@ -5376,7 +5398,7 @@ static void mayfly_sched_win_offset_select(void *params)
|
||||
1250);
|
||||
|
||||
sched_free_win_offset_calc(conn, 1, &ticks_to_offset,
|
||||
conn->llcp_conn_param.interval,
|
||||
conn->llcp_conn_param.interval_max,
|
||||
&offset_m_max, (u8_t *)&win_offset_m[0]);
|
||||
|
||||
while (offset_index_s < OFFSET_S_MAX) {
|
||||
@@ -6209,7 +6231,6 @@ static void mayfly_adv_stop(void *param)
|
||||
{
|
||||
struct radio_le_conn_cmplt *radio_le_conn_cmplt;
|
||||
struct radio_pdu_node_rx *node_rx;
|
||||
struct pdu_data *pdu_data_rx;
|
||||
|
||||
/* Prepare the rx packet structure */
|
||||
node_rx = packet_rx_reserve_get(1);
|
||||
@@ -6220,8 +6241,7 @@ static void mayfly_adv_stop(void *param)
|
||||
node_rx->hdr.type = NODE_RX_TYPE_CONNECTION;
|
||||
|
||||
/* prepare connection complete structure */
|
||||
pdu_data_rx = (void *)node_rx->pdu_data;
|
||||
radio_le_conn_cmplt = (void *)pdu_data_rx->lldata;
|
||||
radio_le_conn_cmplt = (void *)node_rx->pdu_data;
|
||||
memset(radio_le_conn_cmplt, 0x00, sizeof(struct radio_le_conn_cmplt));
|
||||
radio_le_conn_cmplt->status = BT_HCI_ERR_ADV_TIMEOUT;
|
||||
|
||||
@@ -6718,18 +6738,18 @@ static inline u32_t event_conn_upd_prep(struct connection *conn,
|
||||
ctrl_tx_enqueue(conn, node_tx);
|
||||
|
||||
} else if (instant_latency <= 0x7FFF) {
|
||||
struct radio_pdu_node_rx *node_rx;
|
||||
struct pdu_data *pdu_data_rx;
|
||||
struct radio_le_conn_update_cmplt *radio_le_conn_update_cmplt;
|
||||
u32_t ticker_status;
|
||||
u32_t conn_interval_us;
|
||||
u32_t periodic_us;
|
||||
u32_t ticks_win_offset;
|
||||
u32_t ticks_slot_offset;
|
||||
struct radio_pdu_node_rx *node_rx;
|
||||
u32_t mayfly_was_enabled;
|
||||
u16_t conn_interval_old;
|
||||
u16_t conn_interval_new;
|
||||
u32_t ticks_slot_offset;
|
||||
u32_t ticks_win_offset;
|
||||
u32_t conn_interval_us;
|
||||
u32_t ticker_status;
|
||||
u32_t periodic_us;
|
||||
u8_t ticker_id;
|
||||
u16_t latency;
|
||||
u32_t mayfly_was_enabled;
|
||||
|
||||
/* procedure request acked */
|
||||
conn->llcp_ack = conn->llcp_req;
|
||||
@@ -6769,11 +6789,8 @@ static inline u32_t event_conn_upd_prep(struct connection *conn,
|
||||
node_rx->hdr.type = NODE_RX_TYPE_CONN_UPDATE;
|
||||
|
||||
/* prepare connection update complete structure */
|
||||
pdu_data_rx = (void *)node_rx->pdu_data;
|
||||
radio_le_conn_update_cmplt = (void *)
|
||||
pdu_data_rx->lldata;
|
||||
radio_le_conn_update_cmplt->status =
|
||||
0x00;
|
||||
radio_le_conn_update_cmplt = (void *) node_rx->pdu_data;
|
||||
radio_le_conn_update_cmplt->status = 0x00;
|
||||
radio_le_conn_update_cmplt->interval =
|
||||
conn->llcp.conn_upd.interval;
|
||||
radio_le_conn_update_cmplt->latency =
|
||||
@@ -6896,19 +6913,17 @@ static inline u32_t event_conn_upd_prep(struct connection *conn,
|
||||
RADIO_TICKER_USER_ID_JOB, 0);
|
||||
|
||||
/* start slave/master with new timings */
|
||||
ticker_id = RADIO_TICKER_ID_FIRST_CONNECTION + conn->handle;
|
||||
ticker_status =
|
||||
ticker_stop(RADIO_TICKER_INSTANCE_ID_RADIO,
|
||||
RADIO_TICKER_USER_ID_WORKER,
|
||||
RADIO_TICKER_ID_FIRST_CONNECTION +
|
||||
conn->handle, ticker_success_assert,
|
||||
(void *)__LINE__);
|
||||
RADIO_TICKER_USER_ID_WORKER, ticker_id,
|
||||
ticker_stop_slave_assert,
|
||||
(void *)(u32_t)ticker_id);
|
||||
LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) ||
|
||||
(ticker_status == TICKER_STATUS_BUSY));
|
||||
ticker_status =
|
||||
ticker_start(RADIO_TICKER_INSTANCE_ID_RADIO,
|
||||
RADIO_TICKER_USER_ID_WORKER,
|
||||
RADIO_TICKER_ID_FIRST_CONNECTION +
|
||||
conn->handle,
|
||||
RADIO_TICKER_USER_ID_WORKER, ticker_id,
|
||||
ticks_at_expire, ticks_win_offset,
|
||||
HAL_TICKER_US_TO_TICKS(periodic_us),
|
||||
HAL_TICKER_REMAINDER(periodic_us),
|
||||
@@ -6916,8 +6931,8 @@ static inline u32_t event_conn_upd_prep(struct connection *conn,
|
||||
(ticks_slot_offset + conn->hdr.ticks_slot),
|
||||
conn->role ?
|
||||
event_slave_prepare : event_master_prepare,
|
||||
conn, ticker_success_assert,
|
||||
(void *)__LINE__);
|
||||
conn, ticker_start_slave_assert,
|
||||
(void *)(u32_t)ticker_id);
|
||||
LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) ||
|
||||
(ticker_status == TICKER_STATUS_BUSY));
|
||||
|
||||
@@ -7157,6 +7172,42 @@ static inline void event_fex_prep(struct connection *conn)
|
||||
{
|
||||
struct radio_pdu_node_tx *node_tx;
|
||||
|
||||
if (conn->common.fex_valid) {
|
||||
struct radio_pdu_node_rx *node_rx;
|
||||
struct pdu_data *pdu_ctrl_rx;
|
||||
|
||||
/* procedure request acked */
|
||||
conn->llcp_ack = conn->llcp_req;
|
||||
|
||||
/* Prepare the rx packet structure */
|
||||
node_rx = packet_rx_reserve_get(2);
|
||||
LL_ASSERT(node_rx);
|
||||
|
||||
node_rx->hdr.handle = conn->handle;
|
||||
node_rx->hdr.type = NODE_RX_TYPE_DC_PDU;
|
||||
|
||||
/* prepare feature rsp structure */
|
||||
pdu_ctrl_rx = (void *)node_rx->pdu_data;
|
||||
pdu_ctrl_rx->ll_id = PDU_DATA_LLID_CTRL;
|
||||
pdu_ctrl_rx->len = offsetof(struct pdu_data_llctrl,
|
||||
feature_rsp) +
|
||||
sizeof(struct pdu_data_llctrl_feature_rsp);
|
||||
pdu_ctrl_rx->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_FEATURE_RSP;
|
||||
(void)memset(&pdu_ctrl_rx->llctrl.feature_rsp.features[0], 0x00,
|
||||
sizeof(pdu_ctrl_rx->llctrl.feature_rsp.features));
|
||||
pdu_ctrl_rx->llctrl.feature_req.features[0] =
|
||||
conn->llcp_features & 0xFF;
|
||||
pdu_ctrl_rx->llctrl.feature_req.features[1] =
|
||||
(conn->llcp_features >> 8) & 0xFF;
|
||||
pdu_ctrl_rx->llctrl.feature_req.features[2] =
|
||||
(conn->llcp_features >> 16) & 0xFF;
|
||||
|
||||
/* enqueue feature rsp structure into rx queue */
|
||||
packet_rx_enqueue();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
node_tx = mem_acquire(&_radio.pkt_tx_ctrl_free);
|
||||
if (node_tx) {
|
||||
struct pdu_data *pdu_ctrl_tx = (void *)node_tx->pdu_data;
|
||||
@@ -7295,8 +7346,8 @@ static inline void event_conn_param_req(struct connection *conn,
|
||||
sizeof(struct pdu_data_llctrl_conn_param_req);
|
||||
pdu_ctrl_tx->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ;
|
||||
p = (void *)&pdu_ctrl_tx->llctrl.conn_param_req;
|
||||
p->interval_min = conn->llcp_conn_param.interval;
|
||||
p->interval_max = conn->llcp_conn_param.interval;
|
||||
p->interval_min = conn->llcp_conn_param.interval_min;
|
||||
p->interval_max = conn->llcp_conn_param.interval_max;
|
||||
p->latency = conn->llcp_conn_param.latency;
|
||||
p->timeout = conn->llcp_conn_param.timeout;
|
||||
p->preferred_periodicity = 0;
|
||||
@@ -7404,13 +7455,13 @@ static inline void event_conn_param_rsp(struct connection *conn)
|
||||
conn->llcp.conn_upd.win_offset_us = 0;
|
||||
if (conn->llcp_conn_param.preferred_periodicity) {
|
||||
conn->llcp.conn_upd.interval =
|
||||
((conn->llcp_conn_param.interval /
|
||||
((conn->llcp_conn_param.interval_min /
|
||||
conn->llcp_conn_param.preferred_periodicity) +
|
||||
1) *
|
||||
conn->llcp_conn_param.preferred_periodicity;
|
||||
} else {
|
||||
conn->llcp.conn_upd.interval =
|
||||
conn->llcp_conn_param.interval;
|
||||
conn->llcp_conn_param.interval_max;
|
||||
}
|
||||
conn->llcp.conn_upd.latency = conn->llcp_conn_param.latency;
|
||||
conn->llcp.conn_upd.timeout = conn->llcp_conn_param.timeout;
|
||||
@@ -7436,8 +7487,8 @@ static inline void event_conn_param_rsp(struct connection *conn)
|
||||
sizeof(struct pdu_data_llctrl_conn_param_rsp);
|
||||
pdu->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_CONN_PARAM_RSP;
|
||||
rsp = (void *)&pdu->llctrl.conn_param_rsp;
|
||||
rsp->interval_min = conn->llcp_conn_param.interval;
|
||||
rsp->interval_max = conn->llcp_conn_param.interval;
|
||||
rsp->interval_min = conn->llcp_conn_param.interval_min;
|
||||
rsp->interval_max = conn->llcp_conn_param.interval_max;
|
||||
rsp->latency = conn->llcp_conn_param.latency;
|
||||
rsp->timeout = conn->llcp_conn_param.timeout;
|
||||
rsp->preferred_periodicity =
|
||||
@@ -7491,8 +7542,8 @@ static inline void event_conn_param_app_req(struct connection *conn)
|
||||
sizeof(struct pdu_data_llctrl_conn_param_req);
|
||||
pdu->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ;
|
||||
p = (void *) &pdu->llctrl.conn_param_req;
|
||||
p->interval_min = conn->llcp_conn_param.interval;
|
||||
p->interval_max = conn->llcp_conn_param.interval;
|
||||
p->interval_min = conn->llcp_conn_param.interval_min;
|
||||
p->interval_max = conn->llcp_conn_param.interval_max;
|
||||
p->latency = conn->llcp_conn_param.latency;
|
||||
p->timeout = conn->llcp_conn_param.timeout;
|
||||
|
||||
@@ -7655,11 +7706,9 @@ static inline void event_len_prep(struct connection *conn)
|
||||
|
||||
/* Procedure complete */
|
||||
conn->llcp_length.ack = conn->llcp_length.req;
|
||||
conn->llcp_length.pause_tx = 0;
|
||||
conn->procedure_expire = 0;
|
||||
|
||||
/* resume data packet tx */
|
||||
_radio.conn_curr->pause_tx = 0;
|
||||
|
||||
/* Use the new rx octets/time in the connection */
|
||||
conn->max_rx_octets = conn->llcp_length.rx_octets;
|
||||
|
||||
@@ -7834,6 +7883,11 @@ static inline void event_phy_req_prep(struct connection *conn)
|
||||
|
||||
case LLCP_PHY_STATE_UPD:
|
||||
{
|
||||
/* Defer if another procedure in progress */
|
||||
if (conn->llcp_ack != conn->llcp_req) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Procedure complete */
|
||||
conn->llcp_phy.ack = conn->llcp_phy.req;
|
||||
|
||||
@@ -7919,7 +7973,6 @@ static inline void event_phy_upd_ind_prep(struct connection *conn,
|
||||
/* generate phy update event */
|
||||
if (conn->llcp.phy_upd_ind.cmd) {
|
||||
struct radio_pdu_node_rx *node_rx;
|
||||
struct pdu_data *pdu_data;
|
||||
|
||||
node_rx = packet_rx_reserve_get(2);
|
||||
LL_ASSERT(node_rx);
|
||||
@@ -7928,8 +7981,7 @@ static inline void event_phy_upd_ind_prep(struct connection *conn,
|
||||
node_rx->hdr.type =
|
||||
NODE_RX_TYPE_PHY_UPDATE;
|
||||
|
||||
pdu_data = (void *)&node_rx->pdu_data;
|
||||
upd = (void *)pdu_data->lldata;
|
||||
upd = (void *)&node_rx->pdu_data;
|
||||
upd->status = 0;
|
||||
upd->tx = conn->phy_tx;
|
||||
upd->rx = conn->phy_rx;
|
||||
@@ -7962,7 +8014,6 @@ static inline void event_phy_upd_ind_prep(struct connection *conn,
|
||||
} else if (((event_counter - conn->llcp.phy_upd_ind.instant) & 0xFFFF)
|
||||
<= 0x7FFF) {
|
||||
struct radio_pdu_node_rx *node_rx;
|
||||
struct pdu_data *pdu_data;
|
||||
u8_t old_tx, old_rx;
|
||||
|
||||
/* procedure request acked */
|
||||
@@ -7991,8 +8042,7 @@ static inline void event_phy_upd_ind_prep(struct connection *conn,
|
||||
node_rx->hdr.handle = conn->handle;
|
||||
node_rx->hdr.type = NODE_RX_TYPE_PHY_UPDATE;
|
||||
|
||||
pdu_data = (void *)&node_rx->pdu_data;
|
||||
upd = (void *)pdu_data->lldata;
|
||||
upd = (void *)&node_rx->pdu_data;
|
||||
upd->status = 0;
|
||||
upd->tx = conn->phy_tx;
|
||||
upd->rx = conn->phy_rx;
|
||||
@@ -8642,7 +8692,11 @@ static void prepare_pdu_data_tx(struct connection *conn,
|
||||
/* no ctrl or data packet */
|
||||
!conn->pkt_tx_head ||
|
||||
/* data tx paused, only control packets allowed */
|
||||
(conn->pause_tx && (conn->pkt_tx_head != conn->pkt_tx_ctrl))) {
|
||||
((conn->pause_tx ||
|
||||
#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
|
||||
conn->llcp_length.pause_tx ||
|
||||
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
|
||||
0) && (conn->pkt_tx_head != conn->pkt_tx_ctrl))) {
|
||||
_pdu_data_tx = empty_tx_enqueue(conn);
|
||||
} else {
|
||||
u16_t max_tx_octets;
|
||||
@@ -9253,7 +9307,8 @@ static u32_t conn_update_req(struct connection *conn)
|
||||
BIT(BT_LE_FEAT_BIT_CONN_PARAM_REQ)))) {
|
||||
/** Perform slave intiated conn param req */
|
||||
conn->llcp_conn_param.status = 0;
|
||||
conn->llcp_conn_param.interval = conn->conn_interval;
|
||||
conn->llcp_conn_param.interval_min = conn->conn_interval;
|
||||
conn->llcp_conn_param.interval_max = conn->conn_interval;
|
||||
conn->llcp_conn_param.latency = conn->latency;
|
||||
conn->llcp_conn_param.timeout = conn->conn_interval *
|
||||
conn->supervision_reload *
|
||||
@@ -9271,15 +9326,19 @@ static u32_t conn_update_req(struct connection *conn)
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_XTAL_ADVANCED && CONFIG_BT_CTLR_SCHED_ADVANCED */
|
||||
|
||||
static u32_t chan_map_update(struct connection *conn,
|
||||
struct pdu_data *pdu_data_rx)
|
||||
static u8_t chan_map_update(struct connection *conn,
|
||||
struct pdu_data *pdu_data_rx)
|
||||
{
|
||||
if (((pdu_data_rx->llctrl.chan_map_ind.instant -
|
||||
conn->event_counter) & 0xffff) > 0x7fff) {
|
||||
return 1;
|
||||
return BT_HCI_ERR_INSTANT_PASSED;
|
||||
}
|
||||
|
||||
/* different transaction collision */
|
||||
if (conn->llcp_req != conn->llcp_ack) {
|
||||
return BT_HCI_ERR_DIFF_TRANS_COLLISION;
|
||||
}
|
||||
|
||||
LL_ASSERT(conn->llcp_req == conn->llcp_ack);
|
||||
|
||||
memcpy(&conn->llcp.chan_map.chm[0],
|
||||
&pdu_data_rx->llctrl.chan_map_ind.chm[0],
|
||||
@@ -9327,7 +9386,7 @@ static inline u8_t phy_upd_ind_recv(struct radio_pdu_node_rx *node_rx,
|
||||
/* generate phy update complete event */
|
||||
node_rx->hdr.type = NODE_RX_TYPE_PHY_UPDATE;
|
||||
|
||||
upd = (void *)pdu_data_rx->lldata;
|
||||
upd = (void *)pdu_data_rx;
|
||||
upd->status = 0;
|
||||
upd->tx = conn->phy_tx;
|
||||
upd->rx = conn->phy_rx;
|
||||
@@ -10162,6 +10221,7 @@ u32_t radio_adv_enable(u16_t interval, u8_t chan_map, u8_t filter_policy,
|
||||
#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
|
||||
conn->llcp_length.req = 0;
|
||||
conn->llcp_length.ack = 0;
|
||||
conn->llcp_length.pause_tx = 0;
|
||||
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_PHY)
|
||||
@@ -10473,33 +10533,25 @@ u32_t radio_scan_enable(u8_t type, u8_t init_addr_type, u8_t *init_addr,
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32_t radio_scan_disable(void)
|
||||
u32_t radio_scan_disable(bool scanner)
|
||||
{
|
||||
u32_t status;
|
||||
|
||||
if (scanner && _radio.scanner.conn) {
|
||||
return BT_HCI_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
status = role_disable(RADIO_TICKER_ID_SCAN,
|
||||
RADIO_TICKER_ID_SCAN_STOP);
|
||||
if (!status) {
|
||||
struct connection *conn;
|
||||
|
||||
if (!status && !_radio.scanner.conn) {
|
||||
_radio.scanner.is_enabled = 0;
|
||||
|
||||
if (!_radio.advertiser.is_enabled) {
|
||||
ll_adv_scan_state_cb(0);
|
||||
}
|
||||
|
||||
conn = _radio.scanner.conn;
|
||||
if (conn) {
|
||||
_radio.scanner.conn = NULL;
|
||||
|
||||
mem_release(conn->llcp_terminate.
|
||||
radio_pdu_node_rx.hdr.onion.link,
|
||||
&_radio.link_rx_free);
|
||||
mem_release(conn, &_radio.conn_free);
|
||||
}
|
||||
}
|
||||
|
||||
return status ? BT_HCI_ERR_CMD_DISALLOWED : 0;
|
||||
return _radio.scanner.is_enabled ? BT_HCI_ERR_CMD_DISALLOWED : 0;
|
||||
}
|
||||
|
||||
u32_t ll_scan_is_enabled(void)
|
||||
@@ -10644,6 +10696,7 @@ u32_t radio_connect_enable(u8_t adv_addr_type, u8_t *adv_addr, u16_t interval,
|
||||
#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
|
||||
conn->llcp_length.req = 0;
|
||||
conn->llcp_length.ack = 0;
|
||||
conn->llcp_length.pause_tx = 0;
|
||||
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_PHY)
|
||||
@@ -10681,7 +10734,7 @@ u32_t radio_connect_enable(u8_t adv_addr_type, u8_t *adv_addr, u16_t interval,
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32_t ll_connect_disable(void)
|
||||
u32_t ll_connect_disable(void **node_rx)
|
||||
{
|
||||
u32_t status;
|
||||
|
||||
@@ -10689,13 +10742,27 @@ u32_t ll_connect_disable(void)
|
||||
return BT_HCI_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
status = radio_scan_disable();
|
||||
status = radio_scan_disable(false);
|
||||
if (!status) {
|
||||
struct connection *conn = _radio.scanner.conn;
|
||||
struct radio_pdu_node_rx *rx;
|
||||
|
||||
rx = (void *)&conn->llcp_terminate.radio_pdu_node_rx;
|
||||
|
||||
/* free the memq link early, as caller could overwrite it */
|
||||
mem_release(rx->hdr.onion.link, &_radio.link_rx_free);
|
||||
|
||||
rx->hdr.type = NODE_RX_TYPE_CONNECTION;
|
||||
rx->hdr.handle = 0xffff;
|
||||
*((u8_t *)rx->pdu_data) = BT_HCI_ERR_UNKNOWN_CONN_ID;
|
||||
*node_rx = rx;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
u32_t ll_conn_update(u16_t handle, u8_t cmd, u8_t status, u16_t interval,
|
||||
u16_t latency, u16_t timeout)
|
||||
u32_t ll_conn_update(u16_t handle, u8_t cmd, u8_t status, u16_t interval_min,
|
||||
u16_t interval_max, u16_t latency, u16_t timeout)
|
||||
{
|
||||
struct connection *conn;
|
||||
|
||||
@@ -10728,7 +10795,7 @@ u32_t ll_conn_update(u16_t handle, u8_t cmd, u8_t status, u16_t interval,
|
||||
|
||||
conn->llcp.conn_upd.win_size = 1;
|
||||
conn->llcp.conn_upd.win_offset_us = 0;
|
||||
conn->llcp.conn_upd.interval = interval;
|
||||
conn->llcp.conn_upd.interval = interval_max;
|
||||
conn->llcp.conn_upd.latency = latency;
|
||||
conn->llcp.conn_upd.timeout = timeout;
|
||||
/* conn->llcp.conn_upd.instant = 0; */
|
||||
@@ -10759,7 +10826,8 @@ u32_t ll_conn_update(u16_t handle, u8_t cmd, u8_t status, u16_t interval,
|
||||
}
|
||||
|
||||
conn->llcp_conn_param.status = 0;
|
||||
conn->llcp_conn_param.interval = interval;
|
||||
conn->llcp_conn_param.interval_min = interval_min;
|
||||
conn->llcp_conn_param.interval_max = interval_max;
|
||||
conn->llcp_conn_param.latency = latency;
|
||||
conn->llcp_conn_param.timeout = timeout;
|
||||
conn->llcp_conn_param.state = cmd;
|
||||
@@ -11323,11 +11391,9 @@ void ll_rx_dequeue(void)
|
||||
if (node_rx->hdr.type == NODE_RX_TYPE_CONNECTION) {
|
||||
struct radio_le_conn_cmplt *radio_le_conn_cmplt;
|
||||
struct connection *conn = NULL;
|
||||
struct pdu_data *pdu_data_rx;
|
||||
u8_t bm;
|
||||
|
||||
pdu_data_rx = (void *)node_rx->pdu_data;
|
||||
radio_le_conn_cmplt = (void *)pdu_data_rx->lldata;
|
||||
radio_le_conn_cmplt = (void *)node_rx->pdu_data;
|
||||
if ((radio_le_conn_cmplt->status == BT_HCI_ERR_ADV_TIMEOUT) ||
|
||||
radio_le_conn_cmplt->role) {
|
||||
if (radio_le_conn_cmplt->status ==
|
||||
@@ -11374,6 +11440,27 @@ void ll_rx_mem_release(void **node_rx)
|
||||
_node_rx = _node_rx->hdr.onion.next;
|
||||
|
||||
switch (_node_rx_free->hdr.type) {
|
||||
case NODE_RX_TYPE_CONNECTION:
|
||||
if (IS_ENABLED(CONFIG_BT_CENTRAL)) {
|
||||
if (*((u8_t *)_node_rx_free->pdu_data) ==
|
||||
BT_HCI_ERR_UNKNOWN_CONN_ID) {
|
||||
struct connection *conn;
|
||||
|
||||
conn = _radio.scanner.conn;
|
||||
_radio.scanner.conn = NULL;
|
||||
|
||||
mem_release(conn, &_radio.conn_free);
|
||||
|
||||
_radio.scanner.is_enabled = 0;
|
||||
|
||||
if (!_radio.advertiser.is_enabled) {
|
||||
ll_adv_scan_state_cb(0);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* passthrough */
|
||||
case NODE_RX_TYPE_DC_PDU:
|
||||
case NODE_RX_TYPE_REPORT:
|
||||
|
||||
@@ -11386,7 +11473,6 @@ void ll_rx_mem_release(void **node_rx)
|
||||
case NODE_RX_TYPE_SCAN_REQ:
|
||||
#endif /* CONFIG_BT_CTLR_SCAN_REQ_NOTIFY */
|
||||
|
||||
case NODE_RX_TYPE_CONNECTION:
|
||||
case NODE_RX_TYPE_CONN_UPDATE:
|
||||
case NODE_RX_TYPE_ENC_REFRESH:
|
||||
|
||||
|
||||
@@ -356,7 +356,7 @@ u32_t radio_adv_filter_pol_get(void);
|
||||
u32_t radio_scan_enable(u8_t type, u8_t init_addr_type, u8_t *init_addr,
|
||||
u16_t interval, u16_t window, u8_t filter_policy,
|
||||
u8_t rpa_gen, u8_t rl_idx);
|
||||
u32_t radio_scan_disable(void);
|
||||
u32_t radio_scan_disable(bool scanner);
|
||||
u32_t ll_scan_is_enabled(void);
|
||||
u32_t radio_scan_filter_pol_get(void);
|
||||
|
||||
|
||||
@@ -210,7 +210,8 @@ struct connection {
|
||||
u8_t cmd:1;
|
||||
u8_t disabled:1;
|
||||
u8_t status;
|
||||
u16_t interval;
|
||||
u16_t interval_min;
|
||||
u16_t interval_max;
|
||||
u16_t latency;
|
||||
u16_t timeout;
|
||||
u8_t preferred_periodicity;
|
||||
@@ -236,6 +237,7 @@ struct connection {
|
||||
#define LLCP_LENGTH_STATE_ACK_WAIT 1
|
||||
#define LLCP_LENGTH_STATE_RSP_WAIT 2
|
||||
#define LLCP_LENGTH_STATE_RESIZE 3
|
||||
u8_t pause_tx:1;
|
||||
u16_t rx_octets;
|
||||
u16_t tx_octets;
|
||||
#if defined(CONFIG_BT_CTLR_PHY)
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include <zephyr/types.h>
|
||||
#include <bluetooth/hci.h>
|
||||
#include <bluetooth/controller.h>
|
||||
#include <misc/slist.h>
|
||||
|
||||
#include "util/util.h"
|
||||
@@ -55,3 +56,8 @@ u32_t ll_addr_set(u8_t addr_type, u8_t const *const bdaddr)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bt_ctlr_set_public_addr(const u8_t *addr)
|
||||
{
|
||||
(void)memcpy(pub_addr, addr, sizeof(pub_addr));
|
||||
}
|
||||
|
||||
@@ -59,12 +59,22 @@ u32_t ll_scan_params_set(u8_t type, u16_t interval, u16_t window,
|
||||
|
||||
u32_t ll_scan_enable(u8_t enable)
|
||||
{
|
||||
u8_t rpa_gen = 0;
|
||||
u32_t status;
|
||||
u8_t rpa_gen = 0;
|
||||
u32_t scan;
|
||||
|
||||
if (!enable) {
|
||||
return radio_scan_disable();
|
||||
} else if (ll_scan_is_enabled()) {
|
||||
return radio_scan_disable(true);
|
||||
}
|
||||
|
||||
scan = ll_scan_is_enabled();
|
||||
|
||||
/* Initiator and scanning are not supported */
|
||||
if (scan & BIT(2)) {
|
||||
return BT_HCI_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
if (scan) {
|
||||
/* Duplicate filtering is processed in the HCI layer */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -244,6 +244,7 @@ config BT_ATT_TX_MAX
|
||||
|
||||
config BT_AUTO_PHY_UPDATE
|
||||
bool "Auto-initiate PHY Update Procedure"
|
||||
depends on BT_PHY_UPDATE
|
||||
default y
|
||||
help
|
||||
Initiate PHY Update Procedure on connection establishment.
|
||||
@@ -258,6 +259,7 @@ config BT_SMP
|
||||
select TINYCRYPT_AES
|
||||
select TINYCRYPT_AES_CMAC
|
||||
select BT_RPA
|
||||
select BT_ECC
|
||||
help
|
||||
This option enables support for the Security Manager Protocol
|
||||
(SMP), making it possible to pair devices over LE.
|
||||
@@ -311,6 +313,14 @@ config BT_USE_DEBUG_KEYS
|
||||
If this option is enabled anyone is able to decipher encrypted air
|
||||
traffic.
|
||||
|
||||
config BT_BONDABLE
|
||||
bool "Bondable Mode"
|
||||
default y
|
||||
help
|
||||
This option enables support for Bondable Mode. In this mode,
|
||||
Bonding flag in AuthReq of SMP Pairing Request/Response will be set
|
||||
indicating the support for this mode.
|
||||
|
||||
endif # BT_SMP
|
||||
|
||||
config BT_L2CAP_DYNAMIC_CHANNEL
|
||||
@@ -341,8 +351,61 @@ config BT_MAX_PAIRED
|
||||
Maximum number of paired Bluetooth devices. The minimum (and
|
||||
default) number is 1.
|
||||
|
||||
config BT_GAP_PERIPHERAL_PREF_PARAMS
|
||||
bool "Configure peripheral preferred connection parameters"
|
||||
default y
|
||||
depends on BT_PERIPHERAL
|
||||
help
|
||||
This allows to configure periphral preferred connection parameters.
|
||||
Enabling this option results in adding PPCP characteristic in GAP
|
||||
and sending request for connection parameters udpate after GAP
|
||||
recommended 5 seconds of connection as peripheral. If disabled it is
|
||||
up to application to set expected connection parameters.
|
||||
|
||||
if BT_GAP_PERIPHERAL_PREF_PARAMS
|
||||
config BT_PERIPHERAL_PREF_MIN_INT
|
||||
int "Peripheral preferred minimum connection interval in 1.25ms units"
|
||||
default 24
|
||||
range 6 3200
|
||||
|
||||
config BT_PERIPHERAL_PREF_MAX_INT
|
||||
int "Peripheral preferred maximum connection interval in 1.25ms units"
|
||||
default 40
|
||||
range 6 3200
|
||||
|
||||
config BT_PERIPHERAL_PREF_SLAVE_LATENCY
|
||||
int "Peripheral preferred slave latency in Connection Intervals"
|
||||
default 0
|
||||
range 0 499
|
||||
|
||||
config BT_PERIPHERAL_PREF_TIMEOUT
|
||||
int "Peripheral preferred supervision timeout in 10ms units"
|
||||
default 42
|
||||
range 10 3200
|
||||
help
|
||||
It is up to user to provide valid timeout which pass required minimum
|
||||
value: in milliseconds it shall be larger than
|
||||
"(1+ Conn_Latency) * Conn_Interval_Max * 2"
|
||||
where Conn_Interval_Max is given in milliseconds.
|
||||
endif # BT_GAP_PERIPHERAL_PREF_PARAMS
|
||||
|
||||
config BT_CREATE_CONN_TIMEOUT
|
||||
int "Timeout for pending LE Create Connection command in seconds"
|
||||
default 3
|
||||
range 1 65535
|
||||
endif # BT_CONN
|
||||
|
||||
if BT_OBSERVER
|
||||
config BT_BACKGROUND_SCAN_INTERVAL
|
||||
int "Scan interval used for background scanning in 0.625 ms units"
|
||||
default 2048
|
||||
range 4 16384
|
||||
config BT_BACKGROUND_SCAN_WINDOW
|
||||
int "Scan window used for background scanning in 0.625 ms units"
|
||||
default 18
|
||||
range 4 16384
|
||||
endif # BT_OBSERVER
|
||||
|
||||
config BT_SCAN_WITH_IDENTITY
|
||||
bool "Perform active scanning using local identity address"
|
||||
depends on !BT_PRIVACY && (BT_CENTRAL || BT_OBSERVER)
|
||||
@@ -402,12 +465,17 @@ config BT_ID_MAX
|
||||
|
||||
endif # BT_HCI_HOST
|
||||
|
||||
config BT_ECC
|
||||
bool "Enable ECDH key generation support"
|
||||
help
|
||||
This option adds support for ECDH HCI commands.
|
||||
|
||||
config BT_TINYCRYPT_ECC
|
||||
bool "Use TinyCrypt library for ECDH"
|
||||
select TINYCRYPT
|
||||
select TINYCRYPT_ECC_DH
|
||||
depends on BT_HCI_RAW || BT_HCI_HOST
|
||||
default y if BT_CTLR && (BT_SMP || BT_MESH_PROV)
|
||||
depends on BT_ECC && (BT_HCI_RAW || BT_HCI_HOST)
|
||||
default y if BT_CTLR
|
||||
help
|
||||
If this option is set TinyCrypt library is used for emulating the
|
||||
ECDH HCI commands and events needed by e.g. LE Secure Connections.
|
||||
|
||||
@@ -337,6 +337,7 @@ process:
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_GATT_CLIENT)
|
||||
static u8_t att_mtu_rsp(struct bt_att *att, struct net_buf *buf)
|
||||
{
|
||||
struct bt_att_exchange_mtu_rsp *rsp;
|
||||
@@ -370,6 +371,7 @@ static u8_t att_mtu_rsp(struct bt_att *att, struct net_buf *buf)
|
||||
|
||||
return att_handle_rsp(att, rsp, buf->len, 0);
|
||||
}
|
||||
#endif /* CONFIG_BT_GATT_CLIENT */
|
||||
|
||||
static bool range_is_valid(u16_t start, u16_t end, u16_t *err)
|
||||
{
|
||||
@@ -1298,9 +1300,9 @@ static u8_t prep_write_cb(const struct bt_gatt_attr *attr, void *user_data)
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
||||
/* Check if attribute requires handler to accept the data */
|
||||
if (!(attr->perm & BT_GATT_PERM_PREPARE_WRITE)) {
|
||||
data->err = BT_ATT_ERR_WRITE_NOT_PERMITTED;
|
||||
return BT_GATT_ITER_STOP;
|
||||
goto append;
|
||||
}
|
||||
|
||||
/* Write attribute value to check if device is authorized */
|
||||
@@ -1311,6 +1313,7 @@ static u8_t prep_write_cb(const struct bt_gatt_attr *attr, void *user_data)
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
||||
append:
|
||||
/* Copy data into the outstanding queue */
|
||||
data->buf = net_buf_alloc(&prep_pool, K_NO_WAIT);
|
||||
if (!data->buf) {
|
||||
@@ -1503,6 +1506,7 @@ static u8_t att_signed_write_cmd(struct bt_att *att, struct net_buf *buf)
|
||||
}
|
||||
#endif /* CONFIG_BT_SIGNING */
|
||||
|
||||
#if defined(CONFIG_BT_GATT_CLIENT)
|
||||
#if defined(CONFIG_BT_SMP)
|
||||
static int att_change_security(struct bt_conn *conn, u8_t err)
|
||||
{
|
||||
@@ -1647,6 +1651,13 @@ static u8_t att_handle_read_mult_rsp(struct bt_att *att, struct net_buf *buf)
|
||||
}
|
||||
#endif /* CONFIG_BT_GATT_READ_MULTIPLE */
|
||||
|
||||
static u8_t att_handle_read_group_rsp(struct bt_att *att, struct net_buf *buf)
|
||||
{
|
||||
BT_DBG("");
|
||||
|
||||
return att_handle_rsp(att, buf->data, buf->len, 0);
|
||||
}
|
||||
|
||||
static u8_t att_handle_write_rsp(struct bt_att *att, struct net_buf *buf)
|
||||
{
|
||||
BT_DBG("");
|
||||
@@ -1703,6 +1714,7 @@ static u8_t att_indicate(struct bt_att *att, struct net_buf *buf)
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_BT_GATT_CLIENT */
|
||||
|
||||
static u8_t att_confirm(struct bt_att *att, struct net_buf *buf)
|
||||
{
|
||||
@@ -1717,69 +1729,35 @@ static const struct att_handler {
|
||||
att_type_t type;
|
||||
u8_t (*func)(struct bt_att *att, struct net_buf *buf);
|
||||
} handlers[] = {
|
||||
{ BT_ATT_OP_ERROR_RSP,
|
||||
sizeof(struct bt_att_error_rsp),
|
||||
ATT_RESPONSE,
|
||||
att_error_rsp },
|
||||
{ BT_ATT_OP_MTU_REQ,
|
||||
sizeof(struct bt_att_exchange_mtu_req),
|
||||
ATT_REQUEST,
|
||||
att_mtu_req },
|
||||
{ BT_ATT_OP_MTU_RSP,
|
||||
sizeof(struct bt_att_exchange_mtu_rsp),
|
||||
ATT_RESPONSE,
|
||||
att_mtu_rsp },
|
||||
{ BT_ATT_OP_FIND_INFO_REQ,
|
||||
sizeof(struct bt_att_find_info_req),
|
||||
ATT_REQUEST,
|
||||
att_find_info_req },
|
||||
{ BT_ATT_OP_FIND_INFO_RSP,
|
||||
sizeof(struct bt_att_find_info_rsp),
|
||||
ATT_RESPONSE,
|
||||
att_handle_find_info_rsp },
|
||||
{ BT_ATT_OP_FIND_TYPE_REQ,
|
||||
sizeof(struct bt_att_find_type_req),
|
||||
ATT_REQUEST,
|
||||
att_find_type_req },
|
||||
{ BT_ATT_OP_FIND_TYPE_RSP,
|
||||
sizeof(struct bt_att_find_type_rsp),
|
||||
ATT_RESPONSE,
|
||||
att_handle_find_type_rsp },
|
||||
{ BT_ATT_OP_READ_TYPE_REQ,
|
||||
sizeof(struct bt_att_read_type_req),
|
||||
ATT_REQUEST,
|
||||
att_read_type_req },
|
||||
{ BT_ATT_OP_READ_TYPE_RSP,
|
||||
sizeof(struct bt_att_read_type_rsp),
|
||||
ATT_RESPONSE,
|
||||
att_handle_read_type_rsp },
|
||||
{ BT_ATT_OP_READ_REQ,
|
||||
sizeof(struct bt_att_read_req),
|
||||
ATT_REQUEST,
|
||||
att_read_req },
|
||||
{ BT_ATT_OP_READ_RSP,
|
||||
sizeof(struct bt_att_read_rsp),
|
||||
ATT_RESPONSE,
|
||||
att_handle_read_rsp },
|
||||
{ BT_ATT_OP_READ_BLOB_REQ,
|
||||
sizeof(struct bt_att_read_blob_req),
|
||||
ATT_REQUEST,
|
||||
att_read_blob_req },
|
||||
{ BT_ATT_OP_READ_BLOB_RSP,
|
||||
sizeof(struct bt_att_read_blob_rsp),
|
||||
ATT_RESPONSE,
|
||||
att_handle_read_blob_rsp },
|
||||
#if defined(CONFIG_BT_GATT_READ_MULTIPLE)
|
||||
{ BT_ATT_OP_READ_MULT_REQ,
|
||||
BT_ATT_READ_MULT_MIN_LEN_REQ,
|
||||
ATT_REQUEST,
|
||||
att_read_mult_req },
|
||||
#endif /* CONFIG_BT_GATT_READ_MULTIPLE */
|
||||
#if defined(CONFIG_BT_GATT_READ_MULTIPLE)
|
||||
{ BT_ATT_OP_READ_MULT_RSP,
|
||||
sizeof(struct bt_att_read_mult_rsp),
|
||||
ATT_RESPONSE,
|
||||
att_handle_read_mult_rsp },
|
||||
#endif /* CONFIG_BT_GATT_READ_MULTIPLE */
|
||||
{ BT_ATT_OP_READ_GROUP_REQ,
|
||||
sizeof(struct bt_att_read_group_req),
|
||||
@@ -1789,34 +1767,14 @@ static const struct att_handler {
|
||||
sizeof(struct bt_att_write_req),
|
||||
ATT_REQUEST,
|
||||
att_write_req },
|
||||
{ BT_ATT_OP_WRITE_RSP,
|
||||
0,
|
||||
ATT_RESPONSE,
|
||||
att_handle_write_rsp },
|
||||
{ BT_ATT_OP_PREPARE_WRITE_REQ,
|
||||
sizeof(struct bt_att_prepare_write_req),
|
||||
ATT_REQUEST,
|
||||
att_prepare_write_req },
|
||||
{ BT_ATT_OP_PREPARE_WRITE_RSP,
|
||||
sizeof(struct bt_att_prepare_write_rsp),
|
||||
ATT_RESPONSE,
|
||||
att_handle_prepare_write_rsp },
|
||||
{ BT_ATT_OP_EXEC_WRITE_REQ,
|
||||
sizeof(struct bt_att_exec_write_req),
|
||||
ATT_REQUEST,
|
||||
att_exec_write_req },
|
||||
{ BT_ATT_OP_EXEC_WRITE_RSP,
|
||||
0,
|
||||
ATT_RESPONSE,
|
||||
att_handle_exec_write_rsp },
|
||||
{ BT_ATT_OP_NOTIFY,
|
||||
sizeof(struct bt_att_notify),
|
||||
ATT_NOTIFICATION,
|
||||
att_notify },
|
||||
{ BT_ATT_OP_INDICATE,
|
||||
sizeof(struct bt_att_indicate),
|
||||
ATT_INDICATION,
|
||||
att_indicate },
|
||||
{ BT_ATT_OP_CONFIRM,
|
||||
0,
|
||||
ATT_CONFIRMATION,
|
||||
@@ -1832,6 +1790,66 @@ static const struct att_handler {
|
||||
ATT_COMMAND,
|
||||
att_signed_write_cmd },
|
||||
#endif /* CONFIG_BT_SIGNING */
|
||||
#if defined(CONFIG_BT_GATT_CLIENT)
|
||||
{ BT_ATT_OP_ERROR_RSP,
|
||||
sizeof(struct bt_att_error_rsp),
|
||||
ATT_RESPONSE,
|
||||
att_error_rsp },
|
||||
{ BT_ATT_OP_MTU_RSP,
|
||||
sizeof(struct bt_att_exchange_mtu_rsp),
|
||||
ATT_RESPONSE,
|
||||
att_mtu_rsp },
|
||||
{ BT_ATT_OP_FIND_INFO_RSP,
|
||||
sizeof(struct bt_att_find_info_rsp),
|
||||
ATT_RESPONSE,
|
||||
att_handle_find_info_rsp },
|
||||
{ BT_ATT_OP_FIND_TYPE_RSP,
|
||||
sizeof(struct bt_att_find_type_rsp),
|
||||
ATT_RESPONSE,
|
||||
att_handle_find_type_rsp },
|
||||
{ BT_ATT_OP_READ_TYPE_RSP,
|
||||
sizeof(struct bt_att_read_type_rsp),
|
||||
ATT_RESPONSE,
|
||||
att_handle_read_type_rsp },
|
||||
{ BT_ATT_OP_READ_RSP,
|
||||
sizeof(struct bt_att_read_rsp),
|
||||
ATT_RESPONSE,
|
||||
att_handle_read_rsp },
|
||||
{ BT_ATT_OP_READ_BLOB_RSP,
|
||||
sizeof(struct bt_att_read_blob_rsp),
|
||||
ATT_RESPONSE,
|
||||
att_handle_read_blob_rsp },
|
||||
#if defined(CONFIG_BT_GATT_READ_MULTIPLE)
|
||||
{ BT_ATT_OP_READ_MULT_RSP,
|
||||
sizeof(struct bt_att_read_mult_rsp),
|
||||
ATT_RESPONSE,
|
||||
att_handle_read_mult_rsp },
|
||||
#endif /* CONFIG_BT_GATT_READ_MULTIPLE */
|
||||
{ BT_ATT_OP_READ_GROUP_RSP,
|
||||
sizeof(struct bt_att_read_group_rsp),
|
||||
ATT_RESPONSE,
|
||||
att_handle_read_group_rsp },
|
||||
{ BT_ATT_OP_WRITE_RSP,
|
||||
0,
|
||||
ATT_RESPONSE,
|
||||
att_handle_write_rsp },
|
||||
{ BT_ATT_OP_PREPARE_WRITE_RSP,
|
||||
sizeof(struct bt_att_prepare_write_rsp),
|
||||
ATT_RESPONSE,
|
||||
att_handle_prepare_write_rsp },
|
||||
{ BT_ATT_OP_EXEC_WRITE_RSP,
|
||||
0,
|
||||
ATT_RESPONSE,
|
||||
att_handle_exec_write_rsp },
|
||||
{ BT_ATT_OP_NOTIFY,
|
||||
sizeof(struct bt_att_notify),
|
||||
ATT_NOTIFICATION,
|
||||
att_notify },
|
||||
{ BT_ATT_OP_INDICATE,
|
||||
sizeof(struct bt_att_indicate),
|
||||
ATT_INDICATION,
|
||||
att_indicate },
|
||||
#endif /* CONFIG_BT_GATT_CLIENT */
|
||||
};
|
||||
|
||||
static att_type_t att_op_get_type(u8_t op)
|
||||
|
||||
@@ -57,7 +57,7 @@ NET_BUF_POOL_FIXED_DEFINE(frag_pool, CONFIG_BT_L2CAP_TX_FRAG_COUNT, FRAG_SIZE,
|
||||
#endif /* CONFIG_BT_L2CAP_TX_FRAG_COUNT > 0 */
|
||||
|
||||
/* How long until we cancel HCI_LE_Create_Connection */
|
||||
#define CONN_TIMEOUT K_SECONDS(3)
|
||||
#define CONN_TIMEOUT K_SECONDS(CONFIG_BT_CREATE_CONN_TIMEOUT)
|
||||
|
||||
#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
|
||||
const struct bt_conn_auth_cb *bt_auth;
|
||||
@@ -150,6 +150,17 @@ void notify_le_param_updated(struct bt_conn *conn)
|
||||
{
|
||||
struct bt_conn_cb *cb;
|
||||
|
||||
/* If new connection parameters meet requirement of pending
|
||||
* parameters don't send slave conn param request anymore on timeout
|
||||
*/
|
||||
if (atomic_test_bit(conn->flags, BT_CONN_SLAVE_PARAM_SET) &&
|
||||
conn->le.interval >= conn->le.interval_min &&
|
||||
conn->le.interval <= conn->le.interval_max &&
|
||||
conn->le.latency == conn->le.pending_latency &&
|
||||
conn->le.timeout == conn->le.pending_timeout) {
|
||||
atomic_clear_bit(conn->flags, BT_CONN_SLAVE_PARAM_SET);
|
||||
}
|
||||
|
||||
for (cb = callback_list; cb; cb = cb->_next) {
|
||||
if (cb->le_param_updated) {
|
||||
cb->le_param_updated(conn, conn->le.interval,
|
||||
@@ -188,25 +199,88 @@ bool le_param_req(struct bt_conn *conn, struct bt_le_conn_param *param)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void le_conn_update(struct k_work *work)
|
||||
static int send_conn_le_param_update(struct bt_conn *conn,
|
||||
const struct bt_le_conn_param *param)
|
||||
{
|
||||
BT_DBG("conn %p features 0x%02x params (%d-%d %d %d)", conn,
|
||||
conn->le.features[0], param->interval_min,
|
||||
param->interval_max, param->latency, param->timeout);
|
||||
|
||||
/* Use LE connection parameter request if both local and remote support
|
||||
* it; or if local role is master then use LE connection update.
|
||||
*/
|
||||
if ((BT_FEAT_LE_CONN_PARAM_REQ_PROC(bt_dev.le.features) &&
|
||||
BT_FEAT_LE_CONN_PARAM_REQ_PROC(conn->le.features) &&
|
||||
!atomic_test_bit(conn->flags, BT_CONN_SLAVE_PARAM_L2CAP)) ||
|
||||
(conn->role == BT_HCI_ROLE_MASTER)) {
|
||||
int rc;
|
||||
|
||||
rc = bt_conn_le_conn_update(conn, param);
|
||||
|
||||
/* store those in case of fallback to L2CAP */
|
||||
if (rc == 0) {
|
||||
conn->le.pending_latency = param->latency;
|
||||
conn->le.pending_timeout = param->timeout;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* If remote master does not support LL Connection Parameters Request
|
||||
* Procedure
|
||||
*/
|
||||
return bt_l2cap_update_conn_param(conn, param);
|
||||
}
|
||||
|
||||
static void conn_le_update_timeout(struct k_work *work)
|
||||
{
|
||||
struct bt_conn_le *le = CONTAINER_OF(work, struct bt_conn_le,
|
||||
update_work);
|
||||
struct bt_conn *conn = CONTAINER_OF(le, struct bt_conn, le);
|
||||
const struct bt_le_conn_param *param;
|
||||
|
||||
BT_DBG("conn %p", conn);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
|
||||
conn->state == BT_CONN_CONNECT) {
|
||||
bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
|
||||
conn->role == BT_CONN_ROLE_MASTER) {
|
||||
/* we don't call bt_conn_disconnect as it would also clear
|
||||
* auto connect flag if it was set, instead just cancel
|
||||
* connection directly
|
||||
*/
|
||||
bt_hci_cmd_send(BT_HCI_OP_LE_CREATE_CONN_CANCEL, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
param = BT_LE_CONN_PARAM(conn->le.interval_min,
|
||||
conn->le.interval_max,
|
||||
conn->le.latency,
|
||||
conn->le.timeout);
|
||||
#if defined (CONFIG_BT_GAP_PERIPHERAL_PREF_PARAMS)
|
||||
/* if application set own params use those, otherwise use defaults */
|
||||
if (atomic_test_and_clear_bit(conn->flags, BT_CONN_SLAVE_PARAM_SET)) {
|
||||
param = BT_LE_CONN_PARAM(conn->le.interval_min,
|
||||
conn->le.interval_max,
|
||||
conn->le.pending_latency,
|
||||
conn->le.pending_timeout);
|
||||
|
||||
bt_conn_le_param_update(conn, param);
|
||||
send_conn_le_param_update(conn, param);
|
||||
} else {
|
||||
param = BT_LE_CONN_PARAM(CONFIG_BT_PERIPHERAL_PREF_MIN_INT,
|
||||
CONFIG_BT_PERIPHERAL_PREF_MAX_INT,
|
||||
CONFIG_BT_PERIPHERAL_PREF_SLAVE_LATENCY,
|
||||
CONFIG_BT_PERIPHERAL_PREF_TIMEOUT);
|
||||
|
||||
send_conn_le_param_update(conn, param);
|
||||
}
|
||||
#else
|
||||
/* update only if application set own params */
|
||||
if (atomic_test_and_clear_bit(conn->flags, BT_CONN_SLAVE_PARAM_SET)) {
|
||||
param = BT_LE_CONN_PARAM(conn->le.interval_min,
|
||||
conn->le.interval_max,
|
||||
conn->le.latency,
|
||||
conn->le.timeout);
|
||||
|
||||
send_conn_le_param_update(conn, param);
|
||||
}
|
||||
#endif
|
||||
|
||||
atomic_set_bit(conn->flags, BT_CONN_SLAVE_PARAM_UPDATE);
|
||||
}
|
||||
|
||||
static struct bt_conn *conn_new(void)
|
||||
@@ -1383,7 +1457,7 @@ struct bt_conn *bt_conn_add_le(const bt_addr_le_t *peer)
|
||||
conn->type = BT_CONN_TYPE_LE;
|
||||
conn->le.interval_min = BT_GAP_INIT_CONN_INT_MIN;
|
||||
conn->le.interval_max = BT_GAP_INIT_CONN_INT_MAX;
|
||||
k_delayed_work_init(&conn->le.update_work, le_conn_update);
|
||||
k_delayed_work_init(&conn->le.update_work, conn_le_update_timeout);
|
||||
|
||||
return conn;
|
||||
}
|
||||
@@ -1735,25 +1809,30 @@ int bt_conn_le_param_update(struct bt_conn *conn,
|
||||
conn->le.interval <= param->interval_max &&
|
||||
conn->le.latency == param->latency &&
|
||||
conn->le.timeout == param->timeout) {
|
||||
atomic_clear_bit(conn->flags, BT_CONN_SLAVE_PARAM_SET);
|
||||
return -EALREADY;
|
||||
}
|
||||
|
||||
/* Cancel any pending update */
|
||||
k_delayed_work_cancel(&conn->le.update_work);
|
||||
|
||||
/* Use LE connection parameter request if both local and remote support
|
||||
* it; or if local role is master then use LE connection update.
|
||||
*/
|
||||
if ((BT_FEAT_LE_CONN_PARAM_REQ_PROC(bt_dev.le.features) &&
|
||||
BT_FEAT_LE_CONN_PARAM_REQ_PROC(conn->le.features)) ||
|
||||
(conn->role == BT_HCI_ROLE_MASTER)) {
|
||||
return bt_conn_le_conn_update(conn, param);
|
||||
if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
|
||||
conn->role == BT_CONN_ROLE_MASTER) {
|
||||
return send_conn_le_param_update(conn, param);
|
||||
}
|
||||
|
||||
/* If remote master does not support LL Connection Parameters Request
|
||||
* Procedure
|
||||
*/
|
||||
return bt_l2cap_update_conn_param(conn, param);
|
||||
if (IS_ENABLED(CONFIG_BT_PERIPHERAL)) {
|
||||
/* if slave conn param update timer expired just send request */
|
||||
if (atomic_test_bit(conn->flags, BT_CONN_SLAVE_PARAM_UPDATE)) {
|
||||
return send_conn_le_param_update(conn, param);
|
||||
}
|
||||
|
||||
/* store new conn params to be used by update timer */
|
||||
conn->le.interval_min = param->interval_min;
|
||||
conn->le.interval_max = param->interval_max;
|
||||
conn->le.pending_latency = param->latency;
|
||||
conn->le.pending_timeout = param->timeout;
|
||||
atomic_set_bit(conn->flags, BT_CONN_SLAVE_PARAM_SET);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_conn_disconnect(struct bt_conn *conn, u8_t reason)
|
||||
@@ -1857,7 +1936,7 @@ struct bt_conn *bt_conn_create_le(const bt_addr_le_t *peer,
|
||||
return conn;
|
||||
}
|
||||
|
||||
int bt_le_set_auto_conn(bt_addr_le_t *addr,
|
||||
int bt_le_set_auto_conn(const bt_addr_le_t *addr,
|
||||
const struct bt_le_conn_param *param)
|
||||
{
|
||||
struct bt_conn *conn;
|
||||
|
||||
@@ -25,7 +25,9 @@ enum {
|
||||
BT_CONN_BR_PAIRING_INITIATOR, /* local host starts authentication */
|
||||
BT_CONN_CLEANUP, /* Disconnected, pending cleanup */
|
||||
BT_CONN_AUTO_PHY_UPDATE, /* Auto-update PHY */
|
||||
BT_CONN_AUTO_DATA_LEN, /* Auto data len change in progress */
|
||||
BT_CONN_SLAVE_PARAM_UPDATE, /* If slave param update timer fired */
|
||||
BT_CONN_SLAVE_PARAM_SET, /* If slave param were set from app */
|
||||
BT_CONN_SLAVE_PARAM_L2CAP, /* If should force L2CAP for CPUP */
|
||||
|
||||
/* Total number of flags - must be at the end of the enum */
|
||||
BT_CONN_NUM_FLAGS,
|
||||
@@ -43,6 +45,8 @@ struct bt_conn_le {
|
||||
|
||||
u16_t latency;
|
||||
u16_t timeout;
|
||||
u16_t pending_latency;
|
||||
u16_t pending_timeout;
|
||||
|
||||
u8_t features[8];
|
||||
|
||||
|
||||
@@ -100,6 +100,27 @@ static ssize_t read_appearance(struct bt_conn *conn,
|
||||
sizeof(appearance));
|
||||
}
|
||||
|
||||
#if defined (CONFIG_BT_GAP_PERIPHERAL_PREF_PARAMS)
|
||||
static ssize_t read_ppcp(struct bt_conn *conn, const struct bt_gatt_attr *attr,
|
||||
void *buf, u16_t len, u16_t offset)
|
||||
{
|
||||
struct __packed {
|
||||
uint16_t min_int;
|
||||
uint16_t max_int;
|
||||
uint16_t latency;
|
||||
uint16_t timeout;
|
||||
} ppcp;
|
||||
|
||||
ppcp.min_int = sys_cpu_to_le16(CONFIG_BT_PERIPHERAL_PREF_MIN_INT);
|
||||
ppcp.max_int = sys_cpu_to_le16(CONFIG_BT_PERIPHERAL_PREF_MAX_INT);
|
||||
ppcp.latency = sys_cpu_to_le16(CONFIG_BT_PERIPHERAL_PREF_SLAVE_LATENCY);
|
||||
ppcp.timeout = sys_cpu_to_le16(CONFIG_BT_PERIPHERAL_PREF_TIMEOUT);
|
||||
|
||||
return bt_gatt_attr_read(conn, attr, buf, len, offset, &ppcp,
|
||||
sizeof(ppcp));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BT_CENTRAL) && defined(CONFIG_BT_PRIVACY)
|
||||
static ssize_t read_central_addr_res(struct bt_conn *conn,
|
||||
const struct bt_gatt_attr *attr, void *buf,
|
||||
@@ -131,6 +152,10 @@ static struct bt_gatt_attr gap_attrs[] = {
|
||||
BT_GATT_CHRC_READ, BT_GATT_PERM_READ,
|
||||
read_central_addr_res, NULL, NULL),
|
||||
#endif /* CONFIG_BT_CENTRAL && CONFIG_BT_PRIVACY */
|
||||
#if defined(CONFIG_BT_GAP_PERIPHERAL_PREF_PARAMS)
|
||||
BT_GATT_CHARACTERISTIC(BT_UUID_GAP_PPCP, BT_GATT_CHRC_READ,
|
||||
BT_GATT_PERM_READ, read_ppcp, NULL, NULL),
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct bt_gatt_service gap_svc = BT_GATT_SERVICE(gap_attrs);
|
||||
@@ -145,6 +170,11 @@ static void sc_ccc_cfg_changed(const struct bt_gatt_attr *attr,
|
||||
|
||||
static struct bt_gatt_attr gatt_attrs[] = {
|
||||
BT_GATT_PRIMARY_SERVICE(BT_UUID_GATT),
|
||||
/* Bluetooth 5.0, Vol3 Part G:
|
||||
* The Service Changed characteristic Attribute Handle on the server
|
||||
* shall not change if the server has a trusted relationship with any
|
||||
* client.
|
||||
*/
|
||||
BT_GATT_CHARACTERISTIC(BT_UUID_GATT_SC, BT_GATT_CHRC_INDICATE,
|
||||
BT_GATT_PERM_NONE, NULL, NULL, NULL),
|
||||
BT_GATT_CCC(sc_ccc_cfg, sc_ccc_cfg_changed),
|
||||
@@ -260,8 +290,8 @@ void bt_gatt_init(void)
|
||||
}
|
||||
|
||||
/* Register mandatory services */
|
||||
gatt_register(&gap_svc);
|
||||
gatt_register(&gatt_svc);
|
||||
gatt_register(&gap_svc);
|
||||
|
||||
k_delayed_work_init(&gatt_sc.work, sc_process);
|
||||
}
|
||||
@@ -1573,6 +1603,137 @@ static int gatt_read_type(struct bt_conn *conn,
|
||||
return gatt_send(conn, buf, gatt_read_type_rsp, params, NULL);
|
||||
}
|
||||
|
||||
static u16_t parse_service(struct bt_conn *conn, const void *pdu,
|
||||
struct bt_gatt_discover_params *params,
|
||||
u16_t length)
|
||||
{
|
||||
const struct bt_att_read_group_rsp *rsp = pdu;
|
||||
u16_t start_handle, end_handle = 0;
|
||||
union {
|
||||
struct bt_uuid uuid;
|
||||
struct bt_uuid_16 u16;
|
||||
struct bt_uuid_128 u128;
|
||||
} u;
|
||||
|
||||
/* Data can be either in UUID16 or UUID128 */
|
||||
switch (rsp->len) {
|
||||
case 6: /* UUID16 */
|
||||
u.uuid.type = BT_UUID_TYPE_16;
|
||||
break;
|
||||
case 20: /* UUID128 */
|
||||
u.uuid.type = BT_UUID_TYPE_128;
|
||||
break;
|
||||
default:
|
||||
BT_ERR("Invalid data len %u", rsp->len);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Parse services found */
|
||||
for (length--, pdu = rsp->data; length >= rsp->len;
|
||||
length -= rsp->len, pdu += rsp->len) {
|
||||
struct bt_gatt_attr attr = {};
|
||||
struct bt_gatt_service_val value;
|
||||
const struct bt_att_group_data *data = pdu;
|
||||
|
||||
start_handle = sys_le16_to_cpu(data->start_handle);
|
||||
if (!start_handle) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
end_handle = sys_le16_to_cpu(data->end_handle);
|
||||
if (!end_handle || end_handle < start_handle) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
switch (u.uuid.type) {
|
||||
case BT_UUID_TYPE_16:
|
||||
memcpy(&u.u16.val, data->value, sizeof(u.u16.val));
|
||||
u.u16.val = sys_le16_to_cpu(u.u16.val);
|
||||
break;
|
||||
case BT_UUID_TYPE_128:
|
||||
memcpy(u.u128.val, data->value, sizeof(u.u128.val));
|
||||
break;
|
||||
}
|
||||
|
||||
BT_DBG("start_handle 0x%04x end_handle 0x%04x uuid %s",
|
||||
start_handle, end_handle, bt_uuid_str(&u.uuid));
|
||||
|
||||
if (params->type == BT_GATT_DISCOVER_PRIMARY) {
|
||||
attr.uuid = BT_UUID_GATT_PRIMARY;
|
||||
} else {
|
||||
attr.uuid = BT_UUID_GATT_SECONDARY;
|
||||
}
|
||||
|
||||
value.end_handle = end_handle;
|
||||
value.uuid = &u.uuid;
|
||||
|
||||
attr.handle = start_handle;
|
||||
attr.user_data = &value;
|
||||
|
||||
if (params->func(conn, &attr, params) == BT_GATT_ITER_STOP) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Whole PDU read without error */
|
||||
if (length == 0 && end_handle) {
|
||||
return end_handle;
|
||||
}
|
||||
|
||||
done:
|
||||
params->func(conn, NULL, params);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void gatt_read_group_rsp(struct bt_conn *conn, u8_t err,
|
||||
const void *pdu, u16_t length,
|
||||
void *user_data)
|
||||
{
|
||||
struct bt_gatt_discover_params *params = user_data;
|
||||
u16_t handle;
|
||||
|
||||
BT_DBG("err 0x%02x", err);
|
||||
|
||||
if (err) {
|
||||
params->func(conn, NULL, params);
|
||||
return;
|
||||
}
|
||||
|
||||
handle = parse_service(conn, pdu, params, length);
|
||||
if (!handle) {
|
||||
return;
|
||||
}
|
||||
|
||||
gatt_discover_next(conn, handle, params);
|
||||
}
|
||||
|
||||
static int gatt_read_group(struct bt_conn *conn,
|
||||
struct bt_gatt_discover_params *params)
|
||||
{
|
||||
struct net_buf *buf;
|
||||
struct bt_att_read_group_req *req;
|
||||
|
||||
buf = bt_att_create_pdu(conn, BT_ATT_OP_READ_GROUP_REQ, sizeof(*req));
|
||||
if (!buf) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
req = net_buf_add(buf, sizeof(*req));
|
||||
req->start_handle = sys_cpu_to_le16(params->start_handle);
|
||||
req->end_handle = sys_cpu_to_le16(params->end_handle);
|
||||
|
||||
if (params->type == BT_GATT_DISCOVER_PRIMARY) {
|
||||
net_buf_add_le16(buf, BT_UUID_16(BT_UUID_GATT_PRIMARY)->val);
|
||||
} else {
|
||||
net_buf_add_le16(buf, BT_UUID_16(BT_UUID_GATT_SECONDARY)->val);
|
||||
}
|
||||
|
||||
BT_DBG("start_handle 0x%04x end_handle 0x%04x", params->start_handle,
|
||||
params->end_handle);
|
||||
|
||||
return gatt_send(conn, buf, gatt_read_group_rsp, params, NULL);
|
||||
}
|
||||
|
||||
static void gatt_find_info_rsp(struct bt_conn *conn, u8_t err,
|
||||
const void *pdu, u16_t length,
|
||||
void *user_data)
|
||||
@@ -1696,7 +1857,10 @@ int bt_gatt_discover(struct bt_conn *conn,
|
||||
switch (params->type) {
|
||||
case BT_GATT_DISCOVER_PRIMARY:
|
||||
case BT_GATT_DISCOVER_SECONDARY:
|
||||
return gatt_find_type(conn, params);
|
||||
if (params->uuid) {
|
||||
return gatt_find_type(conn, params);
|
||||
}
|
||||
return gatt_read_group(conn, params);
|
||||
case BT_GATT_DISCOVER_INCLUDE:
|
||||
case BT_GATT_DISCOVER_CHARACTERISTIC:
|
||||
return gatt_read_type(conn, params);
|
||||
@@ -2277,14 +2441,6 @@ int bt_gatt_store_ccc(u8_t id, const bt_addr_le_t *addr)
|
||||
|
||||
bt_gatt_foreach_attr(0x0001, 0xffff, ccc_save, &save);
|
||||
|
||||
str = settings_str_from_bytes(save.store,
|
||||
save.count * sizeof(*save.store),
|
||||
val, sizeof(val));
|
||||
if (!str) {
|
||||
BT_ERR("Unable to encode CCC as handle:value");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (id) {
|
||||
char id_str[4];
|
||||
|
||||
@@ -2296,6 +2452,21 @@ int bt_gatt_store_ccc(u8_t id, const bt_addr_le_t *addr)
|
||||
(bt_addr_le_t *)addr, NULL);
|
||||
}
|
||||
|
||||
if (!save.count) {
|
||||
/* No entries to encode just clear */
|
||||
str = NULL;
|
||||
goto save;
|
||||
}
|
||||
|
||||
str = settings_str_from_bytes(save.store,
|
||||
save.count * sizeof(*save.store),
|
||||
val, sizeof(val));
|
||||
if (!str) {
|
||||
BT_ERR("Unable to encode CCC as handle:value");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
save:
|
||||
err = settings_save_one(key, str);
|
||||
if (err) {
|
||||
BT_ERR("Failed to store CCCs (err %d)", err);
|
||||
@@ -2303,7 +2474,7 @@ int bt_gatt_store_ccc(u8_t id, const bt_addr_le_t *addr)
|
||||
}
|
||||
|
||||
BT_DBG("Stored CCCs for %s (%s) val %s", bt_addr_le_str(addr), key,
|
||||
str);
|
||||
str ? str : "nill");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2385,13 +2556,16 @@ static u8_t ccc_load(const struct bt_gatt_attr *attr, void *user_data)
|
||||
BT_DBG("Restoring CCC: handle 0x%04x value 0x%04x", load->entry->handle,
|
||||
load->entry->value);
|
||||
|
||||
cfg = ccc_find_cfg(ccc, BT_ADDR_LE_ANY);
|
||||
cfg = ccc_find_cfg(ccc, &load->addr);
|
||||
if (!cfg) {
|
||||
BT_DBG("Unable to restore CCC: no cfg left");
|
||||
goto next;
|
||||
cfg = ccc_find_cfg(ccc, BT_ADDR_LE_ANY);
|
||||
if (!cfg) {
|
||||
BT_DBG("Unable to restore CCC: no cfg left");
|
||||
goto next;
|
||||
}
|
||||
bt_addr_le_copy(&cfg->peer, &load->addr);
|
||||
}
|
||||
|
||||
bt_addr_le_copy(&cfg->peer, &load->addr);
|
||||
cfg->value = load->entry->value;
|
||||
|
||||
next:
|
||||
|
||||
@@ -82,9 +82,11 @@ static bt_ready_cb_t ready_cb;
|
||||
|
||||
static bt_le_scan_cb_t *scan_dev_found_cb;
|
||||
|
||||
#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;
|
||||
@@ -680,7 +682,10 @@ static int hci_le_read_remote_features(struct bt_conn *conn)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hci_le_set_data_len(struct bt_conn *conn)
|
||||
/* 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;
|
||||
@@ -690,7 +695,8 @@ static int hci_le_set_data_len(struct bt_conn *conn)
|
||||
|
||||
err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_READ_MAX_DATA_LEN, NULL, &rsp);
|
||||
if (err) {
|
||||
return err;
|
||||
BT_ERR("Failed to read DLE max data len");
|
||||
return;
|
||||
}
|
||||
|
||||
rp = (void *)rsp->data;
|
||||
@@ -700,7 +706,8 @@ static int hci_le_set_data_len(struct bt_conn *conn)
|
||||
|
||||
buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_DATA_LEN, sizeof(*cp));
|
||||
if (!buf) {
|
||||
return -ENOBUFS;
|
||||
BT_ERR("Failed to create LE Set Data Length Command");
|
||||
return;
|
||||
}
|
||||
|
||||
cp = net_buf_add(buf, sizeof(*cp));
|
||||
@@ -709,10 +716,8 @@ static int hci_le_set_data_len(struct bt_conn *conn)
|
||||
cp->tx_time = sys_cpu_to_le16(tx_time);
|
||||
err = bt_hci_cmd_send(BT_HCI_OP_LE_SET_DATA_LEN, buf);
|
||||
if (err) {
|
||||
return err;
|
||||
BT_ERR("Failed to send LE Set Data Length Command");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hci_le_set_phy(struct bt_conn *conn)
|
||||
@@ -736,16 +741,23 @@ static int hci_le_set_phy(struct bt_conn *conn)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void update_conn_param(struct bt_conn *conn)
|
||||
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->le.update_work,
|
||||
conn->role == BT_HCI_ROLE_MASTER ? K_NO_WAIT :
|
||||
CONN_UPDATE_TIMEOUT);
|
||||
k_delayed_work_submit(&conn->le.update_work, CONN_UPDATE_TIMEOUT);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_SMP)
|
||||
@@ -781,30 +793,33 @@ static void le_enh_conn_complete(struct bt_hci_evt_le_enh_conn_complete *evt)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (evt->status) {
|
||||
/*
|
||||
* if there was an error we are only interested in pending
|
||||
* connection so there is no need to check ID address as
|
||||
* only one connection can be in that state
|
||||
*
|
||||
* Depending on error code address might not be valid anyway.
|
||||
*/
|
||||
conn = bt_conn_lookup_state_le(NULL, BT_CONN_CONNECT);
|
||||
if (!conn) {
|
||||
return;
|
||||
if (IS_ENABLED(CONFIG_BT_CENTRAL)) {
|
||||
if (evt->status) {
|
||||
/*
|
||||
* if there was an error we are only interested in pending
|
||||
* connection so there is no need to check ID address as
|
||||
* only one connection can be in that state
|
||||
*
|
||||
* Depending on error code address might not be valid anyway.
|
||||
*/
|
||||
conn = bt_conn_lookup_state_le(NULL, BT_CONN_CONNECT);
|
||||
if (!conn) {
|
||||
return;
|
||||
}
|
||||
|
||||
conn->err = evt->status;
|
||||
|
||||
bt_conn_set_state(conn, BT_CONN_DISCONNECTED);
|
||||
|
||||
/* check if device is market for auto connect */
|
||||
if (atomic_test_bit(conn->flags, BT_CONN_AUTO_CONNECT)) {
|
||||
bt_conn_set_state(conn, BT_CONN_CONNECT_SCAN);
|
||||
}
|
||||
|
||||
goto done;
|
||||
}
|
||||
|
||||
conn->err = evt->status;
|
||||
|
||||
bt_conn_set_state(conn, BT_CONN_DISCONNECTED);
|
||||
|
||||
/* Drop the reference got by lookup call in CONNECT state.
|
||||
* We are now in DISCONNECTED state since no successful LE
|
||||
* link been made.
|
||||
*/
|
||||
bt_conn_unref(conn);
|
||||
|
||||
return;
|
||||
} else {
|
||||
BT_ASSERT(evt->status == 0);
|
||||
}
|
||||
|
||||
bt_addr_le_copy(&id_addr, &evt->peer_addr);
|
||||
@@ -849,6 +864,7 @@ static void le_enh_conn_complete(struct bt_hci_evt_le_enh_conn_complete *evt)
|
||||
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 = 0;
|
||||
|
||||
/*
|
||||
* Use connection address (instead of identity address) as initiator
|
||||
@@ -910,15 +926,15 @@ static void le_enh_conn_complete(struct bt_hci_evt_le_enh_conn_complete *evt)
|
||||
}
|
||||
}
|
||||
|
||||
if (BT_FEAT_LE_DLE(bt_dev.le.features)) {
|
||||
err = hci_le_set_data_len(conn);
|
||||
if (!err) {
|
||||
atomic_set_bit(conn->flags, BT_CONN_AUTO_DATA_LEN);
|
||||
goto done;
|
||||
}
|
||||
if (IS_ENABLED(CONFIG_BT_DATA_LEN_UPDATE) &&
|
||||
BT_FEAT_LE_DLE(bt_dev.le.features)) {
|
||||
hci_le_set_data_len(conn);
|
||||
}
|
||||
|
||||
update_conn_param(conn);
|
||||
if (IS_ENABLED(CONFIG_BT_PERIPHERAL) &&
|
||||
conn->role == BT_CONN_ROLE_SLAVE) {
|
||||
slave_update_conn_param(conn);
|
||||
}
|
||||
|
||||
done:
|
||||
bt_conn_unref(conn);
|
||||
@@ -998,23 +1014,22 @@ static void le_remote_feat_complete(struct net_buf *buf)
|
||||
}
|
||||
}
|
||||
|
||||
if (BT_FEAT_LE_DLE(bt_dev.le.features) &&
|
||||
if (IS_ENABLED(CONFIG_BT_DATA_LEN_UPDATE) &&
|
||||
BT_FEAT_LE_DLE(bt_dev.le.features) &&
|
||||
BT_FEAT_LE_DLE(conn->le.features)) {
|
||||
int err;
|
||||
|
||||
err = hci_le_set_data_len(conn);
|
||||
if (!err) {
|
||||
atomic_set_bit(conn->flags, BT_CONN_AUTO_DATA_LEN);
|
||||
goto done;
|
||||
}
|
||||
hci_le_set_data_len(conn);
|
||||
}
|
||||
|
||||
update_conn_param(conn);
|
||||
if (IS_ENABLED(CONFIG_BT_PERIPHERAL) &&
|
||||
conn->role == BT_CONN_ROLE_SLAVE) {
|
||||
slave_update_conn_param(conn);
|
||||
}
|
||||
|
||||
done:
|
||||
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;
|
||||
@@ -1034,16 +1049,13 @@ static void le_data_len_change(struct net_buf *buf)
|
||||
BT_DBG("max. tx: %u (%uus), max. rx: %u (%uus)", max_tx_octets,
|
||||
max_tx_time, max_rx_octets, max_rx_time);
|
||||
|
||||
if (!atomic_test_and_clear_bit(conn->flags, BT_CONN_AUTO_DATA_LEN)) {
|
||||
goto done;
|
||||
}
|
||||
/* TODO use those */
|
||||
|
||||
update_conn_param(conn);
|
||||
|
||||
done:
|
||||
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;
|
||||
@@ -1064,22 +1076,21 @@ static void le_phy_update_complete(struct net_buf *buf)
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (BT_FEAT_LE_DLE(bt_dev.le.features) &&
|
||||
if (IS_ENABLED(CONFIG_BT_DATA_LEN_UPDATE) &&
|
||||
BT_FEAT_LE_DLE(bt_dev.le.features) &&
|
||||
BT_FEAT_LE_DLE(conn->le.features)) {
|
||||
int err;
|
||||
|
||||
err = hci_le_set_data_len(conn);
|
||||
if (!err) {
|
||||
atomic_set_bit(conn->flags, BT_CONN_AUTO_DATA_LEN);
|
||||
goto done;
|
||||
}
|
||||
hci_le_set_data_len(conn);
|
||||
}
|
||||
|
||||
update_conn_param(conn);
|
||||
if (IS_ENABLED(CONFIG_BT_PERIPHERAL) &&
|
||||
conn->role == BT_CONN_ROLE_SLAVE) {
|
||||
slave_update_conn_param(conn);
|
||||
}
|
||||
|
||||
done:
|
||||
bt_conn_unref(conn);
|
||||
}
|
||||
#endif /* CONFIG_BT_PHY_UPDATE */
|
||||
|
||||
bool bt_le_conn_params_valid(const struct bt_le_conn_param *param)
|
||||
{
|
||||
@@ -1197,6 +1208,18 @@ static void le_conn_update_complete(struct net_buf *buf)
|
||||
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)) {
|
||||
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);
|
||||
@@ -1574,6 +1597,7 @@ static void conn_complete(struct net_buf *buf)
|
||||
}
|
||||
|
||||
conn->handle = handle;
|
||||
conn->err = 0;
|
||||
conn->encrypt = evt->encr_enabled;
|
||||
update_sec_level_br(conn);
|
||||
bt_conn_set_state(conn, BT_CONN_CONNECTED);
|
||||
@@ -2652,7 +2676,7 @@ static void update_sec_level(struct bt_conn *conn)
|
||||
}
|
||||
|
||||
if (conn->le.keys && (conn->le.keys->flags & BT_KEYS_AUTHENTICATED)) {
|
||||
if (conn->le.keys->keys & BT_KEYS_LTK_P256) {
|
||||
if (conn->le.keys->flags & BT_KEYS_SC) {
|
||||
conn->sec_level = BT_SECURITY_FIPS;
|
||||
} else {
|
||||
conn->sec_level = BT_SECURITY_HIGH;
|
||||
@@ -2913,6 +2937,7 @@ done:
|
||||
}
|
||||
#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;
|
||||
@@ -2943,6 +2968,7 @@ static void le_dhkey_complete(struct net_buf *buf)
|
||||
dh_key_cb = NULL;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_BT_ECC */
|
||||
|
||||
static void hci_reset_complete(struct net_buf *buf)
|
||||
{
|
||||
@@ -3075,6 +3101,8 @@ static int start_le_scan(u8_t scan_type, u16_t interval, u16_t window)
|
||||
}
|
||||
|
||||
set_param.addr_type = BT_ADDR_LE_RANDOM;
|
||||
} else if (set_param.addr_type == BT_ADDR_LE_RANDOM) {
|
||||
set_random_address(&bt_dev.id_addr[0].a);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3121,6 +3149,13 @@ int bt_le_scan_update(bool fast_scan)
|
||||
u16_t interval, window;
|
||||
struct bt_conn *conn;
|
||||
|
||||
/* don't restart scan if we have pending connection */
|
||||
conn = bt_conn_lookup_state_le(NULL, BT_CONN_CONNECT);
|
||||
if (conn) {
|
||||
bt_conn_unref(conn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
conn = bt_conn_lookup_state_le(NULL, BT_CONN_CONNECT_SCAN);
|
||||
if (!conn) {
|
||||
return 0;
|
||||
@@ -3134,8 +3169,8 @@ int bt_le_scan_update(bool fast_scan)
|
||||
interval = BT_GAP_SCAN_FAST_INTERVAL;
|
||||
window = BT_GAP_SCAN_FAST_WINDOW;
|
||||
} else {
|
||||
interval = BT_GAP_SCAN_SLOW_INTERVAL_1;
|
||||
window = BT_GAP_SCAN_SLOW_WINDOW_1;
|
||||
interval = CONFIG_BT_BACKGROUND_SCAN_INTERVAL;
|
||||
window = CONFIG_BT_BACKGROUND_SCAN_WINDOW;
|
||||
}
|
||||
|
||||
return start_le_scan(BT_HCI_LE_SCAN_PASSIVE, interval, window);
|
||||
@@ -3254,24 +3289,30 @@ static void hci_le_meta_event(struct net_buf *buf)
|
||||
case BT_HCI_EVT_LE_CONN_PARAM_REQ:
|
||||
le_conn_param_req(buf);
|
||||
break;
|
||||
#if defined(CONFIG_BT_DATA_LEN_UPDATE)
|
||||
case BT_HCI_EVT_LE_DATA_LEN_CHANGE:
|
||||
le_data_len_change(buf);
|
||||
break;
|
||||
#endif /* CONFIG_BT_DATA_LEN_UPDATE */
|
||||
#if defined(CONFIG_BT_PHY_UPDATE)
|
||||
case BT_HCI_EVT_LE_PHY_UPDATE_COMPLETE:
|
||||
le_phy_update_complete(buf);
|
||||
break;
|
||||
#endif /* CONFIG_BT_PHY_UPDATE */
|
||||
#endif /* CONFIG_BT_CONN */
|
||||
#if defined(CONFIG_BT_SMP)
|
||||
case BT_HCI_EVT_LE_LTK_REQUEST:
|
||||
le_ltk_request(buf);
|
||||
break;
|
||||
#endif /* CONFIG_BT_SMP */
|
||||
#if defined(CONFIG_BT_ECC)
|
||||
case BT_HCI_EVT_LE_P256_PUBLIC_KEY_COMPLETE:
|
||||
le_pkey_complete(buf);
|
||||
break;
|
||||
case BT_HCI_EVT_LE_GENERATE_DHKEY_COMPLETE:
|
||||
le_dhkey_complete(buf);
|
||||
break;
|
||||
#endif /* CONFIG_BT_SMP */
|
||||
#if defined(CONFIG_BT_OBSERVER)
|
||||
case BT_HCI_EVT_LE_ADVERTISING_REPORT:
|
||||
le_adv_report(buf);
|
||||
@@ -3740,12 +3781,14 @@ static int le_set_event_mask(void)
|
||||
mask |= BT_EVT_MASK_LE_CONN_PARAM_REQ;
|
||||
}
|
||||
|
||||
if (BT_FEAT_LE_DLE(bt_dev.le.features)) {
|
||||
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 (BT_FEAT_LE_PHY_2M(bt_dev.le.features) ||
|
||||
BT_FEAT_LE_PHY_CODED(bt_dev.le.features)) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -3759,7 +3802,8 @@ static int le_set_event_mask(void)
|
||||
* If "LE Read Local P-256 Public Key" and "LE Generate DH Key" are
|
||||
* supported we need to enable events generated by those commands.
|
||||
*/
|
||||
if ((bt_dev.supported_commands[34] & 0x02) &&
|
||||
if (IS_ENABLED(CONFIG_BT_ECC) &&
|
||||
(bt_dev.supported_commands[34] & 0x02) &&
|
||||
(bt_dev.supported_commands[34] & 0x04)) {
|
||||
mask |= BT_EVT_MASK_LE_P256_PUBLIC_KEY_COMPLETE;
|
||||
mask |= BT_EVT_MASK_LE_GENERATE_DHKEY_COMPLETE;
|
||||
@@ -3832,6 +3876,7 @@ static int le_init(void)
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -4191,49 +4236,6 @@ int bt_addr_le_create_static(bt_addr_le_t *addr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_setup_id_addr(void)
|
||||
{
|
||||
#if defined(CONFIG_BT_HCI_VS_EXT)
|
||||
/* Check for VS_Read_Static_Addresses support. Only read the
|
||||
* addresses if the user has not already configured one or
|
||||
* more identities (!bt_dev.id_count).
|
||||
*/
|
||||
if (!bt_dev.id_count && (bt_dev.vs_commands[1] & BIT(0))) {
|
||||
struct bt_hci_rp_vs_read_static_addrs *rp;
|
||||
struct net_buf *rsp;
|
||||
int err, i;
|
||||
|
||||
err = bt_hci_cmd_send_sync(BT_HCI_OP_VS_READ_STATIC_ADDRS,
|
||||
NULL, &rsp);
|
||||
if (err) {
|
||||
BT_WARN("Failed to read static addresses");
|
||||
goto generate;
|
||||
}
|
||||
|
||||
rp = (void *)rsp->data;
|
||||
bt_dev.id_count = min(rp->num_addrs, CONFIG_BT_ID_MAX);
|
||||
for (i = 0; i < bt_dev.id_count; i++) {
|
||||
bt_dev.id_addr[i].type = BT_ADDR_LE_RANDOM;
|
||||
bt_addr_copy(&bt_dev.id_addr[i].a, &rp->a[i].bdaddr);
|
||||
}
|
||||
|
||||
net_buf_unref(rsp);
|
||||
|
||||
if (bt_dev.id_count) {
|
||||
return set_random_address(&bt_dev.id_addr[0].a);
|
||||
}
|
||||
|
||||
BT_WARN("No static addresses stored in controller");
|
||||
} else {
|
||||
BT_WARN("Read Static Addresses command not available");
|
||||
}
|
||||
|
||||
generate:
|
||||
#endif
|
||||
|
||||
return bt_id_create(NULL, NULL);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_DEBUG)
|
||||
static const char *ver_str(u8_t ver)
|
||||
{
|
||||
@@ -4867,7 +4869,7 @@ static void id_create(u8_t id, bt_addr_le_t *addr, u8_t *irk)
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_PRIVACY)
|
||||
if (atomic_test_bit(bt_dev.flags, BT_DEV_READY)) {
|
||||
{
|
||||
u8_t zero_irk[16] = { 0 };
|
||||
|
||||
if (irk && memcmp(irk, zero_irk, 16)) {
|
||||
@@ -5005,6 +5007,64 @@ int bt_id_delete(u8_t id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_HCI_VS_EXT)
|
||||
static uint8_t bt_read_static_addr(bt_addr_le_t *addr)
|
||||
{
|
||||
struct bt_hci_rp_vs_read_static_addrs *rp;
|
||||
struct net_buf *rsp;
|
||||
int err, i;
|
||||
u8_t cnt;
|
||||
if (!(bt_dev.vs_commands[1] & BIT(0))) {
|
||||
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;
|
||||
}
|
||||
rp = (void *)rsp->data;
|
||||
cnt = min(rp->num_addrs, CONFIG_BT_ID_MAX);
|
||||
|
||||
for (i = 0; i < cnt; i++) {
|
||||
addr[i].type = BT_ADDR_LE_RANDOM;
|
||||
bt_addr_copy(&addr[i].a, &rp->a[i].bdaddr);
|
||||
}
|
||||
net_buf_unref(rsp);
|
||||
if (!cnt) {
|
||||
BT_WARN("No static addresses stored in controller");
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
#elif defined(CONFIG_BT_CTLR)
|
||||
uint8_t bt_read_static_addr(bt_addr_le_t *addr);
|
||||
#endif /* CONFIG_BT_HCI_VS_EXT */
|
||||
|
||||
int bt_setup_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) {
|
||||
bt_addr_le_t addrs[CONFIG_BT_ID_MAX];
|
||||
|
||||
bt_dev.id_count = bt_read_static_addr(addrs);
|
||||
if (bt_dev.id_count) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < bt_dev.id_count; i++) {
|
||||
id_create(i, &addrs[i], NULL);
|
||||
}
|
||||
|
||||
return set_random_address(&bt_dev.id_addr[0].a);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
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)) {
|
||||
@@ -5559,6 +5619,7 @@ u16_t bt_hci_get_cmd_opcode(struct net_buf *buf)
|
||||
return cmd(buf)->opcode;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_ECC)
|
||||
int bt_pub_key_gen(struct bt_pub_key_cb *new_cb)
|
||||
{
|
||||
struct bt_pub_key_cb *cb;
|
||||
@@ -5644,6 +5705,7 @@ int bt_dh_key_gen(const u8_t remote_pk[64], bt_dh_key_cb_t cb)
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_BT_ECC */
|
||||
|
||||
#if defined(CONFIG_BT_BREDR)
|
||||
int bt_br_oob_get_local(struct bt_br_oob *oob)
|
||||
|
||||
@@ -113,8 +113,9 @@ static u8_t generate_keys(void)
|
||||
/* make sure generated key isn't debug key */
|
||||
} while (memcmp(ecc.private_key, debug_private_key, 32) == 0);
|
||||
#else
|
||||
memcpy(&ecc.pk, debug_public_key, 64);
|
||||
memcpy(ecc.private_key, debug_private_key, 32);
|
||||
sys_memcpy_swap(&ecc.pk, debug_public_key, 32);
|
||||
sys_memcpy_swap(&ecc.pk[32], &debug_public_key[32], 32);
|
||||
sys_memcpy_swap(ecc.private_key, debug_private_key, 32);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ enum {
|
||||
BT_KEYS_DEBUG = BIT(1),
|
||||
BT_KEYS_ID_PENDING_ADD = BIT(2),
|
||||
BT_KEYS_ID_PENDING_DEL = BIT(3),
|
||||
BT_KEYS_SC = BIT(4),
|
||||
};
|
||||
|
||||
struct bt_ltk {
|
||||
|
||||
@@ -719,6 +719,20 @@ static void l2cap_chan_destroy(struct bt_l2cap_chan *chan)
|
||||
}
|
||||
}
|
||||
|
||||
static u16_t le_err_to_result(int err)
|
||||
{
|
||||
switch (err) {
|
||||
case -ENOMEM:
|
||||
return BT_L2CAP_LE_ERR_NO_RESOURCES;
|
||||
case -EACCES:
|
||||
return BT_L2CAP_LE_ERR_AUTHORIZATION;
|
||||
case -EPERM:
|
||||
return BT_L2CAP_LE_ERR_KEY_SIZE;
|
||||
default:
|
||||
return BT_L2CAP_LE_ERR_UNACCEPT_PARAMS;
|
||||
}
|
||||
}
|
||||
|
||||
static void le_conn_req(struct bt_l2cap *l2cap, u8_t ident,
|
||||
struct net_buf *buf)
|
||||
{
|
||||
@@ -728,6 +742,7 @@ static void le_conn_req(struct bt_l2cap *l2cap, u8_t ident,
|
||||
struct bt_l2cap_le_conn_req *req = (void *)buf->data;
|
||||
struct bt_l2cap_le_conn_rsp *rsp;
|
||||
u16_t psm, scid, mtu, mps, credits;
|
||||
int err;
|
||||
|
||||
if (buf->len < sizeof(*req)) {
|
||||
BT_ERR("Too small LE conn req packet size");
|
||||
@@ -757,34 +772,33 @@ static void le_conn_req(struct bt_l2cap *l2cap, u8_t ident,
|
||||
/* Check if there is a server registered */
|
||||
server = l2cap_server_lookup_psm(psm);
|
||||
if (!server) {
|
||||
rsp->result = sys_cpu_to_le16(BT_L2CAP_ERR_PSM_NOT_SUPP);
|
||||
rsp->result = sys_cpu_to_le16(BT_L2CAP_LE_ERR_PSM_NOT_SUPP);
|
||||
goto rsp;
|
||||
}
|
||||
|
||||
/* Check if connection has minimum required security level */
|
||||
if (conn->sec_level < server->sec_level) {
|
||||
rsp->result = sys_cpu_to_le16(BT_L2CAP_ERR_AUTHENTICATION);
|
||||
rsp->result = sys_cpu_to_le16(BT_L2CAP_LE_ERR_AUTHENTICATION);
|
||||
goto rsp;
|
||||
}
|
||||
|
||||
if (!L2CAP_LE_CID_IS_DYN(scid)) {
|
||||
rsp->result = sys_cpu_to_le16(BT_L2CAP_ERR_INVALID_SCID);
|
||||
rsp->result = sys_cpu_to_le16(BT_L2CAP_LE_ERR_INVALID_SCID);
|
||||
goto rsp;
|
||||
}
|
||||
|
||||
chan = bt_l2cap_le_lookup_tx_cid(conn, scid);
|
||||
if (chan) {
|
||||
rsp->result = sys_cpu_to_le16(BT_L2CAP_ERR_SCID_IN_USE);
|
||||
rsp->result = sys_cpu_to_le16(BT_L2CAP_LE_ERR_SCID_IN_USE);
|
||||
goto rsp;
|
||||
}
|
||||
|
||||
/* Request server to accept the new connection and allocate the
|
||||
* channel.
|
||||
*
|
||||
* TODO: Handle different errors, it may be required to respond async.
|
||||
*/
|
||||
if (server->accept(conn, &chan) < 0) {
|
||||
rsp->result = sys_cpu_to_le16(BT_L2CAP_ERR_NO_RESOURCES);
|
||||
err = server->accept(conn, &chan);
|
||||
if (err < 0) {
|
||||
rsp->result = sys_cpu_to_le16(le_err_to_result(err));
|
||||
goto rsp;
|
||||
}
|
||||
|
||||
@@ -820,9 +834,9 @@ static void le_conn_req(struct bt_l2cap *l2cap, u8_t ident,
|
||||
rsp->mps = sys_cpu_to_le16(ch->rx.mps);
|
||||
rsp->mtu = sys_cpu_to_le16(ch->rx.mtu);
|
||||
rsp->credits = sys_cpu_to_le16(ch->rx.init_credits);
|
||||
rsp->result = BT_L2CAP_SUCCESS;
|
||||
rsp->result = BT_L2CAP_LE_SUCCESS;
|
||||
} else {
|
||||
rsp->result = sys_cpu_to_le16(BT_L2CAP_ERR_NO_RESOURCES);
|
||||
rsp->result = sys_cpu_to_le16(BT_L2CAP_LE_ERR_NO_RESOURCES);
|
||||
}
|
||||
rsp:
|
||||
bt_l2cap_send(conn, BT_L2CAP_CID_LE_SIG, buf);
|
||||
@@ -896,13 +910,13 @@ static void le_disconn_req(struct bt_l2cap *l2cap, u8_t ident,
|
||||
static int l2cap_change_security(struct bt_l2cap_le_chan *chan, u16_t err)
|
||||
{
|
||||
switch (err) {
|
||||
case BT_L2CAP_ERR_ENCRYPTION:
|
||||
case BT_L2CAP_LE_ERR_ENCRYPTION:
|
||||
if (chan->chan.required_sec_level >= BT_SECURITY_MEDIUM) {
|
||||
return -EALREADY;
|
||||
}
|
||||
chan->chan.required_sec_level = BT_SECURITY_MEDIUM;
|
||||
break;
|
||||
case BT_L2CAP_ERR_AUTHENTICATION:
|
||||
case BT_L2CAP_LE_ERR_AUTHENTICATION:
|
||||
if (chan->chan.required_sec_level < BT_SECURITY_MEDIUM) {
|
||||
chan->chan.required_sec_level = BT_SECURITY_MEDIUM;
|
||||
} else if (chan->chan.required_sec_level < BT_SECURITY_HIGH) {
|
||||
@@ -943,9 +957,9 @@ static void le_conn_rsp(struct bt_l2cap *l2cap, u8_t ident,
|
||||
mtu, mps, credits, result);
|
||||
|
||||
/* Keep the channel in case of security errors */
|
||||
if (result == BT_L2CAP_SUCCESS ||
|
||||
result == BT_L2CAP_ERR_AUTHENTICATION ||
|
||||
result == BT_L2CAP_ERR_ENCRYPTION) {
|
||||
if (result == BT_L2CAP_LE_SUCCESS ||
|
||||
result == BT_L2CAP_LE_ERR_AUTHENTICATION ||
|
||||
result == BT_L2CAP_LE_ERR_ENCRYPTION) {
|
||||
chan = l2cap_lookup_ident(conn, ident);
|
||||
} else {
|
||||
chan = l2cap_remove_ident(conn, ident);
|
||||
@@ -963,7 +977,7 @@ static void le_conn_rsp(struct bt_l2cap *l2cap, u8_t ident,
|
||||
chan->chan.ident = 0;
|
||||
|
||||
switch (result) {
|
||||
case BT_L2CAP_SUCCESS:
|
||||
case BT_L2CAP_LE_SUCCESS:
|
||||
chan->tx.cid = dcid;
|
||||
chan->tx.mtu = mtu;
|
||||
chan->tx.mps = mps;
|
||||
@@ -980,8 +994,8 @@ static void le_conn_rsp(struct bt_l2cap *l2cap, u8_t ident,
|
||||
l2cap_chan_rx_give_credits(chan, chan->rx.init_credits);
|
||||
|
||||
break;
|
||||
case BT_L2CAP_ERR_AUTHENTICATION:
|
||||
case BT_L2CAP_ERR_ENCRYPTION:
|
||||
case BT_L2CAP_LE_ERR_AUTHENTICATION:
|
||||
case BT_L2CAP_LE_ERR_ENCRYPTION:
|
||||
/* If security needs changing wait it to be completed */
|
||||
if (l2cap_change_security(chan, result) == 0) {
|
||||
return;
|
||||
|
||||
@@ -164,16 +164,16 @@ struct bt_l2cap_le_conn_req {
|
||||
} __packed;
|
||||
|
||||
/* valid results in conn response on LE */
|
||||
#define BT_L2CAP_SUCCESS 0x0000
|
||||
#define BT_L2CAP_ERR_PSM_NOT_SUPP 0x0002
|
||||
#define BT_L2CAP_ERR_NO_RESOURCES 0x0004
|
||||
#define BT_L2CAP_ERR_AUTHENTICATION 0x0005
|
||||
#define BT_L2CAP_ERR_AUTHORIZATION 0x0006
|
||||
#define BT_L2CAP_ERR_KEY_SIZE 0x0007
|
||||
#define BT_L2CAP_ERR_ENCRYPTION 0x0008
|
||||
#define BT_L2CAP_ERR_INVALID_SCID 0x0009
|
||||
#define BT_L2CAP_ERR_SCID_IN_USE 0x000A
|
||||
#define BT_L2CAP_ERR_UNACCEPT_PARAMS 0x000B
|
||||
#define BT_L2CAP_LE_SUCCESS 0x0000
|
||||
#define BT_L2CAP_LE_ERR_PSM_NOT_SUPP 0x0002
|
||||
#define BT_L2CAP_LE_ERR_NO_RESOURCES 0x0004
|
||||
#define BT_L2CAP_LE_ERR_AUTHENTICATION 0x0005
|
||||
#define BT_L2CAP_LE_ERR_AUTHORIZATION 0x0006
|
||||
#define BT_L2CAP_LE_ERR_KEY_SIZE 0x0007
|
||||
#define BT_L2CAP_LE_ERR_ENCRYPTION 0x0008
|
||||
#define BT_L2CAP_LE_ERR_INVALID_SCID 0x0009
|
||||
#define BT_L2CAP_LE_ERR_SCID_IN_USE 0x000A
|
||||
#define BT_L2CAP_LE_ERR_UNACCEPT_PARAMS 0x000B
|
||||
|
||||
#define BT_L2CAP_LE_CONN_RSP 0x15
|
||||
struct bt_l2cap_le_conn_rsp {
|
||||
|
||||
@@ -22,6 +22,7 @@ if BT_MESH
|
||||
# Virtual option enabled whenever Generic Provisioning layer is needed
|
||||
config BT_MESH_PROV
|
||||
bool
|
||||
select BT_ECC
|
||||
|
||||
config BT_MESH_PB_ADV
|
||||
bool "Provisioning support using the advertising bearer (PB-ADV)"
|
||||
|
||||
@@ -33,8 +33,8 @@
|
||||
#define ADV_SCAN_UNIT(_ms) ((_ms) * 8 / 5)
|
||||
|
||||
/* Window and Interval are equal for continuous scanning */
|
||||
#define MESH_SCAN_INTERVAL_MS 10
|
||||
#define MESH_SCAN_WINDOW_MS 10
|
||||
#define MESH_SCAN_INTERVAL_MS 30
|
||||
#define MESH_SCAN_WINDOW_MS 30
|
||||
#define MESH_SCAN_INTERVAL ADV_SCAN_UNIT(MESH_SCAN_INTERVAL_MS)
|
||||
#define MESH_SCAN_WINDOW ADV_SCAN_UNIT(MESH_SCAN_WINDOW_MS)
|
||||
|
||||
|
||||
@@ -833,13 +833,7 @@ int bt_mesh_friend_req(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf)
|
||||
}
|
||||
|
||||
old_friend = sys_be16_to_cpu(msg->prev_addr);
|
||||
if (BT_MESH_ADDR_IS_UNICAST(old_friend)) {
|
||||
frnd = bt_mesh_friend_find(rx->sub->net_idx, old_friend,
|
||||
true, false);
|
||||
} else {
|
||||
frnd = bt_mesh_friend_find(rx->sub->net_idx, rx->ctx.addr,
|
||||
true, false);
|
||||
}
|
||||
frnd = bt_mesh_friend_find(rx->sub->net_idx, rx->ctx.addr, true, false);
|
||||
|
||||
if (frnd) {
|
||||
BT_WARN("Existing LPN re-requesting Friendship");
|
||||
|
||||
@@ -1030,7 +1030,7 @@ static void store_pending_hb_pub(void)
|
||||
if (pub->dst == BT_MESH_ADDR_UNASSIGNED) {
|
||||
str = NULL;
|
||||
} else {
|
||||
val.indefinite = (pub->count = 0xffff);
|
||||
val.indefinite = (pub->count == 0xffff);
|
||||
val.dst = pub->dst;
|
||||
val.period = pub->period;
|
||||
val.ttl = pub->ttl;
|
||||
|
||||
@@ -72,13 +72,19 @@
|
||||
|
||||
#define BT_SMP_AUTH_MASK 0x07
|
||||
|
||||
#if defined(CONFIG_BT_BONDABLE)
|
||||
#define BT_SMP_AUTH_BONDING_FLAGS BT_SMP_AUTH_BONDING
|
||||
#else
|
||||
#define BT_SMP_AUTH_BONDING_FLAGS 0
|
||||
#endif /* CONFIG_BT_BONDABLE */
|
||||
|
||||
#if defined(CONFIG_BT_BREDR)
|
||||
#define BT_SMP_AUTH_MASK_SC 0x2f
|
||||
#define BT_SMP_AUTH_DEFAULT (BT_SMP_AUTH_BONDING | BT_SMP_AUTH_SC |\
|
||||
#define BT_SMP_AUTH_DEFAULT (BT_SMP_AUTH_BONDING_FLAGS | BT_SMP_AUTH_SC |\
|
||||
BT_SMP_AUTH_CT2)
|
||||
#else
|
||||
#define BT_SMP_AUTH_MASK_SC 0x0f
|
||||
#define BT_SMP_AUTH_DEFAULT (BT_SMP_AUTH_BONDING | BT_SMP_AUTH_SC)
|
||||
#define BT_SMP_AUTH_DEFAULT (BT_SMP_AUTH_BONDING_FLAGS | BT_SMP_AUTH_SC)
|
||||
#endif
|
||||
|
||||
enum pairing_method {
|
||||
@@ -243,6 +249,7 @@ static struct bt_smp_br bt_smp_br_pool[CONFIG_BT_MAX_CONN];
|
||||
#endif /* CONFIG_BT_BREDR */
|
||||
|
||||
static struct bt_smp bt_smp_pool[CONFIG_BT_MAX_CONN];
|
||||
static bool bondable = IS_ENABLED(CONFIG_BT_BONDABLE);
|
||||
static bool sc_supported;
|
||||
static bool sc_local_pkey_valid;
|
||||
static u8_t sc_public_key[64];
|
||||
@@ -2261,6 +2268,11 @@ static int smp_init(struct bt_smp *smp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bt_set_bondable(bool enable)
|
||||
{
|
||||
bondable = enable;
|
||||
}
|
||||
|
||||
static u8_t get_auth(u8_t auth)
|
||||
{
|
||||
if (sc_supported) {
|
||||
@@ -2275,6 +2287,12 @@ static u8_t get_auth(u8_t auth)
|
||||
auth |= BT_SMP_AUTH_MITM;
|
||||
}
|
||||
|
||||
if (bondable) {
|
||||
auth |= BT_SMP_AUTH_BONDING;
|
||||
} else {
|
||||
auth &= ~BT_SMP_AUTH_BONDING;
|
||||
}
|
||||
|
||||
return auth;
|
||||
}
|
||||
|
||||
@@ -4460,15 +4478,20 @@ void bt_smp_update_keys(struct bt_conn *conn)
|
||||
* exclusive with legacy pairing. Other keys are added on keys
|
||||
* distribution.
|
||||
*/
|
||||
if (atomic_test_bit(smp->flags, SMP_FLAG_SC) &&
|
||||
atomic_test_bit(smp->flags, SMP_FLAG_BOND)) {
|
||||
bt_keys_add_type(conn->le.keys, BT_KEYS_LTK_P256);
|
||||
memcpy(conn->le.keys->ltk.val, smp->tk,
|
||||
sizeof(conn->le.keys->ltk.val));
|
||||
memset(conn->le.keys->ltk.rand, 0,
|
||||
sizeof(conn->le.keys->ltk.rand));
|
||||
memset(conn->le.keys->ltk.ediv, 0,
|
||||
sizeof(conn->le.keys->ltk.ediv));
|
||||
if (atomic_test_bit(smp->flags, SMP_FLAG_SC)) {
|
||||
conn->le.keys->flags |= BT_KEYS_SC;
|
||||
|
||||
if (atomic_test_bit(smp->flags, SMP_FLAG_BOND)) {
|
||||
bt_keys_add_type(conn->le.keys, BT_KEYS_LTK_P256);
|
||||
memcpy(conn->le.keys->ltk.val, smp->tk,
|
||||
sizeof(conn->le.keys->ltk.val));
|
||||
(void)memset(conn->le.keys->ltk.rand, 0,
|
||||
sizeof(conn->le.keys->ltk.rand));
|
||||
(void)memset(conn->le.keys->ltk.ediv, 0,
|
||||
sizeof(conn->le.keys->ltk.ediv));
|
||||
}
|
||||
} else {
|
||||
conn->le.keys->flags &= ~BT_KEYS_SC;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1142,6 +1142,26 @@ static int cmd_security(int argc, char *argv[])
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_bondable(int argc, char *argv[])
|
||||
{
|
||||
const char *bondable;
|
||||
|
||||
if (argc < 2) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bondable = argv[1];
|
||||
if (!strcmp(bondable, "on")) {
|
||||
bt_set_bondable(true);
|
||||
} else if (!strcmp(bondable, "off")) {
|
||||
bt_set_bondable(false);
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void auth_passkey_display(struct bt_conn *conn, unsigned int passkey)
|
||||
{
|
||||
char addr[BT_ADDR_LE_STR_LEN];
|
||||
@@ -2179,6 +2199,7 @@ static const struct shell_cmd bt_commands[] = {
|
||||
{ "clear", cmd_clear },
|
||||
#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
|
||||
{ "security", cmd_security, "<security level: 0, 1, 2, 3>" },
|
||||
{ "bondable", cmd_bondable, "<bondable: on, off>" },
|
||||
{ "auth", cmd_auth,
|
||||
"<auth method: all, input, display, yesno, confirm, none>" },
|
||||
{ "auth-cancel", cmd_auth_cancel, HELP_NONE },
|
||||
|
||||
@@ -5,8 +5,8 @@ CONFIG_BT_CTLR_CONN_PARAM_REQ=n
|
||||
CONFIG_BT_CTLR_LE_PING=n
|
||||
CONFIG_BT_CTLR_PRIVACY=n
|
||||
CONFIG_BT_CTLR_EXT_SCAN_FP=n
|
||||
CONFIG_BT_CTLR_DATA_LENGTH=n
|
||||
CONFIG_BT_CTLR_PHY=n
|
||||
CONFIG_BT_DATA_LEN_UPDATE=n
|
||||
CONFIG_BT_PHY_UPDATE=n
|
||||
CONFIG_BT_CTLR_CHAN_SEL_2=n
|
||||
CONFIG_BT_CTLR_MIN_USED_CHAN=n
|
||||
CONFIG_BT_CTLR_ADV_EXT=n
|
||||
|
||||
@@ -5,8 +5,8 @@ CONFIG_BT_CTLR_CONN_PARAM_REQ=y
|
||||
CONFIG_BT_CTLR_LE_PING=y
|
||||
CONFIG_BT_CTLR_PRIVACY=y
|
||||
CONFIG_BT_CTLR_EXT_SCAN_FP=y
|
||||
CONFIG_BT_CTLR_DATA_LENGTH=y
|
||||
CONFIG_BT_CTLR_PHY=y
|
||||
CONFIG_BT_DATA_LEN_UPDATE=y
|
||||
CONFIG_BT_PHY_UPDATE=y
|
||||
CONFIG_BT_CTLR_CHAN_SEL_2=y
|
||||
CONFIG_BT_CTLR_MIN_USED_CHAN=y
|
||||
CONFIG_BT_CTLR_ADV_EXT=y
|
||||
|
||||
@@ -5,8 +5,8 @@ CONFIG_BT_CTLR_CONN_PARAM_REQ=n
|
||||
CONFIG_BT_CTLR_LE_PING=n
|
||||
CONFIG_BT_CTLR_PRIVACY=n
|
||||
CONFIG_BT_CTLR_EXT_SCAN_FP=n
|
||||
CONFIG_BT_CTLR_DATA_LENGTH=n
|
||||
CONFIG_BT_CTLR_PHY=n
|
||||
CONFIG_BT_DATA_LEN_UPDATE=n
|
||||
CONFIG_BT_PHY_UPDATE=n
|
||||
CONFIG_BT_CTLR_CHAN_SEL_2=n
|
||||
CONFIG_BT_CTLR_MIN_USED_CHAN=n
|
||||
CONFIG_BT_CTLR_ADV_EXT=n
|
||||
|
||||
@@ -8,8 +8,8 @@ CONFIG_BT_BROADCASTER=y
|
||||
CONFIG_BT_CTLR_DUP_FILTER_LEN=0
|
||||
CONFIG_BT_CTLR_LE_ENC=n
|
||||
CONFIG_BT_CTLR_LE_PING=n
|
||||
CONFIG_BT_CTLR_DATA_LENGTH=n
|
||||
CONFIG_BT_CTLR_PHY=n
|
||||
CONFIG_BT_DATA_LEN_UPDATE=n
|
||||
CONFIG_BT_PHY_UPDATE=n
|
||||
CONFIG_BT_CTLR_CHAN_SEL_2=n
|
||||
CONFIG_BT_CTLR_MIN_USED_CHAN=n
|
||||
CONFIG_BT_CTLR_ADV_EXT=n
|
||||
|
||||
@@ -8,8 +8,8 @@ CONFIG_BT_BROADCASTER=y
|
||||
CONFIG_BT_CTLR_DUP_FILTER_LEN=0
|
||||
CONFIG_BT_CTLR_LE_ENC=n
|
||||
CONFIG_BT_CTLR_LE_PING=n
|
||||
CONFIG_BT_CTLR_DATA_LENGTH=n
|
||||
CONFIG_BT_CTLR_PHY=n
|
||||
CONFIG_BT_DATA_LEN_UPDATE=n
|
||||
CONFIG_BT_PHY_UPDATE=n
|
||||
CONFIG_BT_CTLR_CHAN_SEL_2=n
|
||||
CONFIG_BT_CTLR_MIN_USED_CHAN=n
|
||||
CONFIG_BT_CTLR_ADV_EXT=n
|
||||
|
||||
@@ -8,8 +8,8 @@ CONFIG_BT_BROADCASTER=y
|
||||
CONFIG_BT_CTLR_DUP_FILTER_LEN=0
|
||||
CONFIG_BT_CTLR_LE_ENC=n
|
||||
CONFIG_BT_CTLR_LE_PING=n
|
||||
CONFIG_BT_CTLR_DATA_LENGTH=n
|
||||
CONFIG_BT_CTLR_PHY=n
|
||||
CONFIG_BT_DATA_LEN_UPDATE=n
|
||||
CONFIG_BT_PHY_UPDATE=n
|
||||
CONFIG_BT_CTLR_CHAN_SEL_2=n
|
||||
CONFIG_BT_CTLR_MIN_USED_CHAN=n
|
||||
CONFIG_BT_CTLR_ADV_EXT=n
|
||||
|
||||
@@ -8,8 +8,8 @@ CONFIG_BT_BROADCASTER=y
|
||||
CONFIG_BT_CTLR_DUP_FILTER_LEN=0
|
||||
CONFIG_BT_CTLR_LE_ENC=n
|
||||
CONFIG_BT_CTLR_LE_PING=n
|
||||
CONFIG_BT_CTLR_DATA_LENGTH=n
|
||||
CONFIG_BT_CTLR_PHY=n
|
||||
CONFIG_BT_DATA_LEN_UPDATE=n
|
||||
CONFIG_BT_PHY_UPDATE=n
|
||||
CONFIG_BT_CTLR_CHAN_SEL_2=n
|
||||
CONFIG_BT_CTLR_MIN_USED_CHAN=n
|
||||
CONFIG_BT_CTLR_ADV_EXT=n
|
||||
|
||||
@@ -16,8 +16,8 @@ CONFIG_BT_BROADCASTER=y
|
||||
|
||||
CONFIG_BT_CTLR_LE_ENC=n
|
||||
CONFIG_BT_CTLR_LE_PING=n
|
||||
CONFIG_BT_CTLR_DATA_LENGTH=n
|
||||
CONFIG_BT_CTLR_PHY=n
|
||||
CONFIG_BT_DATA_LEN_UPDATE=n
|
||||
CONFIG_BT_PHY_UPDATE=n
|
||||
CONFIG_BT_CTLR_CHAN_SEL_2=n
|
||||
CONFIG_BT_CTLR_MIN_USED_CHAN=n
|
||||
CONFIG_BT_CTLR_ADV_EXT=n
|
||||
|
||||
@@ -24,8 +24,8 @@ CONFIG_BT_BROADCASTER=y
|
||||
|
||||
CONFIG_BT_CTLR_LE_ENC=n
|
||||
CONFIG_BT_CTLR_LE_PING=n
|
||||
CONFIG_BT_CTLR_DATA_LENGTH=n
|
||||
CONFIG_BT_CTLR_PHY=n
|
||||
CONFIG_BT_DATA_LEN_UPDATE=n
|
||||
CONFIG_BT_PHY_UPDATE=n
|
||||
CONFIG_BT_CTLR_CHAN_SEL_2=n
|
||||
CONFIG_BT_CTLR_MIN_USED_CHAN=n
|
||||
CONFIG_BT_CTLR_ADV_EXT=n
|
||||
|
||||
@@ -8,8 +8,8 @@ CONFIG_BT_BROADCASTER=y
|
||||
CONFIG_BT_CTLR_DUP_FILTER_LEN=0
|
||||
CONFIG_BT_CTLR_LE_ENC=n
|
||||
CONFIG_BT_CTLR_LE_PING=n
|
||||
CONFIG_BT_CTLR_DATA_LENGTH=n
|
||||
CONFIG_BT_CTLR_PHY=n
|
||||
CONFIG_BT_DATA_LEN_UPDATE=n
|
||||
CONFIG_BT_PHY_UPDATE=n
|
||||
CONFIG_BT_CTLR_CHAN_SEL_2=n
|
||||
CONFIG_BT_CTLR_MIN_USED_CHAN=n
|
||||
CONFIG_BT_CTLR_ADV_EXT=n
|
||||
|
||||
@@ -8,8 +8,8 @@ CONFIG_BT_BROADCASTER=y
|
||||
CONFIG_BT_CTLR_DUP_FILTER_LEN=0
|
||||
CONFIG_BT_CTLR_LE_ENC=n
|
||||
CONFIG_BT_CTLR_LE_PING=n
|
||||
CONFIG_BT_CTLR_DATA_LENGTH=n
|
||||
CONFIG_BT_CTLR_PHY=n
|
||||
CONFIG_BT_DATA_LEN_UPDATE=n
|
||||
CONFIG_BT_PHY_UPDATE=n
|
||||
CONFIG_BT_CTLR_CHAN_SEL_2=n
|
||||
CONFIG_BT_CTLR_MIN_USED_CHAN=n
|
||||
CONFIG_BT_CTLR_ADV_EXT=n
|
||||
|
||||
@@ -8,8 +8,8 @@ CONFIG_BT_BROADCASTER=y
|
||||
CONFIG_BT_CTLR_DUP_FILTER_LEN=0
|
||||
CONFIG_BT_CTLR_LE_ENC=n
|
||||
CONFIG_BT_CTLR_LE_PING=n
|
||||
CONFIG_BT_CTLR_DATA_LENGTH=n
|
||||
CONFIG_BT_CTLR_PHY=n
|
||||
CONFIG_BT_DATA_LEN_UPDATE=n
|
||||
CONFIG_BT_PHY_UPDATE=n
|
||||
CONFIG_BT_CTLR_CHAN_SEL_2=n
|
||||
CONFIG_BT_CTLR_MIN_USED_CHAN=n
|
||||
CONFIG_BT_CTLR_ADV_EXT=n
|
||||
|
||||
@@ -25,8 +25,8 @@ CONFIG_BT_DEVICE_NAME="Zephyr Mesh"
|
||||
CONFIG_BT_CTLR_DUP_FILTER_LEN=0
|
||||
CONFIG_BT_CTLR_LE_ENC=n
|
||||
CONFIG_BT_CTLR_LE_PING=n
|
||||
CONFIG_BT_CTLR_DATA_LENGTH=n
|
||||
CONFIG_BT_CTLR_PHY=n
|
||||
CONFIG_BT_DATA_LEN_UPDATE=n
|
||||
CONFIG_BT_PHY_UPDATE=n
|
||||
CONFIG_BT_CTLR_CHAN_SEL_2=n
|
||||
CONFIG_BT_CTLR_MIN_USED_CHAN=n
|
||||
CONFIG_BT_CTLR_ADV_EXT=n
|
||||
|
||||
Reference in New Issue
Block a user