2018-12-18 05:48:20 +01:00
|
|
|
/*
|
2020-03-17 19:30:46 +05:30
|
|
|
* Copyright (c) 2018-2020 Nordic Semiconductor ASA
|
2018-12-18 05:48:20 +01:00
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <zephyr.h>
|
2020-08-19 10:09:58 +05:30
|
|
|
#include <soc.h>
|
2018-12-18 05:48:20 +01:00
|
|
|
#include <bluetooth/hci.h>
|
2019-06-26 10:33:41 -04:00
|
|
|
#include <sys/byteorder.h>
|
2018-12-18 05:48:20 +01:00
|
|
|
|
|
|
|
#include "util/util.h"
|
|
|
|
#include "util/memq.h"
|
2019-05-09 18:39:26 +05:30
|
|
|
#include "util/mayfly.h"
|
2018-12-18 05:48:20 +01:00
|
|
|
|
2020-08-19 10:09:58 +05:30
|
|
|
#include "hal/cpu.h"
|
2018-12-18 05:48:20 +01:00
|
|
|
#include "hal/ccm.h"
|
2020-06-15 20:43:54 +05:30
|
|
|
#include "hal/radio.h"
|
|
|
|
#include "hal/ticker.h"
|
2019-10-22 13:13:24 +02:00
|
|
|
|
2018-12-18 05:48:20 +01:00
|
|
|
#include "ticker/ticker.h"
|
|
|
|
|
|
|
|
#include "pdu.h"
|
|
|
|
#include "ll.h"
|
|
|
|
#include "ll_feat.h"
|
2020-01-27 12:52:04 +01:00
|
|
|
#include "ll_settings.h"
|
2018-12-18 05:48:20 +01:00
|
|
|
|
|
|
|
#include "lll.h"
|
|
|
|
#include "lll_vendor.h"
|
|
|
|
#include "lll_clock.h"
|
2019-05-09 18:39:26 +05:30
|
|
|
#include "lll_adv.h"
|
2018-12-18 05:48:20 +01:00
|
|
|
#include "lll_scan.h"
|
|
|
|
#include "lll_conn.h"
|
|
|
|
#include "lll_master.h"
|
2019-05-09 18:39:26 +05:30
|
|
|
#include "lll_filter.h"
|
2018-12-18 05:48:20 +01:00
|
|
|
#include "lll_tim_internal.h"
|
|
|
|
|
2019-05-09 18:39:26 +05:30
|
|
|
#include "ull_adv_types.h"
|
2018-12-18 05:48:20 +01:00
|
|
|
#include "ull_scan_types.h"
|
|
|
|
#include "ull_conn_types.h"
|
2019-05-09 18:39:26 +05:30
|
|
|
#include "ull_filter.h"
|
2018-12-18 05:48:20 +01:00
|
|
|
|
|
|
|
#include "ull_internal.h"
|
2020-02-07 15:10:30 +05:30
|
|
|
#include "ull_chan_internal.h"
|
2018-12-18 05:48:20 +01:00
|
|
|
#include "ull_scan_internal.h"
|
|
|
|
#include "ull_conn_internal.h"
|
|
|
|
#include "ull_master_internal.h"
|
|
|
|
|
2019-11-07 11:39:45 +05:30
|
|
|
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
|
|
|
|
#define LOG_MODULE_NAME bt_ctlr_ull_master
|
2018-12-18 05:48:20 +01:00
|
|
|
#include "common/log.h"
|
|
|
|
#include "hal/debug.h"
|
|
|
|
|
2020-05-27 11:26:57 -05:00
|
|
|
static void ticker_op_stop_scan_cb(uint32_t status, void *params);
|
|
|
|
static void ticker_op_cb(uint32_t status, void *params);
|
2020-03-17 19:30:46 +05:30
|
|
|
static inline void conn_release(struct ll_scan_set *scan);
|
2018-12-18 05:48:20 +01:00
|
|
|
|
2020-04-14 17:22:07 +05:30
|
|
|
#if defined(CONFIG_BT_CTLR_ADV_EXT)
|
|
|
|
uint8_t ll_create_connection(uint16_t scan_interval, uint16_t scan_window,
|
|
|
|
uint8_t filter_policy, uint8_t peer_addr_type,
|
2020-05-04 14:21:40 +05:30
|
|
|
uint8_t const *const peer_addr, uint8_t own_addr_type,
|
2020-04-14 17:22:07 +05:30
|
|
|
uint16_t interval, uint16_t latency, uint16_t timeout,
|
|
|
|
uint8_t phy)
|
|
|
|
#else /* !CONFIG_BT_CTLR_ADV_EXT */
|
2020-05-27 11:26:57 -05:00
|
|
|
uint8_t ll_create_connection(uint16_t scan_interval, uint16_t scan_window,
|
|
|
|
uint8_t filter_policy, uint8_t peer_addr_type,
|
2020-05-04 14:21:40 +05:30
|
|
|
uint8_t const *const peer_addr, uint8_t own_addr_type,
|
2020-05-27 11:26:57 -05:00
|
|
|
uint16_t interval, uint16_t latency, uint16_t timeout)
|
2020-04-14 17:22:07 +05:30
|
|
|
#endif /* !CONFIG_BT_CTLR_ADV_EXT */
|
2018-12-18 05:48:20 +01:00
|
|
|
{
|
|
|
|
struct lll_conn *conn_lll;
|
|
|
|
struct ll_scan_set *scan;
|
2020-05-27 11:26:57 -05:00
|
|
|
uint32_t conn_interval_us;
|
2018-12-18 05:48:20 +01:00
|
|
|
struct lll_scan *lll;
|
|
|
|
struct ll_conn *conn;
|
|
|
|
memq_link_t *link;
|
2020-05-27 11:26:57 -05:00
|
|
|
uint8_t hop;
|
2020-03-17 19:30:46 +05:30
|
|
|
int err;
|
2018-12-18 05:48:20 +01:00
|
|
|
|
2020-04-14 17:22:07 +05:30
|
|
|
scan = ull_scan_is_disabled_get(SCAN_HANDLE_1M);
|
2018-12-18 05:48:20 +01:00
|
|
|
if (!scan) {
|
|
|
|
return BT_HCI_ERR_CMD_DISALLOWED;
|
|
|
|
}
|
|
|
|
|
2020-04-14 17:22:07 +05:30
|
|
|
#if defined(CONFIG_BT_CTLR_ADV_EXT)
|
|
|
|
#if defined(CONFIG_BT_CTLR_PHY_CODED)
|
|
|
|
struct ll_scan_set *scan_coded;
|
|
|
|
struct lll_scan *lll_coded;
|
|
|
|
|
|
|
|
scan_coded = ull_scan_is_disabled_get(SCAN_HANDLE_PHY_CODED);
|
|
|
|
if (!scan_coded) {
|
|
|
|
return BT_HCI_ERR_CMD_DISALLOWED;
|
|
|
|
}
|
|
|
|
|
2018-12-18 05:48:20 +01:00
|
|
|
lll = &scan->lll;
|
2020-04-14 17:22:07 +05:30
|
|
|
lll_coded = &scan_coded->lll;
|
|
|
|
|
|
|
|
if (phy & BT_HCI_LE_EXT_SCAN_PHY_CODED) {
|
|
|
|
if (!lll_coded->conn) {
|
|
|
|
lll_coded->conn = lll->conn;
|
|
|
|
}
|
|
|
|
scan = scan_coded;
|
|
|
|
lll = lll_coded;
|
|
|
|
} else {
|
|
|
|
if (!lll->conn) {
|
|
|
|
lll->conn = lll_coded->conn;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#else /* !CONFIG_BT_CTLR_PHY_CODED */
|
|
|
|
if (phy & ~BT_HCI_LE_EXT_SCAN_PHY_1M) {
|
2018-12-18 05:48:20 +01:00
|
|
|
return BT_HCI_ERR_CMD_DISALLOWED;
|
|
|
|
}
|
|
|
|
|
2020-04-14 17:22:07 +05:30
|
|
|
lll = &scan->lll;
|
|
|
|
|
|
|
|
#endif /* !CONFIG_BT_CTLR_PHY_CODED */
|
|
|
|
|
|
|
|
lll->phy = phy;
|
|
|
|
|
|
|
|
#else /* !CONFIG_BT_CTLR_ADV_EXT */
|
|
|
|
lll = &scan->lll;
|
|
|
|
#endif /* !CONFIG_BT_CTLR_ADV_EXT */
|
|
|
|
|
|
|
|
if (lll->conn) {
|
|
|
|
goto conn_is_valid;
|
|
|
|
}
|
|
|
|
|
2018-12-18 05:48:20 +01:00
|
|
|
link = ll_rx_link_alloc();
|
|
|
|
if (!link) {
|
|
|
|
return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
|
|
|
|
}
|
|
|
|
|
|
|
|
conn = ll_conn_acquire();
|
|
|
|
if (!conn) {
|
|
|
|
ll_rx_link_release(link);
|
|
|
|
|
|
|
|
return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
|
|
|
|
}
|
|
|
|
|
2019-05-09 18:39:26 +05:30
|
|
|
ull_scan_params_set(lll, 0, scan_interval, scan_window, filter_policy);
|
2018-12-18 05:48:20 +01:00
|
|
|
|
|
|
|
lll->adv_addr_type = peer_addr_type;
|
2019-05-09 18:39:26 +05:30
|
|
|
memcpy(lll->adv_addr, peer_addr, BDADDR_SIZE);
|
2018-12-18 05:48:20 +01:00
|
|
|
lll->conn_timeout = timeout;
|
|
|
|
lll->conn_ticks_slot = 0; /* TODO: */
|
|
|
|
|
|
|
|
conn_lll = &conn->lll;
|
|
|
|
|
2020-05-11 15:36:12 +05:30
|
|
|
err = util_aa_le32(conn_lll->access_addr);
|
2020-02-07 11:36:54 +05:30
|
|
|
LL_ASSERT(!err);
|
|
|
|
|
2020-05-21 14:51:16 +02:00
|
|
|
lll_csrand_get(conn_lll->crc_init, sizeof(conn_lll->crc_init));
|
2018-12-18 05:48:20 +01:00
|
|
|
|
|
|
|
conn_lll->handle = 0xFFFF;
|
|
|
|
conn_lll->interval = interval;
|
|
|
|
conn_lll->latency = latency;
|
|
|
|
|
|
|
|
if (!conn_lll->link_tx_free) {
|
|
|
|
conn_lll->link_tx_free = &conn_lll->link_tx;
|
|
|
|
}
|
|
|
|
|
|
|
|
memq_init(conn_lll->link_tx_free, &conn_lll->memq_tx.head,
|
|
|
|
&conn_lll->memq_tx.tail);
|
|
|
|
conn_lll->link_tx_free = NULL;
|
|
|
|
|
|
|
|
conn_lll->packet_tx_head_len = 0;
|
|
|
|
conn_lll->packet_tx_head_offset = 0;
|
|
|
|
|
|
|
|
conn_lll->sn = 0;
|
|
|
|
conn_lll->nesn = 0;
|
|
|
|
conn_lll->empty = 0;
|
|
|
|
|
2019-01-26 06:07:45 +05:30
|
|
|
#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
|
|
|
|
conn_lll->max_tx_octets = PDU_DC_PAYLOAD_SIZE_MIN;
|
|
|
|
conn_lll->max_rx_octets = PDU_DC_PAYLOAD_SIZE_MIN;
|
|
|
|
|
|
|
|
#if defined(CONFIG_BT_CTLR_PHY)
|
2020-03-16 10:13:10 +01:00
|
|
|
conn_lll->max_tx_time = PKT_US(PDU_DC_PAYLOAD_SIZE_MIN, PHY_1M);
|
|
|
|
conn_lll->max_rx_time = PKT_US(PDU_DC_PAYLOAD_SIZE_MIN, PHY_1M);
|
2019-01-26 06:07:45 +05:30
|
|
|
#endif /* CONFIG_BT_CTLR_PHY */
|
|
|
|
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
|
|
|
|
|
2018-12-18 05:48:20 +01:00
|
|
|
#if defined(CONFIG_BT_CTLR_PHY)
|
|
|
|
conn_lll->phy_tx = BIT(0);
|
|
|
|
conn_lll->phy_flags = 0;
|
|
|
|
conn_lll->phy_tx_time = BIT(0);
|
|
|
|
conn_lll->phy_rx = BIT(0);
|
|
|
|
#endif /* CONFIG_BT_CTLR_PHY */
|
|
|
|
|
|
|
|
#if defined(CONFIG_BT_CTLR_CONN_RSSI)
|
|
|
|
conn_lll->rssi_latest = 0x7F;
|
2020-04-28 20:23:29 +02:00
|
|
|
#if defined(CONFIG_BT_CTLR_CONN_RSSI_EVENT)
|
2018-12-18 05:48:20 +01:00
|
|
|
conn_lll->rssi_reported = 0x7F;
|
|
|
|
conn_lll->rssi_sample_count = 0;
|
2020-04-28 20:23:29 +02:00
|
|
|
#endif /* CONFIG_BT_CTLR_CONN_RSSI_EVENT */
|
2018-12-18 05:48:20 +01:00
|
|
|
#endif /* CONFIG_BT_CTLR_CONN_RSSI */
|
|
|
|
|
2019-10-22 13:13:24 +02:00
|
|
|
#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
|
|
|
|
conn_lll->tx_pwr_lvl = RADIO_TXP_DEFAULT;
|
|
|
|
#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
|
|
|
|
|
2018-12-18 05:48:20 +01:00
|
|
|
/* FIXME: BEGIN: Move to ULL? */
|
|
|
|
conn_lll->latency_prepare = 0;
|
|
|
|
conn_lll->latency_event = 0;
|
|
|
|
conn_lll->event_counter = 0;
|
|
|
|
|
2020-02-07 15:10:30 +05:30
|
|
|
conn_lll->data_chan_count = ull_chan_map_get(conn_lll->data_chan_map);
|
2020-05-21 14:51:16 +02:00
|
|
|
lll_csrand_get(&hop, sizeof(uint8_t));
|
2018-12-18 05:48:20 +01:00
|
|
|
conn_lll->data_chan_hop = 5 + (hop % 12);
|
|
|
|
conn_lll->data_chan_sel = 0;
|
|
|
|
conn_lll->data_chan_use = 0;
|
|
|
|
conn_lll->role = 0;
|
|
|
|
/* FIXME: END: Move to ULL? */
|
2019-09-30 10:10:45 +02:00
|
|
|
#if defined(CONFIG_BT_CTLR_CONN_META)
|
|
|
|
memset(&conn_lll->conn_meta, 0, sizeof(conn_lll->conn_meta));
|
|
|
|
#endif /* CONFIG_BT_CTLR_CONN_META */
|
2018-12-18 05:48:20 +01:00
|
|
|
|
2019-03-26 19:57:45 -06:00
|
|
|
conn->connect_expire = 6U;
|
|
|
|
conn->supervision_expire = 0U;
|
2020-05-27 11:26:57 -05:00
|
|
|
conn_interval_us = (uint32_t)interval * 1250U;
|
2019-03-26 19:57:45 -06:00
|
|
|
conn->supervision_reload = RADIO_CONN_EVENTS(timeout * 10000U,
|
2018-12-18 05:48:20 +01:00
|
|
|
conn_interval_us);
|
|
|
|
|
2019-03-26 19:57:45 -06:00
|
|
|
conn->procedure_expire = 0U;
|
2018-12-18 05:48:20 +01:00
|
|
|
conn->procedure_reload = RADIO_CONN_EVENTS(40000000,
|
|
|
|
conn_interval_us);
|
|
|
|
|
|
|
|
#if defined(CONFIG_BT_CTLR_LE_PING)
|
2019-03-26 19:57:45 -06:00
|
|
|
conn->apto_expire = 0U;
|
2018-12-18 05:48:20 +01:00
|
|
|
/* APTO in no. of connection events */
|
|
|
|
conn->apto_reload = RADIO_CONN_EVENTS((30000000), conn_interval_us);
|
2019-03-26 19:57:45 -06:00
|
|
|
conn->appto_expire = 0U;
|
2018-12-18 05:48:20 +01:00
|
|
|
/* Dispatch LE Ping PDU 6 connection events (that peer would listen to)
|
|
|
|
* before 30s timeout
|
|
|
|
* TODO: "peer listens to" is greater than 30s due to latency
|
|
|
|
*/
|
|
|
|
conn->appto_reload = (conn->apto_reload > (conn_lll->latency + 6)) ?
|
|
|
|
(conn->apto_reload - (conn_lll->latency + 6)) :
|
|
|
|
conn->apto_reload;
|
|
|
|
#endif /* CONFIG_BT_CTLR_LE_PING */
|
|
|
|
|
2019-03-26 19:57:45 -06:00
|
|
|
conn->common.fex_valid = 0U;
|
2019-10-30 13:42:56 +05:30
|
|
|
conn->master.terminate_ack = 0U;
|
2018-12-18 05:48:20 +01:00
|
|
|
|
2019-03-26 19:57:45 -06:00
|
|
|
conn->llcp_req = conn->llcp_ack = conn->llcp_type = 0U;
|
2018-12-18 05:48:20 +01:00
|
|
|
conn->llcp_rx = NULL;
|
2019-09-18 23:17:39 +05:30
|
|
|
conn->llcp_cu.req = conn->llcp_cu.ack = 0;
|
2019-04-10 09:08:03 +05:30
|
|
|
conn->llcp_feature.req = conn->llcp_feature.ack = 0;
|
2020-05-22 15:16:39 +02:00
|
|
|
conn->llcp_feature.features_conn = LL_FEAT;
|
|
|
|
conn->llcp_feature.features_peer = 0;
|
2019-04-10 09:08:03 +05:30
|
|
|
conn->llcp_version.req = conn->llcp_version.ack = 0;
|
2019-03-26 19:57:45 -06:00
|
|
|
conn->llcp_version.tx = conn->llcp_version.rx = 0U;
|
|
|
|
conn->llcp_terminate.reason_peer = 0U;
|
2018-12-18 05:48:20 +01:00
|
|
|
/* NOTE: use allocated link for generating dedicated
|
|
|
|
* terminate ind rx node
|
|
|
|
*/
|
|
|
|
conn->llcp_terminate.node_rx.hdr.link = link;
|
|
|
|
|
|
|
|
#if defined(CONFIG_BT_CTLR_LE_ENC)
|
2019-05-29 21:54:38 +02:00
|
|
|
conn_lll->enc_rx = conn_lll->enc_tx = 0U;
|
|
|
|
conn->llcp_enc.req = conn->llcp_enc.ack = 0U;
|
|
|
|
conn->llcp_enc.pause_tx = conn->llcp_enc.pause_rx = 0U;
|
|
|
|
conn->llcp_enc.refresh = 0U;
|
2018-12-18 05:48:20 +01:00
|
|
|
#endif /* CONFIG_BT_CTLR_LE_ENC */
|
|
|
|
|
|
|
|
#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
|
2019-03-26 19:57:45 -06:00
|
|
|
conn->llcp_conn_param.req = 0U;
|
|
|
|
conn->llcp_conn_param.ack = 0U;
|
|
|
|
conn->llcp_conn_param.disabled = 0U;
|
2018-12-18 05:48:20 +01:00
|
|
|
#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
|
|
|
|
|
2019-01-26 06:07:45 +05:30
|
|
|
#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
|
|
|
|
conn->llcp_length.req = conn->llcp_length.ack = 0U;
|
2020-02-26 16:14:29 +01:00
|
|
|
conn->llcp_length.disabled = 0U;
|
2019-07-09 22:55:28 +05:30
|
|
|
conn->llcp_length.cache.tx_octets = 0U;
|
2019-01-26 06:07:45 +05:30
|
|
|
conn->default_tx_octets = ull_conn_default_tx_octets_get();
|
|
|
|
|
|
|
|
#if defined(CONFIG_BT_CTLR_PHY)
|
|
|
|
conn->default_tx_time = ull_conn_default_tx_time_get();
|
|
|
|
#endif /* CONFIG_BT_CTLR_PHY */
|
|
|
|
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
|
|
|
|
|
2018-12-18 05:48:20 +01:00
|
|
|
#if defined(CONFIG_BT_CTLR_PHY)
|
2019-03-26 19:57:45 -06:00
|
|
|
conn->llcp_phy.req = conn->llcp_phy.ack = 0U;
|
2020-02-26 16:14:29 +01:00
|
|
|
conn->llcp_phy.disabled = 0U;
|
2019-03-11 15:12:28 +05:30
|
|
|
conn->llcp_phy.pause_tx = 0U;
|
2018-12-18 05:48:20 +01:00
|
|
|
conn->phy_pref_tx = ull_conn_default_phy_tx_get();
|
|
|
|
conn->phy_pref_rx = ull_conn_default_phy_rx_get();
|
2019-03-26 19:57:45 -06:00
|
|
|
conn->phy_pref_flags = 0U;
|
2018-12-18 05:48:20 +01:00
|
|
|
#endif /* CONFIG_BT_CTLR_PHY */
|
|
|
|
|
|
|
|
conn->tx_head = conn->tx_ctrl = conn->tx_ctrl_last =
|
|
|
|
conn->tx_data = conn->tx_data_last = 0;
|
|
|
|
|
|
|
|
lll->conn = conn_lll;
|
|
|
|
|
|
|
|
ull_hdr_init(&conn->ull);
|
|
|
|
lll_hdr_init(&conn->lll, conn);
|
|
|
|
|
2020-04-14 17:22:07 +05:30
|
|
|
conn_is_valid:
|
2018-12-18 05:48:20 +01:00
|
|
|
#if defined(CONFIG_BT_CTLR_PRIVACY)
|
2019-05-09 18:39:26 +05:30
|
|
|
ull_filter_scan_update(filter_policy);
|
2018-12-18 05:48:20 +01:00
|
|
|
|
2019-05-15 16:10:43 +02:00
|
|
|
lll->rl_idx = FILTER_IDX_NONE;
|
|
|
|
lll->rpa_gen = 0;
|
2019-05-09 18:39:26 +05:30
|
|
|
if (!filter_policy && ull_filter_lll_rl_enabled()) {
|
2018-12-18 05:48:20 +01:00
|
|
|
/* Look up the resolving list */
|
2019-05-09 18:39:26 +05:30
|
|
|
lll->rl_idx = ull_filter_rl_find(peer_addr_type, peer_addr,
|
|
|
|
NULL);
|
2018-12-18 05:48:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (own_addr_type == BT_ADDR_LE_PUBLIC_ID ||
|
|
|
|
own_addr_type == BT_ADDR_LE_RANDOM_ID) {
|
|
|
|
|
|
|
|
/* Generate RPAs if required */
|
2019-05-09 18:39:26 +05:30
|
|
|
ull_filter_rpa_update(false);
|
2018-12-18 05:48:20 +01:00
|
|
|
own_addr_type &= 0x1;
|
2019-05-09 18:39:26 +05:30
|
|
|
lll->rpa_gen = 1;
|
2018-12-18 05:48:20 +01:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2019-05-09 18:39:26 +05:30
|
|
|
scan->own_addr_type = own_addr_type;
|
|
|
|
|
2020-04-14 17:22:07 +05:30
|
|
|
#if defined(CONFIG_BT_CTLR_ADV_EXT)
|
|
|
|
return 0;
|
|
|
|
#else /* !CONFIG_BT_CTLR_ADV_EXT */
|
2018-12-18 05:48:20 +01:00
|
|
|
/* wait for stable clocks */
|
2020-03-17 19:30:46 +05:30
|
|
|
err = lll_clock_wait();
|
|
|
|
if (err) {
|
|
|
|
conn_release(scan);
|
|
|
|
|
|
|
|
return BT_HCI_ERR_HW_FAILURE;
|
|
|
|
}
|
2018-12-18 05:48:20 +01:00
|
|
|
|
|
|
|
return ull_scan_enable(scan);
|
2020-04-14 17:22:07 +05:30
|
|
|
#endif /* !CONFIG_BT_CTLR_ADV_EXT */
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(CONFIG_BT_CTLR_ADV_EXT)
|
|
|
|
uint8_t ll_connect_enable(uint8_t is_coded_included)
|
|
|
|
{
|
|
|
|
uint8_t err = BT_HCI_ERR_CMD_DISALLOWED;
|
|
|
|
struct ll_scan_set *scan;
|
|
|
|
|
|
|
|
scan = ull_scan_set_get(SCAN_HANDLE_1M);
|
|
|
|
|
|
|
|
/* wait for stable clocks */
|
|
|
|
err = lll_clock_wait();
|
|
|
|
if (err) {
|
|
|
|
conn_release(scan);
|
|
|
|
|
|
|
|
return BT_HCI_ERR_HW_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!is_coded_included ||
|
|
|
|
(scan->lll.phy & BIT(0))) {
|
|
|
|
err = ull_scan_enable(scan);
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IS_ENABLED(CONFIG_BT_CTLR_PHY_CODED) && is_coded_included) {
|
|
|
|
scan = ull_scan_set_get(SCAN_HANDLE_PHY_CODED);
|
|
|
|
err = ull_scan_enable(scan);
|
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return err;
|
2018-12-18 05:48:20 +01:00
|
|
|
}
|
2020-04-14 17:22:07 +05:30
|
|
|
#endif /* CONFIG_BT_CTLR_ADV_EXT */
|
2018-12-18 05:48:20 +01:00
|
|
|
|
2020-05-27 11:26:57 -05:00
|
|
|
uint8_t ll_connect_disable(void **rx)
|
2018-12-18 05:48:20 +01:00
|
|
|
{
|
|
|
|
struct lll_conn *conn_lll;
|
|
|
|
struct ll_scan_set *scan;
|
2020-05-27 11:26:57 -05:00
|
|
|
uint8_t status;
|
2018-12-18 05:48:20 +01:00
|
|
|
|
|
|
|
scan = ull_scan_is_enabled_get(0);
|
|
|
|
if (!scan) {
|
|
|
|
return BT_HCI_ERR_CMD_DISALLOWED;
|
|
|
|
}
|
|
|
|
|
|
|
|
conn_lll = scan->lll.conn;
|
|
|
|
if (!conn_lll) {
|
|
|
|
return BT_HCI_ERR_CMD_DISALLOWED;
|
|
|
|
}
|
|
|
|
|
|
|
|
status = ull_scan_disable(0, scan);
|
|
|
|
if (!status) {
|
|
|
|
struct ll_conn *conn = (void *)HDR_LLL2EVT(conn_lll);
|
2019-12-26 16:33:17 +05:30
|
|
|
struct node_rx_ftr *ftr;
|
2018-12-18 05:48:20 +01:00
|
|
|
struct node_rx_pdu *cc;
|
|
|
|
memq_link_t *link;
|
|
|
|
|
|
|
|
cc = (void *)&conn->llcp_terminate.node_rx;
|
|
|
|
link = cc->hdr.link;
|
|
|
|
LL_ASSERT(link);
|
|
|
|
|
|
|
|
/* free the memq link early, as caller could overwrite it */
|
|
|
|
ll_rx_link_release(link);
|
|
|
|
|
|
|
|
cc->hdr.type = NODE_RX_TYPE_CONNECTION;
|
|
|
|
cc->hdr.handle = 0xffff;
|
2020-05-27 11:26:57 -05:00
|
|
|
*((uint8_t *)cc->pdu) = BT_HCI_ERR_UNKNOWN_CONN_ID;
|
2019-12-26 16:33:17 +05:30
|
|
|
|
|
|
|
ftr = &(cc->hdr.rx_ftr);
|
|
|
|
ftr->param = &scan->lll;
|
|
|
|
|
2018-12-18 05:48:20 +01:00
|
|
|
*rx = cc;
|
|
|
|
}
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2020-05-11 15:36:12 +05:30
|
|
|
/* FIXME: Refactor out this interface so that its usable by extended
|
|
|
|
* advertising channel classification, and also master role connections can
|
|
|
|
* perform channel map update control procedure.
|
|
|
|
*/
|
2020-05-04 14:21:40 +05:30
|
|
|
uint8_t ll_chm_update(uint8_t const *const chm)
|
2018-12-18 05:48:20 +01:00
|
|
|
{
|
2020-05-27 11:26:57 -05:00
|
|
|
uint16_t handle;
|
|
|
|
uint8_t ret;
|
2018-12-18 05:48:20 +01:00
|
|
|
|
2020-02-07 15:10:30 +05:30
|
|
|
ull_chan_map_set(chm);
|
2018-12-18 05:48:20 +01:00
|
|
|
|
|
|
|
handle = CONFIG_BT_MAX_CONN;
|
|
|
|
while (handle--) {
|
|
|
|
struct ll_conn *conn;
|
|
|
|
|
|
|
|
conn = ll_connected_get(handle);
|
|
|
|
if (!conn || conn->lll.role) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2019-01-26 06:07:45 +05:30
|
|
|
ret = ull_conn_llcp_req(conn);
|
2019-02-06 15:53:16 +01:00
|
|
|
if (ret) {
|
|
|
|
return ret;
|
2019-01-11 02:30:42 +05:30
|
|
|
}
|
|
|
|
|
2018-12-18 05:48:20 +01:00
|
|
|
memcpy(conn->llcp.chan_map.chm, chm,
|
|
|
|
sizeof(conn->llcp.chan_map.chm));
|
|
|
|
/* conn->llcp.chan_map.instant = 0; */
|
2019-03-26 19:57:45 -06:00
|
|
|
conn->llcp.chan_map.initiate = 1U;
|
2018-12-18 05:48:20 +01:00
|
|
|
|
|
|
|
conn->llcp_type = LLCP_CHAN_MAP;
|
|
|
|
conn->llcp_req++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(CONFIG_BT_CTLR_LE_ENC)
|
2020-05-04 14:21:40 +05:30
|
|
|
uint8_t ll_enc_req_send(uint16_t handle, uint8_t const *const rand,
|
|
|
|
uint8_t const *const ediv, uint8_t const *const ltk)
|
2018-12-18 05:48:20 +01:00
|
|
|
{
|
|
|
|
struct ll_conn *conn;
|
|
|
|
struct node_tx *tx;
|
|
|
|
|
|
|
|
conn = ll_connected_get(handle);
|
|
|
|
if (!conn) {
|
|
|
|
return BT_HCI_ERR_UNKNOWN_CONN_ID;
|
|
|
|
}
|
|
|
|
|
2019-09-06 12:00:46 +05:30
|
|
|
if ((conn->llcp_enc.req != conn->llcp_enc.ack) ||
|
|
|
|
((conn->llcp_req != conn->llcp_ack) &&
|
|
|
|
(conn->llcp_type == LLCP_ENCRYPTION))) {
|
2019-05-29 21:54:38 +02:00
|
|
|
return BT_HCI_ERR_CMD_DISALLOWED;
|
2019-01-11 02:30:42 +05:30
|
|
|
}
|
|
|
|
|
2018-12-18 05:48:20 +01:00
|
|
|
tx = ll_tx_mem_acquire();
|
|
|
|
if (tx) {
|
|
|
|
struct pdu_data *pdu_data_tx;
|
|
|
|
|
|
|
|
pdu_data_tx = (void *)tx->pdu;
|
|
|
|
|
2019-05-29 21:54:38 +02:00
|
|
|
memcpy(&conn->llcp_enc.ltk[0], ltk, sizeof(conn->llcp_enc.ltk));
|
2018-12-18 05:48:20 +01:00
|
|
|
|
2019-09-06 12:00:46 +05:30
|
|
|
if (!conn->lll.enc_rx && !conn->lll.enc_tx) {
|
2018-12-18 05:48:20 +01:00
|
|
|
struct pdu_data_llctrl_enc_req *enc_req;
|
|
|
|
|
|
|
|
pdu_data_tx->ll_id = PDU_DATA_LLID_CTRL;
|
|
|
|
pdu_data_tx->len =
|
|
|
|
offsetof(struct pdu_data_llctrl, enc_rsp) +
|
|
|
|
sizeof(struct pdu_data_llctrl_enc_req);
|
|
|
|
pdu_data_tx->llctrl.opcode =
|
|
|
|
PDU_DATA_LLCTRL_TYPE_ENC_REQ;
|
|
|
|
enc_req = (void *)
|
|
|
|
&pdu_data_tx->llctrl.enc_req;
|
|
|
|
memcpy(enc_req->rand, rand, sizeof(enc_req->rand));
|
|
|
|
enc_req->ediv[0] = ediv[0];
|
|
|
|
enc_req->ediv[1] = ediv[1];
|
2020-05-21 14:51:16 +02:00
|
|
|
lll_csrand_get(enc_req->skdm, sizeof(enc_req->skdm));
|
|
|
|
lll_csrand_get(enc_req->ivm, sizeof(enc_req->ivm));
|
2019-09-06 12:00:46 +05:30
|
|
|
} else if (conn->lll.enc_rx && conn->lll.enc_tx) {
|
2019-05-29 21:54:38 +02:00
|
|
|
memcpy(&conn->llcp_enc.rand[0], rand,
|
|
|
|
sizeof(conn->llcp_enc.rand));
|
2018-12-18 05:48:20 +01:00
|
|
|
|
2019-05-29 21:54:38 +02:00
|
|
|
conn->llcp_enc.ediv[0] = ediv[0];
|
|
|
|
conn->llcp_enc.ediv[1] = ediv[1];
|
2018-12-18 05:48:20 +01:00
|
|
|
|
|
|
|
pdu_data_tx->ll_id = PDU_DATA_LLID_CTRL;
|
|
|
|
pdu_data_tx->len = offsetof(struct pdu_data_llctrl,
|
|
|
|
enc_req);
|
|
|
|
pdu_data_tx->llctrl.opcode =
|
|
|
|
PDU_DATA_LLCTRL_TYPE_PAUSE_ENC_REQ;
|
|
|
|
} else {
|
|
|
|
ll_tx_mem_release(tx);
|
|
|
|
|
|
|
|
return BT_HCI_ERR_CMD_DISALLOWED;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ll_tx_mem_enqueue(handle, tx)) {
|
|
|
|
ll_tx_mem_release(tx);
|
|
|
|
|
|
|
|
return BT_HCI_ERR_CMD_DISALLOWED;
|
|
|
|
}
|
|
|
|
|
2019-05-29 21:54:38 +02:00
|
|
|
conn->llcp_enc.req++;
|
2018-12-18 05:48:20 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return BT_HCI_ERR_CMD_DISALLOWED;
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_BT_CTLR_LE_ENC */
|
|
|
|
|
|
|
|
void ull_master_setup(memq_link_t *link, struct node_rx_hdr *rx,
|
|
|
|
struct node_rx_ftr *ftr, struct lll_conn *lll)
|
|
|
|
{
|
2020-05-27 11:26:57 -05:00
|
|
|
uint32_t conn_offset_us, conn_interval_us;
|
|
|
|
uint8_t ticker_id_scan, ticker_id_conn;
|
|
|
|
uint8_t peer_addr[BDADDR_SIZE];
|
|
|
|
uint32_t ticks_slot_overhead;
|
2018-12-18 05:48:20 +01:00
|
|
|
struct ll_scan_set *scan;
|
2020-04-21 11:21:07 +05:30
|
|
|
uint32_t ticks_slot_offset;
|
|
|
|
struct pdu_adv *pdu_tx;
|
2018-12-18 05:48:20 +01:00
|
|
|
struct node_rx_cc *cc;
|
|
|
|
struct ll_conn *conn;
|
2020-04-21 11:21:07 +05:30
|
|
|
uint32_t ready_delay_us;
|
2020-05-27 11:26:57 -05:00
|
|
|
uint8_t peer_addr_type;
|
|
|
|
uint32_t ticker_status;
|
|
|
|
uint8_t chan_sel;
|
2018-12-18 05:48:20 +01:00
|
|
|
|
|
|
|
((struct lll_scan *)ftr->param)->conn = NULL;
|
|
|
|
|
|
|
|
scan = ((struct lll_scan *)ftr->param)->hdr.parent;
|
|
|
|
conn = lll->hdr.parent;
|
|
|
|
|
2019-05-16 14:47:12 +02:00
|
|
|
pdu_tx = (void *)((struct node_rx_pdu *)rx)->pdu;
|
2019-05-15 16:11:13 +02:00
|
|
|
|
2020-01-07 12:22:05 +01:00
|
|
|
peer_addr_type = pdu_tx->rx_addr;
|
|
|
|
memcpy(peer_addr, &pdu_tx->connect_ind.adv_addr[0], BDADDR_SIZE);
|
2019-05-15 16:11:13 +02:00
|
|
|
|
2019-05-16 14:47:12 +02:00
|
|
|
/* This is the chan sel bit from the received adv pdu */
|
|
|
|
chan_sel = pdu_tx->chan_sel;
|
2018-12-18 05:48:20 +01:00
|
|
|
|
2019-05-16 14:47:12 +02:00
|
|
|
cc = (void *)pdu_tx;
|
2019-03-26 19:57:45 -06:00
|
|
|
cc->status = 0U;
|
|
|
|
cc->role = 0U;
|
2019-05-09 18:39:26 +05:30
|
|
|
|
|
|
|
#if defined(CONFIG_BT_CTLR_PRIVACY)
|
2020-05-27 11:26:57 -05:00
|
|
|
uint8_t rl_idx = ftr->rl_idx;
|
2020-04-23 16:54:50 +02:00
|
|
|
|
|
|
|
if (ftr->lrpa_used) {
|
|
|
|
memcpy(&cc->local_rpa[0], &pdu_tx->connect_ind.init_addr[0],
|
|
|
|
BDADDR_SIZE);
|
|
|
|
} else {
|
|
|
|
memset(&cc->local_rpa[0], 0x0, BDADDR_SIZE);
|
|
|
|
}
|
2019-05-09 18:39:26 +05:30
|
|
|
|
|
|
|
if (rl_idx != FILTER_IDX_NONE) {
|
|
|
|
/* Store identity address */
|
|
|
|
ll_rl_id_addr_get(rl_idx, &cc->peer_addr_type,
|
|
|
|
&cc->peer_addr[0]);
|
|
|
|
/* Mark it as identity address from RPA (0x02, 0x03) */
|
|
|
|
cc->peer_addr_type += 2;
|
|
|
|
|
|
|
|
/* Store peer RPA */
|
2019-05-15 16:11:13 +02:00
|
|
|
memcpy(&cc->peer_rpa[0], &peer_addr[0], BDADDR_SIZE);
|
2019-05-09 18:39:26 +05:30
|
|
|
} else {
|
|
|
|
memset(&cc->peer_rpa[0], 0x0, BDADDR_SIZE);
|
|
|
|
#else
|
|
|
|
if (1) {
|
|
|
|
#endif /* CONFIG_BT_CTLR_PRIVACY */
|
2020-01-07 12:22:05 +01:00
|
|
|
cc->peer_addr_type = peer_addr_type;
|
|
|
|
memcpy(cc->peer_addr, &peer_addr[0], BDADDR_SIZE);
|
2019-05-09 18:39:26 +05:30
|
|
|
}
|
|
|
|
|
2018-12-18 05:48:20 +01:00
|
|
|
cc->interval = lll->interval;
|
|
|
|
cc->latency = lll->latency;
|
|
|
|
cc->timeout = scan->lll.conn_timeout;
|
|
|
|
cc->sca = lll_conn_sca_local_get();
|
|
|
|
|
|
|
|
lll->handle = ll_conn_handle_get(conn);
|
|
|
|
rx->handle = lll->handle;
|
|
|
|
|
2019-10-22 13:13:24 +02:00
|
|
|
#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
|
|
|
|
lll->tx_pwr_lvl = RADIO_TXP_DEFAULT;
|
|
|
|
#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
|
|
|
|
|
2018-12-18 05:48:20 +01:00
|
|
|
/* Use Channel Selection Algorithm #2 if peer too supports it */
|
|
|
|
if (IS_ENABLED(CONFIG_BT_CTLR_CHAN_SEL_2)) {
|
|
|
|
struct node_rx_pdu *rx_csa;
|
|
|
|
struct node_rx_cs *cs;
|
|
|
|
|
|
|
|
/* pick the rx node instance stored within the connection
|
|
|
|
* rx node.
|
|
|
|
*/
|
|
|
|
rx_csa = (void *)ftr->extra;
|
|
|
|
|
|
|
|
/* Enqueue the connection event */
|
|
|
|
ll_rx_put(link, rx);
|
|
|
|
|
|
|
|
/* use the rx node for CSA event */
|
|
|
|
rx = (void *)rx_csa;
|
|
|
|
link = rx->link;
|
|
|
|
|
|
|
|
rx->handle = lll->handle;
|
|
|
|
rx->type = NODE_RX_TYPE_CHAN_SEL_ALGO;
|
|
|
|
|
|
|
|
cs = (void *)rx_csa->pdu;
|
|
|
|
|
|
|
|
if (chan_sel) {
|
2020-05-27 11:26:57 -05:00
|
|
|
uint16_t aa_ls = ((uint16_t)lll->access_addr[1] << 8) |
|
2018-12-18 05:48:20 +01:00
|
|
|
lll->access_addr[0];
|
2020-05-27 11:26:57 -05:00
|
|
|
uint16_t aa_ms = ((uint16_t)lll->access_addr[3] << 8) |
|
2018-12-18 05:48:20 +01:00
|
|
|
lll->access_addr[2];
|
|
|
|
|
|
|
|
lll->data_chan_sel = 1;
|
|
|
|
lll->data_chan_id = aa_ms ^ aa_ls;
|
|
|
|
|
|
|
|
cs->csa = 0x01;
|
|
|
|
} else {
|
|
|
|
cs->csa = 0x00;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ll_rx_put(link, rx);
|
|
|
|
ll_rx_sched();
|
|
|
|
|
2020-04-21 11:21:07 +05:30
|
|
|
#if defined(CONFIG_BT_CTLR_PHY)
|
|
|
|
ready_delay_us = lll_radio_tx_ready_delay_get(lll->phy_tx,
|
|
|
|
lll->phy_flags);
|
|
|
|
#else
|
|
|
|
ready_delay_us = lll_radio_tx_ready_delay_get(0, 0);
|
|
|
|
#endif
|
|
|
|
|
2018-12-18 05:48:20 +01:00
|
|
|
/* TODO: active_to_start feature port */
|
2019-03-26 19:57:45 -06:00
|
|
|
conn->evt.ticks_active_to_start = 0U;
|
2018-12-18 05:48:20 +01:00
|
|
|
conn->evt.ticks_xtal_to_start =
|
|
|
|
HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_XTAL_US);
|
|
|
|
conn->evt.ticks_preempt_to_start =
|
|
|
|
HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_PREEMPT_MIN_US);
|
|
|
|
conn->evt.ticks_slot =
|
|
|
|
HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US +
|
2020-04-21 11:21:07 +05:30
|
|
|
ready_delay_us +
|
|
|
|
328 + EVENT_IFS_US + 328);
|
2018-12-18 05:48:20 +01:00
|
|
|
|
2019-02-11 17:14:19 +00:00
|
|
|
ticks_slot_offset = MAX(conn->evt.ticks_active_to_start,
|
2018-12-18 05:48:20 +01:00
|
|
|
conn->evt.ticks_xtal_to_start);
|
|
|
|
|
|
|
|
if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT)) {
|
|
|
|
ticks_slot_overhead = ticks_slot_offset;
|
|
|
|
} else {
|
2019-03-26 19:57:45 -06:00
|
|
|
ticks_slot_overhead = 0U;
|
2018-12-18 05:48:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
conn_interval_us = lll->interval * 1250;
|
2020-04-21 11:21:07 +05:30
|
|
|
conn_offset_us = ftr->radio_end_us;
|
2018-12-18 05:48:20 +01:00
|
|
|
conn_offset_us += HAL_TICKER_TICKS_TO_US(1);
|
|
|
|
conn_offset_us -= EVENT_OVERHEAD_START_US;
|
2020-04-21 11:21:07 +05:30
|
|
|
conn_offset_us -= ready_delay_us;
|
2018-12-18 05:48:20 +01:00
|
|
|
|
2019-09-12 08:37:32 +05:30
|
|
|
#if (CONFIG_BT_CTLR_ULL_HIGH_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO)
|
2018-12-18 05:48:20 +01:00
|
|
|
/* disable ticker job, in order to chain stop and start to avoid RTC
|
|
|
|
* being stopped if no tickers active.
|
|
|
|
*/
|
|
|
|
mayfly_enable(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_ULL_LOW, 0);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Stop Scanner */
|
|
|
|
ticker_id_scan = TICKER_ID_SCAN_BASE + ull_scan_handle_get(scan);
|
|
|
|
ticker_status = ticker_stop(TICKER_INSTANCE_ID_CTLR,
|
|
|
|
TICKER_USER_ID_ULL_HIGH,
|
|
|
|
ticker_id_scan, ticker_op_stop_scan_cb,
|
2020-05-27 11:26:57 -05:00
|
|
|
(void *)(uint32_t)ticker_id_scan);
|
|
|
|
ticker_op_stop_scan_cb(ticker_status, (void *)(uint32_t)ticker_id_scan);
|
2018-12-18 05:48:20 +01:00
|
|
|
|
|
|
|
/* Scanner stop can expire while here in this ISR.
|
|
|
|
* Deferred attempt to stop can fail as it would have
|
|
|
|
* expired, hence ignore failure.
|
|
|
|
*/
|
|
|
|
ticker_stop(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_HIGH,
|
|
|
|
TICKER_ID_SCAN_STOP, NULL, NULL);
|
|
|
|
|
|
|
|
/* Start master */
|
|
|
|
ticker_id_conn = TICKER_ID_CONN_BASE + ll_conn_handle_get(conn);
|
|
|
|
ticker_status = ticker_start(TICKER_INSTANCE_ID_CTLR,
|
|
|
|
TICKER_USER_ID_ULL_HIGH,
|
|
|
|
ticker_id_conn,
|
|
|
|
ftr->ticks_anchor - ticks_slot_offset,
|
|
|
|
HAL_TICKER_US_TO_TICKS(conn_offset_us),
|
|
|
|
HAL_TICKER_US_TO_TICKS(conn_interval_us),
|
|
|
|
HAL_TICKER_REMAINDER(conn_interval_us),
|
|
|
|
TICKER_NULL_LAZY,
|
|
|
|
(conn->evt.ticks_slot +
|
|
|
|
ticks_slot_overhead),
|
|
|
|
ull_master_ticker_cb, conn, ticker_op_cb,
|
|
|
|
(void *)__LINE__);
|
|
|
|
LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) ||
|
|
|
|
(ticker_status == TICKER_STATUS_BUSY));
|
|
|
|
|
|
|
|
#if (CONFIG_BT_CTLR_ULL_HIGH_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO)
|
2019-11-19 11:54:03 +05:30
|
|
|
/* enable ticker job, irrespective of disabled in this function so
|
|
|
|
* first connection event can be scheduled as soon as possible.
|
|
|
|
*/
|
|
|
|
mayfly_enable(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_ULL_LOW, 1);
|
2018-12-18 05:48:20 +01:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2020-05-27 11:26:57 -05:00
|
|
|
void ull_master_ticker_cb(uint32_t ticks_at_expire, uint32_t remainder, uint16_t lazy,
|
2018-12-18 05:48:20 +01:00
|
|
|
void *param)
|
|
|
|
{
|
2019-02-04 22:21:55 +05:30
|
|
|
static memq_link_t link;
|
|
|
|
static struct mayfly mfy = {0, 0, &link, NULL, lll_master_prepare};
|
2018-12-18 05:48:20 +01:00
|
|
|
static struct lll_prepare_param p;
|
2020-09-29 15:14:08 +05:30
|
|
|
struct ll_conn *conn;
|
2020-05-27 11:26:57 -05:00
|
|
|
uint32_t err;
|
|
|
|
uint8_t ref;
|
2018-12-18 05:48:20 +01:00
|
|
|
|
|
|
|
DEBUG_RADIO_PREPARE_M(1);
|
|
|
|
|
2020-09-29 15:14:08 +05:30
|
|
|
conn = param;
|
|
|
|
|
|
|
|
/* Check if stopping ticker (on disconnection, race with ticker expiry)
|
|
|
|
*/
|
|
|
|
if (unlikely(conn->lll.handle == 0xFFFF)) {
|
|
|
|
DEBUG_RADIO_PREPARE_M(0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-02-21 11:34:21 +01:00
|
|
|
/* If this is a must-expire callback, LLCP state machine does not need
|
|
|
|
* to know. Will be called with lazy > 0 when scheduled in air.
|
|
|
|
*/
|
|
|
|
if (!IS_ENABLED(CONFIG_BT_CTLR_CONN_META) ||
|
|
|
|
(lazy != TICKER_LAZY_MUST_EXPIRE)) {
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
/* Handle any LL Control Procedures */
|
|
|
|
ret = ull_conn_llcp(conn, ticks_at_expire, lazy);
|
|
|
|
if (ret) {
|
2020-09-29 15:07:26 +05:30
|
|
|
DEBUG_RADIO_PREPARE_M(0);
|
2020-02-21 11:34:21 +01:00
|
|
|
return;
|
|
|
|
}
|
2018-12-18 05:48:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Increment prepare reference count */
|
|
|
|
ref = ull_ref_inc(&conn->ull);
|
|
|
|
LL_ASSERT(ref);
|
|
|
|
|
2020-09-06 07:16:29 +05:30
|
|
|
/* De-mux 2 tx node from FIFO, sufficient to be able to set MD bit */
|
|
|
|
ull_conn_tx_demux(2);
|
2018-12-18 05:48:20 +01:00
|
|
|
|
|
|
|
/* Enqueue towards LLL */
|
2020-09-06 07:16:29 +05:30
|
|
|
ull_conn_tx_lll_enqueue(conn, 2);
|
2018-12-18 05:48:20 +01:00
|
|
|
|
|
|
|
/* Append timing parameters */
|
|
|
|
p.ticks_at_expire = ticks_at_expire;
|
|
|
|
p.remainder = remainder;
|
|
|
|
p.lazy = lazy;
|
|
|
|
p.param = &conn->lll;
|
2019-02-04 22:21:55 +05:30
|
|
|
mfy.param = &p;
|
2018-12-18 05:48:20 +01:00
|
|
|
|
|
|
|
/* Kick LLL prepare */
|
|
|
|
err = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL,
|
2019-02-04 22:21:55 +05:30
|
|
|
0, &mfy);
|
2018-12-18 05:48:20 +01:00
|
|
|
LL_ASSERT(!err);
|
|
|
|
|
|
|
|
/* De-mux remaining tx nodes from FIFO */
|
|
|
|
ull_conn_tx_demux(UINT8_MAX);
|
|
|
|
|
|
|
|
/* Enqueue towards LLL */
|
|
|
|
ull_conn_tx_lll_enqueue(conn, UINT8_MAX);
|
|
|
|
|
|
|
|
DEBUG_RADIO_PREPARE_M(1);
|
|
|
|
}
|
|
|
|
|
2020-05-27 11:26:57 -05:00
|
|
|
static void ticker_op_stop_scan_cb(uint32_t status, void *params)
|
2018-12-18 05:48:20 +01:00
|
|
|
{
|
|
|
|
/* TODO: */
|
|
|
|
}
|
|
|
|
|
2020-05-27 11:26:57 -05:00
|
|
|
static void ticker_op_cb(uint32_t status, void *params)
|
2018-12-18 05:48:20 +01:00
|
|
|
{
|
|
|
|
ARG_UNUSED(params);
|
|
|
|
|
|
|
|
LL_ASSERT(status == TICKER_STATUS_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2020-03-17 19:30:46 +05:30
|
|
|
static inline void conn_release(struct ll_scan_set *scan)
|
|
|
|
{
|
|
|
|
struct lll_conn *lll = scan->lll.conn;
|
|
|
|
struct node_rx_pdu *cc;
|
|
|
|
struct ll_conn *conn;
|
|
|
|
memq_link_t *link;
|
|
|
|
|
|
|
|
LL_ASSERT(!lll->link_tx_free);
|
|
|
|
link = memq_deinit(&lll->memq_tx.head, &lll->memq_tx.tail);
|
|
|
|
LL_ASSERT(link);
|
|
|
|
lll->link_tx_free = link;
|
|
|
|
|
|
|
|
conn = (void *)HDR_LLL2EVT(lll);
|
|
|
|
|
|
|
|
cc = (void *)&conn->llcp_terminate.node_rx;
|
|
|
|
link = cc->hdr.link;
|
|
|
|
LL_ASSERT(link);
|
|
|
|
|
|
|
|
ll_rx_link_release(link);
|
|
|
|
|
|
|
|
ll_conn_release(conn);
|
|
|
|
scan->lll.conn = NULL;
|
|
|
|
}
|