From d90b7274fa8bbfa09f79660b45b550d91f7b0125 Mon Sep 17 00:00:00 2001 From: Jean-François Milants Date: Tue, 2 Feb 2021 22:09:00 +0100 Subject: Update to nimble 1.3 master branch commit 82153e744833821e20e9a8b0d61c38b2b0dbcfe1 WARNING : heartbeat task is disabled! --- .../nimble/controller/include/controller/ble_ll.h | 30 ++ .../controller/include/controller/ble_ll_conn.h | 7 + .../controller/include/controller/ble_ll_ctrl.h | 87 ++-- .../controller/include/controller/ble_ll_hci.h | 2 +- .../controller/include/controller/ble_ll_iso.h | 53 +++ .../nimble/controller/include/controller/ble_phy.h | 2 + .../mynewt-nimble/nimble/controller/src/ble_ll.c | 63 ++- .../nimble/controller/src/ble_ll_adv.c | 30 +- .../nimble/controller/src/ble_ll_conn.c | 470 +++++++++++++++------ .../nimble/controller/src/ble_ll_conn_hci.c | 35 +- .../nimble/controller/src/ble_ll_conn_priv.h | 13 +- .../nimble/controller/src/ble_ll_ctrl.c | 133 +++++- .../nimble/controller/src/ble_ll_hci.c | 220 +++++++++- .../nimble/controller/src/ble_ll_hci_ev.c | 31 ++ .../nimble/controller/src/ble_ll_iso.c | 146 +++++++ .../nimble/controller/src/ble_ll_rand.c | 18 + .../nimble/controller/src/ble_ll_scan.c | 52 +-- .../nimble/controller/src/ble_ll_sched.c | 32 +- .../nimble/controller/src/ble_ll_supp_cmd.c | 91 +++- .../nimble/controller/src/ble_ll_sync.c | 4 +- .../nimble/controller/src/ble_ll_utils.c | 7 +- .../mynewt-nimble/nimble/controller/syscfg.yml | 70 +-- 22 files changed, 1306 insertions(+), 290 deletions(-) create mode 100644 src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_iso.h create mode 100644 src/libs/mynewt-nimble/nimble/controller/src/ble_ll_iso.c (limited to 'src/libs/mynewt-nimble/nimble/controller') diff --git a/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll.h b/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll.h index d3340445..1c43e69f 100644 --- a/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll.h +++ b/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll.h @@ -69,6 +69,29 @@ extern "C" { /* Timing jitter as per spec is +/16 usecs */ #define BLE_LL_JITTER_USECS (16) + +#if MYNEWT_VAL(BLE_LL_SCA) < 0 +#error Invalid SCA value +#elif MYNEWT_VAL(BLE_LL_SCA) <= 20 +#define BLE_LL_SCA_ENUM 7 +#elif MYNEWT_VAL(BLE_LL_SCA) <= 30 +#define BLE_LL_SCA_ENUM 6 +#elif MYNEWT_VAL(BLE_LL_SCA) <= 50 +#define BLE_LL_SCA_ENUM 5 +#elif MYNEWT_VAL(BLE_LL_SCA) <= 75 +#define BLE_LL_SCA_ENUM 4 +#elif MYNEWT_VAL(BLE_LL_SCA) <= 100 +#define BLE_LL_SCA_ENUM 3 +#elif MYNEWT_VAL(BLE_LL_SCA) <= 150 +#define BLE_LL_SCA_ENUM 2 +#elif MYNEWT_VAL(BLE_LL_SCA) <= 250 +#define BLE_LL_SCA_ENUM 1 +#elif MYNEWT_VAL(BLE_LL_SCA) <= 500 +#define BLE_LL_SCA_ENUM 0 +#else +#error Invalid SCA value +#endif + /* Packet queue header definition */ STAILQ_HEAD(ble_ll_pkt_q, os_mbuf_pkthdr); @@ -373,6 +396,12 @@ struct ble_dev_addr #define BLE_LL_LLID_DATA_START (2) #define BLE_LL_LLID_CTRL (3) +#define BLE_LL_LLID_IS_CTRL(hdr) \ + (((hdr) & BLE_LL_DATA_HDR_LLID_MASK) == BLE_LL_LLID_CTRL) +#define BLE_LL_LLID_IS_DATA(hdr) \ + ((((hdr) & BLE_LL_DATA_HDR_LLID_MASK) == BLE_LL_LLID_DATA_START) || \ + (((hdr) & BLE_LL_DATA_HDR_LLID_MASK) == BLE_LL_LLID_DATA_FRAG)) + /* * CONNECT_REQ * -> InitA (6 bytes) @@ -545,6 +574,7 @@ void ble_ll_rand_sample(uint8_t rnum); int ble_ll_rand_data_get(uint8_t *buf, uint8_t len); void ble_ll_rand_prand_get(uint8_t *prand); int ble_ll_rand_start(void); +uint32_t ble_ll_rand(void); static inline int ble_ll_get_addr_type(uint8_t txrxflag) diff --git a/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_conn.h b/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_conn.h index 26c99265..d7db6878 100644 --- a/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_conn.h +++ b/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_conn.h @@ -58,6 +58,8 @@ extern "C" { /* Definition for RSSI when the RSSI is unknown */ #define BLE_LL_CONN_UNKNOWN_RSSI (127) +#define BLE_LL_CONN_HANDLE_ISO_OFFSET (0x0100) + #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) /* * Encryption states for a connection @@ -69,6 +71,7 @@ extern "C" { enum conn_enc_state { CONN_ENC_S_UNENCRYPTED = 1, CONN_ENC_S_ENCRYPTED, + CONN_ENC_S_ENC_RSP_TO_BE_SENT, CONN_ENC_S_ENC_RSP_WAIT, CONN_ENC_S_PAUSE_ENC_RSP_WAIT, CONN_ENC_S_PAUSED, @@ -270,6 +273,10 @@ struct ble_ll_conn_sm uint8_t last_rxd_hdr_byte; /* note: possibly can make 1 bit since we only use the MD bit now */ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL) + uint16_t cth_flow_pending; +#endif + /* connection event mgmt */ uint8_t reject_reason; uint8_t host_reply_opcode; diff --git a/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_ctrl.h b/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_ctrl.h index b0da1e73..15a45b2a 100644 --- a/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_ctrl.h +++ b/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_ctrl.h @@ -39,7 +39,9 @@ extern "C" { #define BLE_LL_CTRL_PROC_LE_PING (7) #define BLE_LL_CTRL_PROC_DATA_LEN_UPD (8) #define BLE_LL_CTRL_PROC_PHY_UPDATE (9) -#define BLE_LL_CTRL_PROC_NUM (10) +#define BLE_LL_CTRL_PROC_SCA_UPDATE (10) +#define BLE_LL_CTRL_PROC_CIS_CREATE (11) +#define BLE_LL_CTRL_PROC_NUM (12) #define BLE_LL_CTRL_PROC_IDLE (255) /* Checks if a particular control procedure is running */ @@ -54,45 +56,51 @@ extern "C" { * -> Opcode (1 byte) * -> Data (0 - 26 bytes) */ -#define BLE_LL_CTRL_CONN_UPDATE_IND (0) -#define BLE_LL_CTRL_CHANNEL_MAP_REQ (1) -#define BLE_LL_CTRL_TERMINATE_IND (2) -#define BLE_LL_CTRL_ENC_REQ (3) -#define BLE_LL_CTRL_ENC_RSP (4) -#define BLE_LL_CTRL_START_ENC_REQ (5) -#define BLE_LL_CTRL_START_ENC_RSP (6) -#define BLE_LL_CTRL_UNKNOWN_RSP (7) -#define BLE_LL_CTRL_FEATURE_REQ (8) -#define BLE_LL_CTRL_FEATURE_RSP (9) -#define BLE_LL_CTRL_PAUSE_ENC_REQ (10) -#define BLE_LL_CTRL_PAUSE_ENC_RSP (11) -#define BLE_LL_CTRL_VERSION_IND (12) -#define BLE_LL_CTRL_REJECT_IND (13) -#define BLE_LL_CTRL_SLAVE_FEATURE_REQ (14) -#define BLE_LL_CTRL_CONN_PARM_REQ (15) -#define BLE_LL_CTRL_CONN_PARM_RSP (16) -#define BLE_LL_CTRL_REJECT_IND_EXT (17) -#define BLE_LL_CTRL_PING_REQ (18) -#define BLE_LL_CTRL_PING_RSP (19) -#define BLE_LL_CTRL_LENGTH_REQ (20) -#define BLE_LL_CTRL_LENGTH_RSP (21) -#define BLE_LL_CTRL_PHY_REQ (22) -#define BLE_LL_CTRL_PHY_RSP (23) -#define BLE_LL_CTRL_PHY_UPDATE_IND (24) -#define BLE_LL_CTRL_MIN_USED_CHAN_IND (25) -#define BLE_LL_CTRL_CTE_REQ (26) -#define BLE_LL_CTRL_CTE_RSP (27) -#define BLE_LL_CTRL_PERIODIC_SYNC_IND (28) -#define BLE_LL_CTRL_CLOCK_ACCURACY_REQ (29) -#define BLE_LL_CTRL_CLOCK_ACCURACY_RSP (30) +#define BLE_LL_CTRL_CONN_UPDATE_IND (0x00) +#define BLE_LL_CTRL_CHANNEL_MAP_REQ (0x01) +#define BLE_LL_CTRL_TERMINATE_IND (0x02) +#define BLE_LL_CTRL_ENC_REQ (0x03) +#define BLE_LL_CTRL_ENC_RSP (0x04) +#define BLE_LL_CTRL_START_ENC_REQ (0x05) +#define BLE_LL_CTRL_START_ENC_RSP (0x06) +#define BLE_LL_CTRL_UNKNOWN_RSP (0x07) +#define BLE_LL_CTRL_FEATURE_REQ (0x08) +#define BLE_LL_CTRL_FEATURE_RSP (0x09) +#define BLE_LL_CTRL_PAUSE_ENC_REQ (0x0A) +#define BLE_LL_CTRL_PAUSE_ENC_RSP (0x0B) +#define BLE_LL_CTRL_VERSION_IND (0x0C) +#define BLE_LL_CTRL_REJECT_IND (0x0D) +#define BLE_LL_CTRL_SLAVE_FEATURE_REQ (0x0E) +#define BLE_LL_CTRL_CONN_PARM_REQ (0x0F) +#define BLE_LL_CTRL_CONN_PARM_RSP (0x10) +#define BLE_LL_CTRL_REJECT_IND_EXT (0x11) +#define BLE_LL_CTRL_PING_REQ (0x12) +#define BLE_LL_CTRL_PING_RSP (0x13) +#define BLE_LL_CTRL_LENGTH_REQ (0x14) +#define BLE_LL_CTRL_LENGTH_RSP (0x15) +#define BLE_LL_CTRL_PHY_REQ (0x16) +#define BLE_LL_CTRL_PHY_RSP (0x17) +#define BLE_LL_CTRL_PHY_UPDATE_IND (0x18) +#define BLE_LL_CTRL_MIN_USED_CHAN_IND (0x19) +#define BLE_LL_CTRL_CTE_REQ (0x1A) +#define BLE_LL_CTRL_CTE_RSP (0x1B) +#define BLE_LL_CTRL_PERIODIC_SYNC_IND (0x1C) +#define BLE_LL_CTRL_CLOCK_ACCURACY_REQ (0x1D) +#define BLE_LL_CTRL_CLOCK_ACCURACY_RSP (0x1E) +#define BLE_LL_CTRL_CIS_REQ (0x1F) +#define BLE_LL_CTRL_CIS_RSP (0x20) +#define BLE_LL_CTRL_CIS_IND (0x21) +#define BLE_LL_CTRL_CIS_TERMINATE_IND (0x22) /* Maximum opcode value */ -#define BLE_LL_CTRL_OPCODES (BLE_LL_CTRL_CLOCK_ACCURACY_RSP + 1) +#define BLE_LL_CTRL_OPCODES (BLE_LL_CTRL_CIS_TERMINATE_IND + 1) extern const uint8_t g_ble_ll_ctrl_pkt_lengths[BLE_LL_CTRL_OPCODES]; /* Maximum LL control PDU size */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) +#if MYNEWT_VAL(BLE_ISO) +#define BLE_LL_CTRL_MAX_PDU_LEN (42) +#elif MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) #define BLE_LL_CTRL_MAX_PDU_LEN (35) #else #define BLE_LL_CTRL_MAX_PDU_LEN (27) @@ -261,6 +269,12 @@ struct ble_ll_len_req #define BLE_LL_CTRL_CLOCK_ACCURACY_REQ_LEN (1) #define BLE_LL_CTRL_CLOCK_ACCURACY_RSP_LEN (1) +/* BLE ISO */ +#define BLE_LL_CTRL_CIS_REQ_LEN (42) +#define BLE_LL_CTRL_CIS_RSP_LEN (8) +#define BLE_LL_CTRL_CIS_IND_LEN (15) +#define BLE_LL_CTRL_CIS_TERMINATE_LEN (3) + /* API */ struct ble_ll_conn_sm; void ble_ll_ctrl_proc_start(struct ble_ll_conn_sm *connsm, int ctrl_proc); @@ -306,6 +320,11 @@ void ble_ll_hci_ev_send_vendor_err(const char *file, uint32_t line); uint8_t ble_ll_ctrl_phy_tx_transition_get(uint8_t phy_mask); uint8_t ble_ll_ctrl_phy_from_phy_mask(uint8_t phy_mask); +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE) +void ble_ll_hci_ev_sca_update(struct ble_ll_conn_sm *connsm, + uint8_t status, uint8_t peer_sca); +#endif + #ifdef __cplusplus } #endif diff --git a/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_hci.h b/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_hci.h index abef8746..6a9e48e5 100644 --- a/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_hci.h +++ b/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_hci.h @@ -27,7 +27,7 @@ extern "C" { #include "nimble/hci_common.h" /* For supported commands */ -#define BLE_LL_SUPP_CMD_LEN (42) +#define BLE_LL_SUPP_CMD_LEN (45) extern const uint8_t g_ble_ll_supp_cmds[BLE_LL_SUPP_CMD_LEN]; /* The largest event the controller will send. */ diff --git a/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_iso.h b/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_iso.h new file mode 100644 index 00000000..2944b074 --- /dev/null +++ b/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_iso.h @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_LL_ISO +#define H_BLE_LL_ISO + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int ble_ll_iso_read_tx_sync(const uint8_t *cmdbuf, uint8_t len); +int ble_ll_iso_set_cig_param(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen); +int ble_ll_iso_set_cig_param_test(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen); +int ble_ll_iso_create_cis(const uint8_t *cmdbuf, uint8_t len); +int ble_ll_iso_disconnect_cmd(const struct ble_hci_lc_disconnect_cp *cmd); +int ble_ll_iso_remove_cig(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen); +int ble_ll_iso_accept_cis_req(const uint8_t *cmdbuf, uint8_t len); +int ble_ll_iso_reject_cis_req(const uint8_t *cmdbuf, uint8_t len); +int ble_ll_iso_create_big(const uint8_t *cmdbuf, uint8_t len); +int ble_ll_iso_create_big_test(const uint8_t *cmdbuf, uint8_t len); +int ble_ll_iso_terminate_big(const uint8_t *cmdbuf, uint8_t len); +int ble_ll_iso_big_create_sync(const uint8_t *cmdbuf, uint8_t len); +int ble_ll_iso_big_terminate_sync(const uint8_t *cmdbuf, uint8_t len); +int ble_ll_iso_setup_iso_data_path(const uint8_t *cmdbuf, uint8_t len); +int ble_ll_iso_remove_iso_data_path(const uint8_t *cmdbuf, uint8_t len); +int ble_ll_iso_transmit_test(const uint8_t *cmdbuf, uint8_t len); +int ble_ll_iso_receive_test(const uint8_t *cmdbuf, uint8_t len); +int ble_ll_iso_read_counters_test(const uint8_t *cmdbuf, uint8_t len); +int ble_ll_iso_end_test(const uint8_t *cmdbuf, uint8_t len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_phy.h b/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_phy.h index cabb0adb..cd8350d6 100644 --- a/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_phy.h +++ b/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_phy.h @@ -225,6 +225,8 @@ static inline int ble_ll_phy_to_phy_mode(int phy, int phy_options) if (phy == BLE_PHY_CODED && phy_options == BLE_HCI_LE_PHY_CODED_S2_PREF) { phy_mode = BLE_PHY_MODE_CODED_500KBPS; } +#else + (void)phy_options; #endif return phy_mode; diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll.c b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll.c index 996ad9c3..a5c48978 100644 --- a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll.c +++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll.c @@ -247,9 +247,6 @@ uint8_t g_dev_addr[BLE_DEV_ADDR_LEN]; /** Our random address */ uint8_t g_random_addr[BLE_DEV_ADDR_LEN]; -/** Our supported features which can be controller by the host */ -uint64_t g_ble_ll_supported_host_features = 0; - static const uint16_t g_ble_ll_pdu_header_tx_time[BLE_PHY_NUM_MODE] = { [BLE_PHY_MODE_1M] = @@ -1206,8 +1203,6 @@ ble_ll_task(void *arg) /* Tell the host that we are ready to receive packets */ ble_ll_hci_send_noop(); - ble_ll_rand_start(); - while (1) { ev = ble_npl_eventq_get(&g_ble_ll_data.ll_evq, BLE_NPL_TIME_FOREVER); assert(ev); @@ -1305,10 +1300,6 @@ ble_ll_set_host_feat(const uint8_t *cmdbuf, uint8_t len) mask = (uint64_t)1 << (cmd->bit_num); if (!(mask & BLE_LL_HOST_CONTROLLED_FEATURES)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - if (!(mask & g_ble_ll_supported_host_features)) { return BLE_ERR_UNSUPPORTED; } @@ -1372,6 +1363,20 @@ ble_ll_mbuf_init(struct os_mbuf *m, uint8_t pdulen, uint8_t hdr) ble_hdr->txinfo.hdr_byte = hdr; } +static void +ble_ll_validate_task(void) +{ +#ifdef MYNEWT +#ifndef NDEBUG + struct os_task_info oti; + + os_task_info_get(&g_ble_ll_task, &oti); + + BLE_LL_ASSERT(oti.oti_stkusage < oti.oti_stksize); +#endif +#endif +} + /** * Called to reset the controller. This performs a "software reset" of the link * layer; it does not perform a HW reset of the controller nor does it reset @@ -1388,6 +1393,9 @@ ble_ll_reset(void) int rc; os_sr_t sr; + /* do sanity check on LL task stack */ + ble_ll_validate_task(); + OS_ENTER_CRITICAL(sr); ble_phy_disable(); ble_ll_sched_stop(); @@ -1447,23 +1455,6 @@ ble_ll_reset(void) return rc; } -static void -ble_ll_seed_prng(void) -{ - uint32_t seed; - int i; - - /* Seed random number generator with least significant bytes of device - * address. - */ - seed = 0; - for (i = 0; i < 4; ++i) { - seed |= g_dev_addr[i]; - seed <<= 8; - } - srand(seed); -} - uint32_t ble_ll_pdu_tx_time_get(uint16_t payload_len, int phy_mode) { @@ -1678,16 +1669,24 @@ ble_ll_init(void) features |= BLE_LL_FEAT_SYNC_TRANS_SEND; #endif - /* Initialize random number generation */ - ble_ll_rand_init(); +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE) + features |= BLE_LL_FEAT_SCA_UPDATE; +#endif - /* XXX: This really doesn't belong here, as the address probably has not - * been set yet. - */ - ble_ll_seed_prng(); +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO) + features |= BLE_LL_FEAT_CIS_MASTER; + features |= BLE_LL_FEAT_CIS_SLAVE; + features |= BLE_LL_FEAT_ISO_BROADCASTER; + features |= BLE_LL_FEAT_ISO_HOST_SUPPORT; +#endif lldata->ll_supp_features = features; + /* Initialize random number generation */ + ble_ll_rand_init(); + /* Start the random number generator */ + ble_ll_rand_start(); + rc = stats_init_and_reg(STATS_HDR(ble_ll_stats), STATS_SIZE_INIT_PARMS(ble_ll_stats, STATS_SIZE_32), STATS_NAME_INIT_PARMS(ble_ll_stats), diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_adv.c b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_adv.c index 4ffbe206..72c4e7d6 100644 --- a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_adv.c +++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_adv.c @@ -131,6 +131,7 @@ struct ble_ll_adv_sm uint8_t aux_index : 1; uint8_t aux_first_pdu : 1; uint8_t aux_not_scanned : 1; + uint8_t aux_dropped : 1; struct ble_mbuf_hdr *rx_ble_hdr; struct os_mbuf **aux_data; struct ble_ll_adv_aux aux[2]; @@ -685,7 +686,7 @@ ble_ll_adv_put_syncinfo(struct ble_ll_adv_sm *advsm, dptr[8] = advsm->periodic_chanmap[4] & 0x1f; /* SCA (3 bits) */ - dptr[8] |= MYNEWT_VAL(BLE_LL_MASTER_SCA) << 5; + dptr[8] |= BLE_LL_SCA_ENUM << 5; /* AA (4 bytes) */ put_le32(&dptr[9], advsm->periodic_access_addr); @@ -1269,7 +1270,7 @@ ble_ll_adv_secondary_tx_start_cb(struct ble_ll_sched_item *sch) rc = ble_phy_tx_set_start_time(txstart, sch->remainder); if (rc) { STATS_INC(ble_ll_stats, adv_late_starts); - goto adv_tx_done; + goto adv_aux_dropped; } #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) @@ -1304,7 +1305,7 @@ ble_ll_adv_secondary_tx_start_cb(struct ble_ll_sched_item *sch) /* Transmit advertisement */ rc = ble_phy_tx(pducb, advsm, end_trans); if (rc) { - goto adv_tx_done; + goto adv_aux_dropped; } /* Enable/disable whitelisting based on filter policy */ @@ -1322,7 +1323,8 @@ ble_ll_adv_secondary_tx_start_cb(struct ble_ll_sched_item *sch) return BLE_LL_SCHED_STATE_RUNNING; -adv_tx_done: +adv_aux_dropped: + advsm->aux_dropped = 1; ble_ll_adv_tx_done(advsm); return BLE_LL_SCHED_STATE_DONE; } @@ -1377,7 +1379,7 @@ ble_ll_adv_aux_calculate(struct ble_ll_adv_sm *advsm, g_ble_ll_conn_params.num_used_chans, g_ble_ll_conn_params.master_chan_map); #else - aux->chan = ble_ll_utils_remapped_channel(rand() % BLE_PHY_NUM_DATA_CHANS, + aux->chan = ble_ll_utils_remapped_channel(ble_ll_rand() % BLE_PHY_NUM_DATA_CHANS, g_ble_ll_conn_params.master_chan_map); #endif @@ -1554,6 +1556,7 @@ ble_ll_adv_aux_schedule_first(struct ble_ll_adv_sm *advsm) advsm->aux_index = 0; advsm->aux_first_pdu = 1; advsm->aux_not_scanned = 0; + advsm->aux_dropped = 0; aux = AUX_CURRENT(advsm); ble_ll_adv_aux_calculate(advsm, aux, 0); @@ -1853,7 +1856,7 @@ ble_ll_adv_update_did(struct ble_ll_adv_sm *advsm) * the previously used value. */ do { - advsm->adi = (advsm->adi & 0xf000) | (rand() & 0x0fff); + advsm->adi = (advsm->adi & 0xf000) | (ble_ll_rand() & 0x0fff); } while (old_adi == advsm->adi); } #endif @@ -2544,11 +2547,11 @@ ble_ll_adv_sm_start_periodic(struct ble_ll_adv_sm *advsm) advsm->periodic_num_used_chans = g_ble_ll_conn_params.num_used_chans; advsm->periodic_event_cntr = 0; /* for chaining we start with random counter as we share access addr */ - advsm->periodic_chain_event_cntr = rand(); + advsm->periodic_chain_event_cntr = ble_ll_rand(); advsm->periodic_access_addr = ble_ll_utils_calc_access_addr(); advsm->periodic_channel_id = ((advsm->periodic_access_addr & 0xffff0000) >> 16) ^ (advsm->periodic_access_addr & 0x0000ffff); - advsm->periodic_crcinit = rand() & 0xffffff; + advsm->periodic_crcinit = ble_ll_rand() & 0xffffff; usecs = (uint32_t)advsm->periodic_adv_itvl_max * BLE_LL_ADV_PERIODIC_ITVL; ticks = os_cputime_usecs_to_ticks(usecs); @@ -2737,7 +2740,7 @@ ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm) */ earliest_start_time = ble_ll_rfmgmt_enable_now(); - start_delay_us = rand() % (BLE_LL_ADV_DELAY_MS_MAX * 1000); + start_delay_us = ble_ll_rand() % (BLE_LL_ADV_DELAY_MS_MAX * 1000); advsm->adv_pdu_start_time = os_cputime_get32() + os_cputime_usecs_to_ticks(start_delay_us); @@ -4019,8 +4022,8 @@ ble_ll_adv_periodic_send_sync_ind(struct ble_ll_adv_sm *advsm, /* SID, AType, SCA */ sync_ind[24] = (advsm->adi >> 12); - sync_ind[24] |= !!(advsm->flags & BLE_LL_ADV_SM_FLAG_TX_ADD) << 4 ; - sync_ind[24] |= MYNEWT_VAL(BLE_LL_MASTER_SCA) << 5; + sync_ind[24] |= !!(advsm->flags & BLE_LL_ADV_SM_FLAG_TX_ADD) << 4; + sync_ind[24] |= BLE_LL_SCA_ENUM << 5; /* PHY */ sync_ind[25] = (0x01 << (advsm->sec_phy - 1)); @@ -4836,6 +4839,11 @@ ble_ll_adv_sec_done(struct ble_ll_adv_sm *advsm) /* We don't need RF anymore */ ble_ll_rfmgmt_release(); + if (advsm->aux_dropped) { + ble_ll_adv_drop_event(advsm); + return; + } + if (advsm->aux_not_scanned) { ble_ll_sched_rmv_elem(&aux_next->sch); } diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_conn.c b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_conn.c index 1b17a0d2..b8352f4a 100644 --- a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_conn.c +++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_conn.c @@ -225,6 +225,166 @@ STATS_NAME_END(ble_ll_conn_stats) static void ble_ll_conn_event_end(struct ble_npl_event *ev); +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL) +struct ble_ll_conn_cth_flow { + bool enabled; + uint16_t max_buffers; + uint16_t num_buffers; +}; + +static struct ble_ll_conn_cth_flow g_ble_ll_conn_cth_flow; + +static struct ble_npl_event g_ble_ll_conn_cth_flow_error_ev; + +static bool +ble_ll_conn_cth_flow_is_enabled(void) +{ + return g_ble_ll_conn_cth_flow.enabled; +} + +static bool +ble_ll_conn_cth_flow_alloc_credit(struct ble_ll_conn_sm *connsm) +{ + struct ble_ll_conn_cth_flow *cth = &g_ble_ll_conn_cth_flow; + os_sr_t sr; + + OS_ENTER_CRITICAL(sr); + + if (!cth->num_buffers) { + OS_EXIT_CRITICAL(sr); + return false; + } + + connsm->cth_flow_pending++; + cth->num_buffers--; + + OS_EXIT_CRITICAL(sr); + + return true; +} + +static void +ble_ll_conn_cth_flow_free_credit(struct ble_ll_conn_sm *connsm, uint16_t credits) +{ + struct ble_ll_conn_cth_flow *cth = &g_ble_ll_conn_cth_flow; + os_sr_t sr; + + OS_ENTER_CRITICAL(sr); + + /* + * It's not quite clear what we should do if host gives back more credits + * that we have allocated. For now let's just set invalid values back to + * sane values and continue. + */ + + cth->num_buffers += credits; + if (cth->num_buffers > cth->max_buffers) { + cth->num_buffers = cth->max_buffers; + } + + if (connsm->cth_flow_pending < credits) { + connsm->cth_flow_pending = 0; + } else { + connsm->cth_flow_pending -= credits; + } + + OS_EXIT_CRITICAL(sr); +} + +static void +ble_ll_conn_cth_flow_error_fn(struct ble_npl_event *ev) +{ + struct ble_hci_ev *hci_ev; + struct ble_hci_ev_command_complete *hci_ev_cp; + uint16_t opcode; + + hci_ev = (void *)ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); + if (!hci_ev) { + /* Not much we can do anyway... */ + return; + } + + /* + * We are here in case length of HCI_Host_Number_Of_Completed_Packets was + * invalid. We will send an error back to host and we can only hope host is + * reasonable and will do some actions to recover, e.g. it should disconnect + * all connections to guarantee that all credits are back in pool and we're + * back in sync (although spec does not really say what should happen). + */ + + opcode = BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND, + BLE_HCI_OCF_CB_HOST_NUM_COMP_PKTS); + + hci_ev->opcode = BLE_HCI_EVCODE_COMMAND_COMPLETE; + hci_ev->length = sizeof(*hci_ev_cp); + + hci_ev_cp = (void *)hci_ev->data; + hci_ev_cp->num_packets = BLE_LL_CFG_NUM_HCI_CMD_PKTS; + hci_ev_cp->opcode = htole16(opcode); + hci_ev_cp->status = BLE_ERR_INV_HCI_CMD_PARMS; + + ble_ll_hci_event_send(hci_ev); +} + +void +ble_ll_conn_cth_flow_set_buffers(uint16_t num_buffers) +{ + BLE_LL_ASSERT(num_buffers); + + g_ble_ll_conn_cth_flow.max_buffers = num_buffers; + g_ble_ll_conn_cth_flow.num_buffers = num_buffers; +} + +bool +ble_ll_conn_cth_flow_enable(bool enabled) +{ + struct ble_ll_conn_cth_flow *cth = &g_ble_ll_conn_cth_flow; + + if (cth->enabled == enabled) { + return true; + } + + if (!SLIST_EMPTY(&g_ble_ll_conn_active_list)) { + return false; + } + + cth->enabled = enabled; + + return true; +} + +void +ble_ll_conn_cth_flow_process_cmd(const uint8_t *cmdbuf) +{ + const struct ble_hci_cmd *cmd; + const struct ble_hci_cb_host_num_comp_pkts_cp *cp; + struct ble_ll_conn_sm *connsm; + int i; + + cmd = (const void *)cmdbuf; + cp = (const void *)cmd->data; + + if (cmd->length != sizeof(cp->handles) + cp->handles * sizeof(cp->h[0])) { + ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_conn_cth_flow_error_ev); + return; + } + + for (i = 0; i < cp->handles; i++) { + /* + * It's probably ok that we do not have active connection with given + * handle - this can happen if disconnection already happened in LL but + * host sent credits back before processing disconnection event. In such + * case we can simply ignore command for that connection since credits + * are returned by LL already. + */ + connsm = ble_ll_conn_find_active_conn(cp->h[i].handle); + if (connsm) { + ble_ll_conn_cth_flow_free_credit(connsm, cp->h[i].count); + } + } +} +#endif + #if (BLE_LL_BT5_PHY_SUPPORTED == 1) /** * Checks to see if we should start a PHY update procedure @@ -332,7 +492,7 @@ ble_ll_conn_is_lru(struct ble_ll_conn_sm *s1, struct ble_ll_conn_sm *s2) int rc; /* Set time that we last serviced the schedule */ - if ((int32_t)(s1->last_scheduled - s2->last_scheduled) < 0) { + if (CPUTIME_LT(s1->last_scheduled, s2->last_scheduled)) { rc = 1; } else { rc = 0; @@ -855,8 +1015,14 @@ ble_ll_conn_tx_pdu(struct ble_ll_conn_sm *connsm) /* * If we are encrypting, we are only allowed to send certain * kinds of LL control PDU's. If none is enqueued, send empty pdu! + * + * In Slave role, we are allowed to send unencrypted packets until + * LL_ENC_RSP is sent. */ - if (connsm->enc_data.enc_state > CONN_ENC_S_ENCRYPTED) { + if (((connsm->enc_data.enc_state > CONN_ENC_S_ENCRYPTED) && + CONN_IS_MASTER(connsm)) || + ((connsm->enc_data.enc_state > CONN_ENC_S_ENC_RSP_TO_BE_SENT) && + CONN_IS_SLAVE(connsm))) { if (!ble_ll_ctrl_enc_allowed_pdu_tx(pkthdr)) { CONN_F_EMPTY_PDU_TXD(connsm) = 1; goto conn_tx_pdu; @@ -991,10 +1157,10 @@ ble_ll_conn_tx_pdu(struct ble_ll_conn_sm *connsm) } ticks = os_cputime_usecs_to_ticks(ticks); - if ((int32_t)((os_cputime_get32() + ticks) - next_event_time) < 0) { + if (CPUTIME_LT(os_cputime_get32() + ticks, next_event_time)) { md = 1; } - } + } /* If we send an empty PDU we need to initialize the header */ conn_tx_pdu: @@ -1450,10 +1616,10 @@ ble_ll_conn_master_common_init(struct ble_ll_conn_sm *connsm) */ connsm->tx_win_size = BLE_LL_CONN_TX_WIN_MIN + 1; connsm->tx_win_off = 0; - connsm->master_sca = MYNEWT_VAL(BLE_LL_MASTER_SCA); + connsm->master_sca = BLE_LL_SCA_ENUM; /* Hop increment is a random value between 5 and 16. */ - connsm->hop_inc = (rand() % 12) + 5; + connsm->hop_inc = (ble_ll_rand() % 12) + 5; /* Set channel map to map requested by host */ connsm->num_used_chans = g_ble_ll_conn_params.num_used_chans; @@ -1462,7 +1628,7 @@ ble_ll_conn_master_common_init(struct ble_ll_conn_sm *connsm) /* Calculate random access address and crc initialization value */ connsm->access_addr = ble_ll_utils_calc_access_addr(); - connsm->crcinit = rand() & 0xffffff; + connsm->crcinit = ble_ll_rand() & 0xffffff; /* Set initial schedule callback */ connsm->conn_sch.sched_cb = ble_ll_conn_event_start_cb; @@ -1861,6 +2027,10 @@ ble_ll_conn_end(struct ble_ll_conn_sm *connsm, uint8_t ble_err) /* Remove from the active connection list */ SLIST_REMOVE(&g_ble_ll_conn_active_list, connsm, ble_ll_conn_sm, act_sle); +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL) + ble_ll_conn_cth_flow_free_credit(connsm, connsm->cth_flow_pending); +#endif + /* Free the current transmit pdu if there is one. */ if (connsm->cur_tx_pdu) { os_mbuf_free_chain(connsm->cur_tx_pdu); @@ -3239,6 +3409,13 @@ ble_ll_init_rx_isr_end(uint8_t *rxbuf, uint8_t crcok, */ memcpy(init_addr, rl->rl_local_rpa, BLE_DEV_ADDR_LEN); } + } else if (!ble_ll_is_rpa(adv_addr, adv_addr_type)) { + /* undirected with ID address, assure privacy if on RL */ + rl = ble_ll_resolv_list_find(adv_addr, adv_addr_type); + if (rl && (rl->rl_priv_mode == BLE_HCI_PRIVACY_NETWORK) && + rl->rl_has_peer) { + goto init_rx_isr_exit; + } } #endif @@ -3452,129 +3629,142 @@ ble_ll_conn_rx_data_pdu(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr) uint16_t acl_hdr; struct ble_ll_conn_sm *connsm; - if (BLE_MBUF_HDR_CRC_OK(hdr)) { - /* XXX: there is a chance that the connection was thrown away and - re-used before processing packets here. Fix this. */ - /* We better have a connection state machine */ - connsm = ble_ll_conn_find_active_conn(hdr->rxinfo.handle); - if (connsm) { - /* Check state machine */ - ble_ll_conn_chk_csm_flags(connsm); + /* Packets with invalid CRC are not sent to LL */ + BLE_LL_ASSERT(BLE_MBUF_HDR_CRC_OK(hdr)); - /* Validate rx data pdu */ - rxbuf = rxpdu->om_data; - hdr_byte = rxbuf[0]; - acl_len = rxbuf[1]; - llid = hdr_byte & BLE_LL_DATA_HDR_LLID_MASK; + /* XXX: there is a chance that the connection was thrown away and + re-used before processing packets here. Fix this. */ + /* We better have a connection state machine */ + connsm = ble_ll_conn_find_active_conn(hdr->rxinfo.handle); + if (!connsm) { + STATS_INC(ble_ll_conn_stats, no_conn_sm); + goto conn_rx_data_pdu_end; + } - /* - * Check that the LLID and payload length are reasonable. - * Empty payload is only allowed for LLID == 01b. - * */ - if ((llid == 0) || - ((acl_len == 0) && (llid != BLE_LL_LLID_DATA_FRAG))) { - STATS_INC(ble_ll_conn_stats, rx_bad_llid); - goto conn_rx_data_pdu_end; - } + /* Check state machine */ + ble_ll_conn_chk_csm_flags(connsm); + + /* Validate rx data pdu */ + rxbuf = rxpdu->om_data; + hdr_byte = rxbuf[0]; + acl_len = rxbuf[1]; + llid = hdr_byte & BLE_LL_DATA_HDR_LLID_MASK; + + /* + * Check that the LLID and payload length are reasonable. + * Empty payload is only allowed for LLID == 01b. + * */ + if ((llid == 0) || ((acl_len == 0) && (llid != BLE_LL_LLID_DATA_FRAG))) { + STATS_INC(ble_ll_conn_stats, rx_bad_llid); + goto conn_rx_data_pdu_end; + } #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - /* Check if PDU is allowed when encryption is started. If not, - * terminate connection. - * - * Reference: Core 5.0, Vol 6, Part B, 5.1.3.1 - */ - if ((connsm->enc_data.enc_state > CONN_ENC_S_PAUSE_ENC_RSP_WAIT) && - !ble_ll_ctrl_enc_allowed_pdu_rx(rxpdu)) { - ble_ll_conn_timeout(connsm, BLE_ERR_CONN_TERM_MIC); - goto conn_rx_data_pdu_end; - } + /* Check if PDU is allowed when encryption is started. If not, + * terminate connection. + * + * Reference: Core 5.0, Vol 6, Part B, 5.1.3.1 + */ + if ((connsm->enc_data.enc_state > CONN_ENC_S_PAUSE_ENC_RSP_WAIT && + CONN_IS_MASTER(connsm)) || + (connsm->enc_data.enc_state >= CONN_ENC_S_ENC_RSP_TO_BE_SENT && + CONN_IS_SLAVE(connsm))) { + if (!ble_ll_ctrl_enc_allowed_pdu_rx(rxpdu)) { + ble_ll_conn_timeout(connsm, BLE_ERR_CONN_TERM_MIC); + goto conn_rx_data_pdu_end; + } + } #endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) - /* - * Reset authenticated payload timeout if valid MIC. NOTE: we dont - * check the MIC failure bit as that would have terminated the - * connection - */ - if ((connsm->enc_data.enc_state == CONN_ENC_S_ENCRYPTED) && - CONN_F_LE_PING_SUPP(connsm) && (acl_len != 0)) { - ble_ll_conn_auth_pyld_timer_start(connsm); - } + /* + * Reset authenticated payload timeout if valid MIC. NOTE: we dont + * check the MIC failure bit as that would have terminated the + * connection + */ + if ((connsm->enc_data.enc_state == CONN_ENC_S_ENCRYPTED) && + CONN_F_LE_PING_SUPP(connsm) && (acl_len != 0)) { + ble_ll_conn_auth_pyld_timer_start(connsm); + } #endif - /* Update RSSI */ - connsm->conn_rssi = hdr->rxinfo.rssi; + /* Update RSSI */ + connsm->conn_rssi = hdr->rxinfo.rssi; - /* - * If we are a slave, we can only start to use slave latency - * once we have received a NESN of 1 from the master - */ - if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { - if (hdr_byte & BLE_LL_DATA_HDR_NESN_MASK) { - connsm->csmflags.cfbit.allow_slave_latency = 1; - } - } + /* + * If we are a slave, we can only start to use slave latency + * once we have received a NESN of 1 from the master + */ + if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { + if (hdr_byte & BLE_LL_DATA_HDR_NESN_MASK) { + connsm->csmflags.cfbit.allow_slave_latency = 1; + } + } - /* - * Discard the received PDU if the sequence number is the same - * as the last received sequence number - */ - rxd_sn = hdr_byte & BLE_LL_DATA_HDR_SN_MASK; - if (rxd_sn != connsm->last_rxd_sn) { - /* Update last rxd sn */ - connsm->last_rxd_sn = rxd_sn; - - /* No need to do anything if empty pdu */ - if ((llid == BLE_LL_LLID_DATA_FRAG) && (acl_len == 0)) { - goto conn_rx_data_pdu_end; - } + /* + * Discard the received PDU if the sequence number is the same + * as the last received sequence number + */ + rxd_sn = hdr_byte & BLE_LL_DATA_HDR_SN_MASK; + if (rxd_sn == connsm->last_rxd_sn) { + STATS_INC(ble_ll_conn_stats, data_pdu_rx_dup); + goto conn_rx_data_pdu_end; + } + + /* Update last rxd sn */ + connsm->last_rxd_sn = rxd_sn; + + /* No need to do anything if empty pdu */ + if ((llid == BLE_LL_LLID_DATA_FRAG) && (acl_len == 0)) { + goto conn_rx_data_pdu_end; + } #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - /* - * XXX: should we check to see if we are in a state where we - * might expect to get an encrypted PDU? - */ - if (BLE_MBUF_HDR_MIC_FAILURE(hdr)) { - STATS_INC(ble_ll_conn_stats, mic_failures); - ble_ll_conn_timeout(connsm, BLE_ERR_CONN_TERM_MIC); - goto conn_rx_data_pdu_end; - } + /* + * XXX: should we check to see if we are in a state where we + * might expect to get an encrypted PDU? + */ + if (BLE_MBUF_HDR_MIC_FAILURE(hdr)) { + STATS_INC(ble_ll_conn_stats, mic_failures); + ble_ll_conn_timeout(connsm, BLE_ERR_CONN_TERM_MIC); + goto conn_rx_data_pdu_end; + } #endif - if (llid == BLE_LL_LLID_CTRL) { - /* Process control frame */ - STATS_INC(ble_ll_conn_stats, rx_ctrl_pdus); - if (ble_ll_ctrl_rx_pdu(connsm, rxpdu)) { - STATS_INC(ble_ll_conn_stats, rx_malformed_ctrl_pdus); - } - } else { - /* Count # of received l2cap frames and byes */ - STATS_INC(ble_ll_conn_stats, rx_l2cap_pdus); - STATS_INCN(ble_ll_conn_stats, rx_l2cap_bytes, acl_len); - - /* NOTE: there should be at least two bytes available */ - BLE_LL_ASSERT(OS_MBUF_LEADINGSPACE(rxpdu) >= 2); - os_mbuf_prepend(rxpdu, 2); - rxbuf = rxpdu->om_data; - - acl_hdr = (llid << 12) | connsm->conn_handle; - put_le16(rxbuf, acl_hdr); - put_le16(rxbuf + 2, acl_len); - ble_hci_trans_ll_acl_tx(rxpdu); - } - - /* NOTE: we dont free the mbuf since we handed it off! */ - return; - } else { - STATS_INC(ble_ll_conn_stats, data_pdu_rx_dup); - } - } else { - STATS_INC(ble_ll_conn_stats, no_conn_sm); + if (llid == BLE_LL_LLID_CTRL) { + /* Process control frame */ + STATS_INC(ble_ll_conn_stats, rx_ctrl_pdus); + if (ble_ll_ctrl_rx_pdu(connsm, rxpdu)) { + STATS_INC(ble_ll_conn_stats, rx_malformed_ctrl_pdus); } + } else { + /* Count # of received l2cap frames and byes */ + STATS_INC(ble_ll_conn_stats, rx_l2cap_pdus); + STATS_INCN(ble_ll_conn_stats, rx_l2cap_bytes, acl_len); + + /* NOTE: there should be at least two bytes available */ + BLE_LL_ASSERT(OS_MBUF_LEADINGSPACE(rxpdu) >= 2); + os_mbuf_prepend(rxpdu, 2); + rxbuf = rxpdu->om_data; + + acl_hdr = (llid << 12) | connsm->conn_handle; + put_le16(rxbuf, acl_hdr); + put_le16(rxbuf + 2, acl_len); + ble_hci_trans_ll_acl_tx(rxpdu); } + /* NOTE: we dont free the mbuf since we handed it off! */ + return; + /* Free buffer */ conn_rx_data_pdu_end: +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL) + /* Need to give credit back if we allocated one for this PDU */ + if (hdr->rxinfo.flags & BLE_MBUF_HDR_F_CONN_CREDIT) { + ble_ll_conn_cth_flow_free_credit(connsm, 1); + } +#endif + os_mbuf_free_chain(rxpdu); } @@ -3595,7 +3785,6 @@ int ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) { int rc; - int is_ctrl; uint8_t hdr_byte; uint8_t hdr_sn; uint8_t hdr_nesn; @@ -3609,14 +3798,43 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) uint32_t add_usecs; struct os_mbuf *txpdu; struct ble_ll_conn_sm *connsm; - struct os_mbuf *rxpdu; + struct os_mbuf *rxpdu = NULL; struct ble_mbuf_hdr *txhdr; int rx_phy_mode; + bool alloc_rxpdu = true; + + rc = -1; + connsm = g_ble_ll_conn_cur_sm; /* Retrieve the header and payload length */ hdr_byte = rxbuf[0]; rx_pyld_len = rxbuf[1]; + /* + * No need to alloc rxpdu for packets with invalid CRC, we would throw them + * away instantly from LL anyway. + */ + if (!BLE_MBUF_HDR_CRC_OK(rxhdr)) { + alloc_rxpdu = false; + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL) + /* + * If flow control is enabled, we need to have credit available for each + * non-empty data packet that LL may send to host. If there are no credits + * available, we don't need to allocate buffer for this packet so LL will + * nak it. + */ + if (alloc_rxpdu && ble_ll_conn_cth_flow_is_enabled() && + BLE_LL_LLID_IS_DATA(hdr_byte) && (rx_pyld_len > 0)) { + if (ble_ll_conn_cth_flow_alloc_credit(connsm)) { + rxhdr->rxinfo.flags |= BLE_MBUF_HDR_F_CONN_CREDIT; + } else { + alloc_rxpdu = false; + } + } +#endif + /* * We need to attempt to allocate a buffer here. The reason we do this * now is that we should not ack the packet if we have no receive @@ -3624,14 +3842,14 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) * acked, but we should not ack the received frame if we cant hand it up. * NOTE: we hand up empty pdu's to the LL task! */ - rxpdu = ble_ll_rxpdu_alloc(rx_pyld_len + BLE_LL_PDU_HDR_LEN); + if (alloc_rxpdu) { + rxpdu = ble_ll_rxpdu_alloc(rx_pyld_len + BLE_LL_PDU_HDR_LEN); + } /* * We should have a current connection state machine. If we dont, we just * hand the packet to the higher layer to count it. */ - rc = -1; - connsm = g_ble_ll_conn_cur_sm; if (!connsm) { STATS_INC(ble_ll_conn_stats, rx_data_pdu_no_conn); goto conn_exit; @@ -3693,9 +3911,7 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) /* Set last received header byte */ connsm->last_rxd_hdr_byte = hdr_byte; - is_ctrl = 0; - if ((hdr_byte & BLE_LL_DATA_HDR_LLID_MASK) == BLE_LL_LLID_CTRL) { - is_ctrl = 1; + if (BLE_LL_LLID_IS_CTRL(hdr_byte)) { opcode = rxbuf[2]; } @@ -3784,7 +4000,7 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) /* Adjust payload for max TX time and octets */ #if (BLE_LL_BT5_PHY_SUPPORTED == 1) - if (is_ctrl && + if (BLE_LL_LLID_IS_CTRL(hdr_byte) && (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) && (opcode == BLE_LL_CTRL_PHY_UPDATE_IND)) { connsm->phy_tx_transition = @@ -3803,8 +4019,9 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) /* If this is a TERMINATE_IND, we have to reply */ chk_rx_terminate_ind: /* If we received a terminate IND, we must set some flags */ - if (is_ctrl && (opcode == BLE_LL_CTRL_TERMINATE_IND) - && (rx_pyld_len == (1 + BLE_LL_CTRL_TERMINATE_IND_LEN))) { + if (BLE_LL_LLID_IS_CTRL(hdr_byte) && + (opcode == BLE_LL_CTRL_TERMINATE_IND) && + (rx_pyld_len == (1 + BLE_LL_CTRL_TERMINATE_IND_LEN))) { connsm->csmflags.cfbit.terminate_ind_rxd = 1; connsm->rxd_disconnect_reason = rxbuf[3]; } @@ -4226,6 +4443,12 @@ ble_ll_conn_module_reset(void) g_ble_ll_conn_sync_transfer_params.mode = 0; g_ble_ll_conn_sync_transfer_params.sync_timeout_us = 0; #endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL) + g_ble_ll_conn_cth_flow.enabled = false; + g_ble_ll_conn_cth_flow.max_buffers = 1; + g_ble_ll_conn_cth_flow.num_buffers = 1; +#endif } /* Initialize the connection module */ @@ -4265,6 +4488,11 @@ ble_ll_conn_module_init(void) "ble_ll_conn"); BLE_LL_ASSERT(rc == 0); +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL) + ble_npl_event_init(&g_ble_ll_conn_cth_flow_error_ev, + ble_ll_conn_cth_flow_error_fn, NULL); +#endif + /* Call reset to finish reset of initialization */ ble_ll_conn_module_reset(); } diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_conn_hci.c b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_conn_hci.c index 1350fdc0..9936b9d3 100644 --- a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_conn_hci.c +++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_conn_hci.c @@ -1128,16 +1128,11 @@ ble_ll_conn_create_cancel(ble_ll_hci_post_cmd_complete_cb *post_cmd_cb) * @return int */ int -ble_ll_conn_hci_disconnect_cmd(const uint8_t *cmdbuf, uint8_t len) +ble_ll_conn_hci_disconnect_cmd(const struct ble_hci_lc_disconnect_cp *cmd) { int rc; uint16_t handle; struct ble_ll_conn_sm *connsm; - const struct ble_hci_lc_disconnect_cp *cmd = (const void *) cmdbuf; - - if (len != sizeof (*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } /* Check for valid parameters */ handle = le16toh(cmd->conn_handle); @@ -1565,6 +1560,34 @@ ltk_key_cmd_complete: } #endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE) +int +ble_ll_conn_req_peer_sca(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen) +{ + const struct ble_hci_le_request_peer_sca_cp *params = (const void *)cmdbuf; + struct ble_ll_conn_sm *connsm; + + connsm = ble_ll_conn_find_active_conn(params->conn_handle); + if (!connsm) { + return BLE_ERR_UNK_CONN_ID; + } + + if (!(connsm->remote_features[2] & (BLE_LL_FEAT_SCA_UPDATE >> 24))) { + return BLE_ERR_UNSUPP_REM_FEATURE; + } + + if (IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_SCA_UPDATE)) { + /* Not really specified what we should return */ + return BLE_ERR_CTLR_BUSY; + } + + ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_SCA_UPDATE); + + return 0; +} +#endif + #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) /** * Read authenticated payload timeout (OGF=3, OCF==0x007B) diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_conn_priv.h b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_conn_priv.h index f2f72d17..53358c4a 100644 --- a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_conn_priv.h +++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_conn_priv.h @@ -164,7 +164,7 @@ bool ble_ll_conn_init_pending_aux_conn_rsp(void); void ble_ll_disconn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t reason); void ble_ll_auth_pyld_tmo_event_send(struct ble_ll_conn_sm *connsm); -int ble_ll_conn_hci_disconnect_cmd(const uint8_t *cmdbuf, uint8_t len); +int ble_ll_conn_hci_disconnect_cmd(const struct ble_hci_lc_disconnect_cp *cmd); int ble_ll_conn_hci_rd_rem_ver_cmd(const uint8_t *cmdbuf, uint8_t len); int ble_ll_conn_create(const uint8_t *cmdbuf, uint8_t len); int ble_ll_conn_hci_update(const uint8_t *cmdbuf, uint8_t len); @@ -196,12 +196,23 @@ int ble_ll_conn_hci_wr_auth_pyld_tmo(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen); int ble_ll_conn_hci_rd_auth_pyld_tmo(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen); +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE) +int ble_ll_conn_req_peer_sca(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen); +#endif + #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) void ble_ll_conn_auth_pyld_timer_start(struct ble_ll_conn_sm *connsm); #else #define ble_ll_conn_auth_pyld_timer_start(x) #endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL) +void ble_ll_conn_cth_flow_set_buffers(uint16_t num_buffers); +bool ble_ll_conn_cth_flow_enable(bool enabled); +void ble_ll_conn_cth_flow_process_cmd(const uint8_t *cmdbuf); +#endif + int ble_ll_hci_cmd_rx(uint8_t *cmd, void *arg); int ble_ll_hci_acl_rx(struct os_mbuf *om, void *arg); diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_ctrl.c b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_ctrl.c index ea2ba834..c4ac6504 100644 --- a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_ctrl.c +++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_ctrl.c @@ -112,6 +112,10 @@ const uint8_t g_ble_ll_ctrl_pkt_lengths[BLE_LL_CTRL_OPCODES] = BLE_LL_CTRL_PERIODIC_SYNC_IND_LEN, BLE_LL_CTRL_CLOCK_ACCURACY_REQ_LEN, BLE_LL_CTRL_CLOCK_ACCURACY_RSP_LEN, + BLE_LL_CTRL_CIS_REQ_LEN, + BLE_LL_CTRL_CIS_RSP_LEN, + BLE_LL_CTRL_CIS_IND_LEN, + BLE_LL_CTRL_CIS_TERMINATE_LEN }; /** @@ -505,6 +509,12 @@ ble_ll_ctrl_proc_unk_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr, uint8_t * ble_ll_ctrl_phy_update_cancel(connsm, BLE_ERR_UNSUPP_REM_FEATURE); ctrl_proc = BLE_LL_CTRL_PROC_PHY_UPDATE; break; +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE) + case BLE_LL_CTRL_CLOCK_ACCURACY_REQ: + ble_ll_hci_ev_sca_update(connsm, BLE_ERR_UNSUPPORTED, 0); + ctrl_proc = BLE_LL_CTRL_PROC_SCA_UPDATE; + break; #endif default: ctrl_proc = BLE_LL_CTRL_PROC_NUM; @@ -836,6 +846,20 @@ ble_ll_ctrl_phy_req_rsp_make(struct ble_ll_conn_sm *connsm, uint8_t *ctrdata) } } +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE) +/** + * Create a LL_CLOCK_ACCURACY_REQ or LL_CLOCK_ACCURACY_RSP pdu + * + * @param connsm Pointer to connection state machine + * @param ctrdata: Pointer to where CtrData starts in pdu + */ +static void +ble_ll_ctrl_sca_req_rsp_make(struct ble_ll_conn_sm *connsm, uint8_t *ctrdata) +{ + ctrdata[0] = BLE_LL_SCA_ENUM; +} +#endif + static uint8_t ble_ll_ctrl_rx_phy_req(struct ble_ll_conn_sm *connsm, uint8_t *req, uint8_t *rsp) @@ -1040,11 +1064,70 @@ ble_ll_ctrl_rx_periodic_sync_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr) connsm->sync_transfer_skip, connsm->sync_transfer_sync_timeout); } + return BLE_ERR_MAX; +} +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE) +/** + * Called when a BLE_LL_CTRL_CLOCK_ACCURACY_REQ PDU is received + * + * @param connsm + * @param dptr + * @param rsp Pointer to CtrData of BLE_LL_CTRL_CLOCK_ACCURACY_RSP. + * + * @return uint8_t + */ +static uint8_t +ble_ll_ctrl_rx_sca_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr, + uint8_t *rsp) +{ + ble_ll_ctrl_sca_req_rsp_make(connsm, rsp); + return BLE_LL_CTRL_CLOCK_ACCURACY_RSP; +} + +/** + * Called when a BLE_LL_CTRL_CLOCK_ACCURACY_RSP PDU is received + * + * @param connsm + * @param dptr + * + * @return uint8_t + */ +static uint8_t +ble_ll_ctrl_rx_sca_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr) +{ + if (connsm->cur_ctrl_proc != BLE_LL_CTRL_PROC_SCA_UPDATE) { + return BLE_LL_CTRL_UNKNOWN_RSP; + } + ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_SCA_UPDATE); + ble_ll_hci_ev_sca_update(connsm, BLE_ERR_SUCCESS, dptr[0]); return BLE_ERR_MAX; } + #endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO) +static uint8_t +ble_ll_ctrl_rx_cis_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr, + uint8_t *rspdata) +{ + return BLE_LL_CTRL_UNKNOWN_RSP; +} + +static uint8_t +ble_ll_ctrl_rx_cis_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr, + uint8_t *rspdata) +{ + return BLE_LL_CTRL_UNKNOWN_RSP; +} + +static uint8_t +ble_ll_ctrl_rx_cis_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr) +{ + return BLE_LL_CTRL_UNKNOWN_RSP; +} +#endif /** * Create a link layer length request or length response PDU. * @@ -1250,6 +1333,15 @@ ble_ll_ctrl_start_enc_send(struct ble_ll_conn_sm *connsm) return rc; } +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO) +static void +ble_ll_ctrl_cis_create(struct ble_ll_conn_sm *connsm, uint8_t *dptr) +{ + /* TODO Implement */ + return; +} +#endif + /** * Create a link layer control "encrypt request" PDU. * @@ -1351,7 +1443,7 @@ ble_ll_ctrl_rx_enc_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr, return BLE_LL_CTRL_UNKNOWN_RSP; } - connsm->enc_data.enc_state = CONN_ENC_S_LTK_REQ_WAIT; + connsm->enc_data.enc_state = CONN_ENC_S_ENC_RSP_TO_BE_SENT; /* In case we were already encrypted we need to reset packet counters */ connsm->enc_data.rx_pkt_cntr = 0; @@ -1676,6 +1768,12 @@ ble_ll_ctrl_rx_reject_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr, */ ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_DATA_LEN_UPD); break; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE) + case BLE_LL_CTRL_PROC_SCA_UPDATE: + ble_ll_hci_ev_sca_update(connsm, ble_error, 0); + ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_SCA_UPDATE); + break; +#endif default: break; } @@ -2138,6 +2236,18 @@ ble_ll_ctrl_proc_init(struct ble_ll_conn_sm *connsm, int ctrl_proc) opcode = BLE_LL_CTRL_PHY_REQ; ble_ll_ctrl_phy_req_rsp_make(connsm, ctrdata); break; +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE) + case BLE_LL_CTRL_PROC_SCA_UPDATE: + opcode = BLE_LL_CTRL_CLOCK_ACCURACY_REQ; + ble_ll_ctrl_sca_req_rsp_make(connsm, ctrdata); + break; +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO) + case BLE_LL_CTRL_PROC_CIS_CREATE: + opcode = BLE_LL_CTRL_CIS_REQ; + ble_ll_ctrl_cis_create(connsm, ctrdata); + break; #endif default: BLE_LL_ASSERT(0); @@ -2568,6 +2678,26 @@ ble_ll_ctrl_rx_pdu(struct ble_ll_conn_sm *connsm, struct os_mbuf *om) rsp_opcode = ble_ll_ctrl_rx_phy_update_ind(connsm, dptr); break; #endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE) + case BLE_LL_CTRL_CLOCK_ACCURACY_REQ: + rsp_opcode = ble_ll_ctrl_rx_sca_req(connsm, dptr, rspdata); + break; + case BLE_LL_CTRL_CLOCK_ACCURACY_RSP: + rsp_opcode = ble_ll_ctrl_rx_sca_rsp(connsm, dptr); + break; +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO) + case BLE_LL_CTRL_CIS_REQ: + rsp_opcode = ble_ll_ctrl_rx_cis_req(connsm, dptr, rspdata); + break; + case BLE_LL_CTRL_CIS_RSP: + rsp_opcode = ble_ll_ctrl_rx_cis_rsp(connsm, dptr, rspdata); + break; + case BLE_LL_CTRL_CIS_IND: + rsp_opcode = ble_ll_ctrl_rx_cis_ind(connsm, dptr); + break; +#endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) case BLE_LL_CTRL_PERIODIC_SYNC_IND: rsp_opcode = ble_ll_ctrl_rx_periodic_sync_ind(connsm, dptr); @@ -2709,6 +2839,7 @@ ble_ll_ctrl_tx_done(struct os_mbuf *txpdu, struct ble_ll_conn_sm *connsm) connsm->enc_data.enc_state = CONN_ENC_S_ENC_RSP_WAIT; break; case BLE_LL_CTRL_ENC_RSP: + connsm->enc_data.enc_state = CONN_ENC_S_LTK_REQ_WAIT; connsm->csmflags.cfbit.send_ltk_req = 1; break; case BLE_LL_CTRL_START_ENC_RSP: diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_hci.c b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_hci.c index b82adc2e..a3da98d9 100644 --- a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_hci.c +++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_hci.c @@ -33,6 +33,7 @@ #include "controller/ble_ll_whitelist.h" #include "controller/ble_ll_resolv.h" #include "controller/ble_ll_sync.h" +#include "controller/ble_ll_iso.h" #include "ble_ll_priv.h" #include "ble_ll_conn_priv.h" @@ -327,6 +328,31 @@ ble_ll_hci_le_read_bufsize(uint8_t *rspbuf, uint8_t *rsplen) return BLE_ERR_SUCCESS; } +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO) +/** + * HCI read buffer size v2 command. Returns the ACL and ISO data packet length and + * num data packets. + * + * @param rspbuf Pointer to response buffer + * @param rsplen Length of response buffer + * + * @return int BLE error code + */ +static int +ble_ll_hci_le_read_bufsize_v2(uint8_t *rspbuf, uint8_t *rsplen) +{ + struct ble_hci_le_rd_buf_size_v2_rp *rp = (void *) rspbuf; + + rp->data_len = htole16(g_ble_ll_data.ll_acl_pkt_size); + rp->data_packets = g_ble_ll_data.ll_num_acl_pkts; + rp->iso_data_len = 0; + rp->iso_data_packets = 0; + + *rsplen = sizeof(*rp); + return BLE_ERR_SUCCESS; +} +#endif + #if (BLE_LL_BT5_PHY_SUPPORTED == 1) /** * Checks the preferred phy masks for validity and places the preferred masks @@ -618,6 +644,9 @@ ble_ll_hci_le_cmd_send_cmd_status(uint16_t ocf) case BLE_HCI_OCF_LE_GEN_DHKEY: case BLE_HCI_OCF_LE_SET_PHY: case BLE_HCI_OCF_LE_PERIODIC_ADV_CREATE_SYNC: +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE) + case BLE_HCI_OCF_LE_REQ_PEER_SCA: +#endif rc = 1; break; default: @@ -1149,10 +1178,77 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf, rc = ble_ll_set_default_sync_transfer_params(cmdbuf, len); break; #endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO) + case BLE_HCI_OCF_LE_READ_ISO_TX_SYNC: + rc = ble_ll_iso_read_tx_sync(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_SET_CIG_PARAM: + rc = ble_ll_iso_set_cig_param(cmdbuf, len, rspbuf, rsplen); + break; + case BLE_HCI_OCF_LE_CREATE_CIS: + rc = ble_ll_iso_create_cis(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_REMOVE_CIG: + rc = ble_ll_iso_remove_cig(cmdbuf, len, rspbuf, rsplen); + break; + case BLE_HCI_OCF_LE_ACCEPT_CIS_REQ: + rc = ble_ll_iso_accept_cis_req(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_REJECT_CIS_REQ: + rc = ble_ll_iso_reject_cis_req(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_CREATE_BIG: + rc = ble_ll_iso_create_big(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_TERMINATE_BIG: + rc = ble_ll_iso_terminate_big(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_BIG_CREATE_SYNC: + rc = ble_ll_iso_big_create_sync(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_BIG_TERMINATE_SYNC: + rc = ble_ll_iso_big_terminate_sync(cmdbuf,len); + break; + case BLE_HCI_OCF_LE_SETUP_ISO_DATA_PATH: + rc = ble_ll_iso_setup_iso_data_path(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_REMOVE_ISO_DATA_PATH: + rc = ble_ll_iso_remove_iso_data_path(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_RD_BUF_SIZE_V2: + rc = ble_ll_hci_le_read_bufsize_v2(rspbuf, rsplen); + break; +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO_TEST) + case BLE_HCI_OCF_LE_SET_CIG_PARAM_TEST: + rc = ble_ll_iso_set_cig_param_test(cmdbuf, len, rspbuf, rsplen); + break; + case BLE_HCI_OCF_LE_CREATE_BIG_TEST: + rc = ble_ll_iso_create_big_test(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_ISO_TRANSMIT_TEST: + rc = ble_ll_iso_transmit_test(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_ISO_RECEIVE_TEST: + rc = ble_ll_iso_receive_test(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_ISO_READ_TEST_COUNTERS: + rc = ble_ll_iso_read_counters_test(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_ISO_TEST_END: + rc = ble_ll_iso_end_test(cmdbuf, len); + break; +#endif #if MYNEWT_VAL(BLE_VERSION) >= 52 case BLE_HCI_OCF_LE_SET_HOST_FEAT: rc = ble_ll_set_host_feat(cmdbuf, len); break; +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE) + case BLE_HCI_OCF_LE_REQ_PEER_SCA: + rc = ble_ll_conn_req_peer_sca(cmdbuf, len, + rspbuf, rsplen); + break; #endif default: rc = BLE_ERR_UNKNOWN_HCI_CMD; @@ -1174,6 +1270,26 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf, return rc; } +static int +ble_ll_hci_disconnect(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_lc_disconnect_cp *cmd; + + cmd = (const void *) cmdbuf; + + if (len != sizeof (*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO) + if (le16toh(cmd->conn_handle) >= BLE_LL_CONN_HANDLE_ISO_OFFSET) { + return ble_ll_iso_disconnect_cmd(cmd); + } +#endif + + return ble_ll_conn_hci_disconnect_cmd(cmd); +} + /** * Process a link control command sent from the host to the controller. The HCI * command has a 3 byte command header followed by data. The header is: @@ -1194,7 +1310,7 @@ ble_ll_hci_link_ctrl_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf) switch (ocf) { case BLE_HCI_OCF_DISCONNECT_CMD: - rc = ble_ll_conn_hci_disconnect_cmd(cmdbuf, len); + rc = ble_ll_hci_disconnect(cmdbuf, len); /* Send command status instead of command complete */ rc += (BLE_ERR_MAX + 1); break; @@ -1227,6 +1343,64 @@ ble_ll_hci_cb_set_event_mask(const uint8_t *cmdbuf, uint8_t len) return BLE_ERR_SUCCESS; } +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL) +static int +ble_ll_hci_cb_set_ctrlr_to_host_fc(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_cb_ctlr_to_host_fc_cp *cmd = (const void *) cmdbuf; + + if (len != sizeof (*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* We only allow to either disable flow control or enable for ACL only */ + if (cmd->enable > 1) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (!ble_ll_conn_cth_flow_enable(cmd->enable)) { + return BLE_ERR_CMD_DISALLOWED; + } + + return BLE_ERR_SUCCESS; +} + +static int +ble_ll_hci_cb_host_buf_size(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_cb_host_buf_size_cp *cmd = (const void *) cmdbuf; + uint16_t acl_num; + uint16_t acl_data_len; + + if (len != sizeof (*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* We do not support SCO so those parameters should be set to 0 */ + if (cmd->sco_num || cmd->sco_data_len) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* + * Core 5.2 Vol 4 Part E section 7.3.39 states that "Both the Host and the + * Controller shall support command and event packets, where the data portion + * (excluding header) contained in the packets is 255 octets in size.". + * This means we can basically accept any allowed value since LL does not + * reassemble incoming data thus will not send more than 255 octets in single + * data packet. + */ + acl_num = le16toh(cmd->acl_num); + acl_data_len = le16toh(cmd->acl_data_len); + if (acl_data_len < 255) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + ble_ll_conn_cth_flow_set_buffers(acl_num); + + return BLE_ERR_SUCCESS; +} +#endif + static int ble_ll_hci_cb_set_event_mask2(const uint8_t *cmdbuf, uint8_t len) { @@ -1259,6 +1433,22 @@ ble_ll_hci_ctlr_bb_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf, rc = ble_ll_reset(); } break; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL) + case BLE_HCI_OCF_CB_SET_CTLR_TO_HOST_FC: + rc = ble_ll_hci_cb_set_ctrlr_to_host_fc(cmdbuf, len); + break; + case BLE_HCI_OCF_CB_HOST_BUF_SIZE: + rc = ble_ll_hci_cb_host_buf_size(cmdbuf, len); + break; + case BLE_HCI_OCF_CB_HOST_NUM_COMP_PKTS: + /* + * HCI_Host_Number_Of_Completed_Packets is handled immediately when + * received from transport so we should never receive it here. + */ + BLE_LL_ASSERT(0); + rc = BLE_ERR_UNKNOWN_HCI_CMD; + break; +#endif case BLE_HCI_OCF_CB_SET_EVENT_MASK2: rc = ble_ll_hci_cb_set_event_mask2(cmdbuf, len); break; @@ -1454,9 +1644,33 @@ ble_ll_hci_cmd_proc(struct ble_npl_event *ev) * BLE_ERR_MEM_CAPACITY on HCI buffer exhaustion. */ int -ble_ll_hci_cmd_rx(uint8_t *cmd, void *arg) +ble_ll_hci_cmd_rx(uint8_t *cmdbuf, void *arg) { struct ble_npl_event *ev; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL) + const struct ble_hci_cmd *cmd; + uint16_t opcode; + uint16_t ocf; + uint16_t ogf; + + cmd = (const void *)cmdbuf; + opcode = le16toh(cmd->opcode); + ogf = BLE_HCI_OGF(opcode); + ocf = BLE_HCI_OCF(opcode); + + /* + * HCI_Host_Number_Of_Completed_Packets is processed outside standard flow + * thus it can be sent at any time, even if another command is already + * pending. This means we should better process it here and send an event to + * LL in case of error. + */ + if ((ogf == BLE_HCI_OGF_CTLR_BASEBAND) && + (ocf == BLE_HCI_OCF_CB_HOST_NUM_COMP_PKTS)) { + ble_ll_conn_cth_flow_process_cmd(cmdbuf); + ble_hci_trans_buf_free(cmdbuf); + return 0; + } +#endif /* Get an event structure off the queue */ ev = &g_ble_ll_hci_cmd_ev; @@ -1465,7 +1679,7 @@ ble_ll_hci_cmd_rx(uint8_t *cmd, void *arg) } /* Fill out the event and post to Link Layer */ - ble_npl_event_set_arg(ev, cmd); + ble_npl_event_set_arg(ev, cmdbuf); ble_npl_eventq_put(&g_ble_ll_data.ll_evq, ev); return 0; diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_hci_ev.c b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_hci_ev.c index dbc50db9..0d6da9a0 100644 --- a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_hci_ev.c +++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_hci_ev.c @@ -461,6 +461,37 @@ ble_ll_hci_ev_phy_update(struct ble_ll_conn_sm *connsm, uint8_t status) } #endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE) +void +ble_ll_hci_ev_sca_update(struct ble_ll_conn_sm *connsm, uint8_t status, + uint8_t peer_sca) +{ + struct ble_hci_ev_le_subev_peer_sca_complete *ev; + struct ble_hci_ev *hci_ev; + + if (!ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_REQ_PEER_SCA_COMP)) { + return; + } + + hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); + if (!hci_ev) { + return; + } + + hci_ev->opcode = BLE_HCI_EVCODE_LE_META; + hci_ev->length = sizeof(*ev); + ev = (void *) hci_ev->data; + + ev->subev_code = BLE_HCI_LE_SUBEV_REQ_PEER_SCA_COMP; + ev->status = status; + ev->conn_handle = htole16(connsm->conn_handle); + ev->sca = peer_sca; + + ble_ll_hci_event_send(hci_ev); +} + +#endif + void ble_ll_hci_ev_send_vendor_err(const char *file, uint32_t line) { diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_iso.c b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_iso.c new file mode 100644 index 00000000..a6186fe1 --- /dev/null +++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_iso.c @@ -0,0 +1,146 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include "syscfg/syscfg.h" +#include "nimble/ble.h" +#include "nimble/hci_common.h" +#include "controller/ble_ll_iso.h" + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO) + +int +ble_ll_iso_read_tx_sync(const uint8_t *cmdbuf, uint8_t len) +{ + return BLE_ERR_UNSUPPORTED; +} + +int +ble_ll_iso_set_cig_param(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen) +{ + return BLE_ERR_UNSUPPORTED; +} + +int +ble_ll_iso_create_cis(const uint8_t *cmdbuf, uint8_t len) +{ + return BLE_ERR_UNSUPPORTED; +} + +int +ble_ll_iso_disconnect_cmd(const struct ble_hci_lc_disconnect_cp *cmd) +{ + return BLE_ERR_UNSUPPORTED; +} + +int +ble_ll_iso_remove_cig(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen) +{ + return BLE_ERR_UNSUPPORTED; +} + +int +ble_ll_iso_accept_cis_req(const uint8_t *cmdbuf, uint8_t len) +{ + return BLE_ERR_UNSUPPORTED; +} + +int +ble_ll_iso_reject_cis_req(const uint8_t *cmdbuf, uint8_t len) +{ + return BLE_ERR_UNSUPPORTED; +} + +int +ble_ll_iso_setup_iso_data_path(const uint8_t *cmdbuf, uint8_t len) +{ + return BLE_ERR_UNSUPPORTED; +} + +int +ble_ll_iso_remove_iso_data_path(const uint8_t *cmdbuf, uint8_t len) +{ + /* Nothing to do here for now when HCI is supported */ + return 0; +} +int +ble_ll_iso_create_big(const uint8_t *cmdbuf, uint8_t len) +{ + return BLE_ERR_UNSUPPORTED; +} + +int +ble_ll_iso_terminate_big(const uint8_t *cmdbuf, uint8_t len) +{ + return BLE_ERR_UNSUPPORTED; +} + +int +ble_ll_iso_big_create_sync(const uint8_t *cmdbuf, uint8_t len) +{ + return BLE_ERR_UNSUPPORTED; +} + +int +ble_ll_iso_big_terminate_sync(const uint8_t *cmdbuf, uint8_t len) +{ + return BLE_ERR_UNSUPPORTED; +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO_TEST) +int +ble_ll_iso_set_cig_param_test(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen) +{ + return BLE_ERR_UNSUPPORTED; +} + +int +ble_ll_iso_create_big_test(const uint8_t *cmdbuf, uint8_t len) +{ + return BLE_ERR_UNSUPPORTED; +} + +int +ble_ll_iso_transmit_test(const uint8_t *cmdbuf, uint8_t len) +{ + return BLE_ERR_UNSUPPORTED; +} + +int +ble_ll_iso_receive_test(const uint8_t *cmdbuf, uint8_t len) +{ + return BLE_ERR_UNSUPPORTED; +} + +int +ble_ll_iso_read_counters_test(const uint8_t *cmdbuf, uint8_t len) +{ + return BLE_ERR_UNSUPPORTED; +} + +int +ble_ll_iso_end_test(const uint8_t *cmdbuf, uint8_t len) +{ + return BLE_ERR_UNSUPPORTED; +} +#endif +#endif diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_rand.c b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_rand.c index 7b384e9d..8aa71271 100644 --- a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_rand.c +++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_rand.c @@ -17,6 +17,9 @@ * under the License. */ +/* for jrand48 */ +#define _XOPEN_SOURCE +#include #include #include #include @@ -120,6 +123,21 @@ ble_ll_rand_data_get(uint8_t *buf, uint8_t len) return BLE_ERR_SUCCESS; } +/* Simple wrapper to allow easy replacement of rand() */ +uint32_t +ble_ll_rand(void) +{ + static unsigned short xsubi[3]; + static bool init = true; + + if (init) { + init = false; + ble_ll_rand_data_get((uint8_t *)xsubi, sizeof(xsubi)); + } + + return (uint32_t) jrand48(xsubi); +} + /** * Called to obtain a "prand" as defined in core V4.2 Vol 6 Part B 1.3.2.2 * diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_scan.c b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_scan.c index 84747db7..0cbcb376 100644 --- a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_scan.c +++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_scan.c @@ -293,7 +293,7 @@ ble_ll_scan_req_backoff(struct ble_ll_scan_sm *scansm, int success) STATS_INC(ble_ll_stats, scan_req_txf); } - scansm->backoff_count = rand() & (scansm->upper_limit - 1); + scansm->backoff_count = ble_ll_rand() & (scansm->upper_limit - 1); ++scansm->backoff_count; BLE_LL_ASSERT(scansm->backoff_count <= 256); } @@ -305,7 +305,7 @@ ble_ll_scan_refresh_nrpa(struct ble_ll_scan_sm *scansm) ble_npl_time_t now; now = ble_npl_time_get(); - if ((ble_npl_stime_t)(now - scansm->scan_nrpa_timer) >= 0) { + if (CPUTIME_GEQ(now, scansm->scan_nrpa_timer)) { /* Generate new NRPA */ ble_ll_rand_data_get(scansm->scan_nrpa, BLE_DEV_ADDR_LEN); scansm->scan_nrpa[5] &= ~0xc0; @@ -617,7 +617,7 @@ ble_ll_scan_add_scan_rsp_adv(uint8_t *addr, uint8_t txadd, static int ble_ll_hci_send_legacy_ext_adv_report(uint8_t evtype, const uint8_t *addr, uint8_t addr_type, - uint8_t rssi, + int8_t rssi, uint8_t adv_data_len, struct os_mbuf *adv_data, const uint8_t *inita, uint8_t inita_type) @@ -1125,6 +1125,22 @@ ble_ll_scan_sm_stop(int chk_disable) scansm = &g_ble_ll_scan_sm; os_cputime_timer_stop(&scansm->scan_timer); + /* Only set state if we are currently in a scan window */ + if (chk_disable) { + OS_ENTER_CRITICAL(sr); + lls = ble_ll_state_get(); + + if ((lls == BLE_LL_STATE_SCANNING) || + (lls == BLE_LL_STATE_INITIATING && chk_disable == 1)) { + /* Disable phy */ + ble_phy_disable(); + + /* Set LL state to standby */ + ble_ll_state_set(BLE_LL_STATE_STANDBY); + } + OS_EXIT_CRITICAL(sr); + } + OS_ENTER_CRITICAL(sr); /* Disable scanning state machine */ @@ -1149,22 +1165,6 @@ ble_ll_scan_sm_stop(int chk_disable) /* Count # of times stopped */ STATS_INC(ble_ll_stats, scan_stops); - /* Only set state if we are currently in a scan window */ - if (chk_disable) { - OS_ENTER_CRITICAL(sr); - lls = ble_ll_state_get(); - - if ((lls == BLE_LL_STATE_SCANNING) || - (lls == BLE_LL_STATE_INITIATING && chk_disable == 1)) { - /* Disable phy */ - ble_phy_disable(); - - /* Set LL state to standby */ - ble_ll_state_set(BLE_LL_STATE_STANDBY); - } - OS_EXIT_CRITICAL(sr); - } - /* No need for RF anymore */ OS_ENTER_CRITICAL(sr); ble_ll_rfmgmt_scan_changed(false, 0); @@ -1991,10 +1991,10 @@ ble_ll_scan_rx_filter(struct ble_mbuf_hdr *hdr, struct ble_ll_scan_addr_data *ad { struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; struct ble_ll_scan_params *scanp = scansm->scanp; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) struct ble_ll_aux_data *aux_data = hdr->rxinfo.user_data; #endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) struct ble_mbuf_hdr_rxinfo *rxinfo = &hdr->rxinfo; struct ble_ll_resolv_entry *rl = NULL; #endif @@ -2227,6 +2227,7 @@ ble_ll_scan_rx_isr_on_aux(uint8_t pdu_type, uint8_t *rxbuf, */ if (aux_data->flags & BLE_LL_AUX_IS_MATCHED) { rxinfo->flags |= BLE_MBUF_HDR_F_DEVMATCH; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) rxinfo->rpa_index = aux_data->rpa_index; if (rxinfo->rpa_index >= 0) { rxinfo->flags |= BLE_MBUF_HDR_F_RESOLVED; @@ -2234,6 +2235,7 @@ ble_ll_scan_rx_isr_on_aux(uint8_t pdu_type, uint8_t *rxbuf, if (aux_data->flags & BLE_LL_AUX_IS_TARGETA_RESOLVED) { rxinfo->flags |= BLE_MBUF_HDR_F_TARGETA_RESOLVED; } +#endif goto done; } @@ -3019,7 +3021,8 @@ ble_ll_scan_rx_pkt_in_on_legacy(uint8_t pdu_type, struct os_mbuf *om, if (!BLE_MBUF_HDR_DEVMATCH(hdr) || !BLE_MBUF_HDR_CRC_OK(hdr) || - BLE_MBUF_HDR_IGNORED(hdr)) { + BLE_MBUF_HDR_IGNORED(hdr) || + !scansm->scan_enabled) { return; } @@ -3058,10 +3061,6 @@ ble_ll_scan_rx_pkt_in_on_aux(uint8_t pdu_type, struct os_mbuf *om, bool send_hci_report; int rc; - if (!scansm->ext_scanning) { - goto scan_continue; - } - if (aux_data) { aux_data->flags_ll |= aux_data->flags_isr; } @@ -3077,7 +3076,8 @@ ble_ll_scan_rx_pkt_in_on_aux(uint8_t pdu_type, struct os_mbuf *om, BLE_MBUF_HDR_IGNORED(hdr) || BLE_MBUF_HDR_AUX_INVALID(hdr) || (aux_data->flags_ll & BLE_LL_AUX_FLAG_SCAN_ERROR) || - (pdu_type != BLE_ADV_PDU_TYPE_ADV_EXT_IND)) { + (pdu_type != BLE_ADV_PDU_TYPE_ADV_EXT_IND) || + !scansm->scan_enabled) { if (aux_data) { ble_ll_scan_end_adv_evt(aux_data); ble_ll_scan_aux_data_unref(aux_data); diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_sched.c b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_sched.c index 370faddf..d01f10ed 100644 --- a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_sched.c +++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_sched.c @@ -83,14 +83,14 @@ ble_ll_sched_is_overlap(struct ble_ll_sched_item *s1, int rc; rc = 1; - if ((int32_t)(s1->start_time - s2->start_time) < 0) { + if (CPUTIME_LT(s1->start_time, s2->start_time)) { /* Make sure this event does not overlap current event */ - if ((int32_t)(s1->end_time - s2->start_time) <= 0) { + if (CPUTIME_LEQ(s1->end_time, s2->start_time)) { rc = 0; } } else { /* Check for overlap */ - if ((int32_t)(s1->start_time - s2->end_time) >= 0) { + if (CPUTIME_GEQ(s1->start_time, s2->end_time)) { rc = 0; } } @@ -111,7 +111,7 @@ ble_ll_sched_overlaps_current(struct ble_ll_sched_item *sch) rc = 0; if (ble_ll_state_get() == BLE_LL_STATE_CONNECTION) { ce_end_time = ble_ll_conn_get_ce_end_time(); - if ((int32_t)(ce_end_time - sch->start_time) > 0) { + if (CPUTIME_GT(ce_end_time, sch->start_time)) { rc = 1; } } @@ -178,7 +178,7 @@ ble_ll_sched_conn_reschedule(struct ble_ll_conn_sm *connsm) sch->end_time = connsm->ce_end_time; /* Better be past current time or we just leave */ - if ((int32_t)(sch->start_time - os_cputime_get32()) < 0) { + if (CPUTIME_LT(sch->start_time, os_cputime_get32())) { return -1; } @@ -216,7 +216,7 @@ ble_ll_sched_conn_reschedule(struct ble_ll_conn_sm *connsm) end_overlap = entry; } } else { - if ((int32_t)(sch->end_time - entry->start_time) <= 0) { + if (CPUTIME_LEQ(sch->end_time, entry->start_time)) { rc = 0; TAILQ_INSERT_BEFORE(entry, sch, link); break; @@ -468,7 +468,7 @@ ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm, sch->end_time = earliest_end; /* We can insert if before entry in list */ - if ((int32_t)(sch->end_time - entry->start_time) <= 0) { + if (CPUTIME_LEQ(sch->end_time, entry->start_time)) { if ((earliest_start - initial_start) <= itvl_t) { rc = 0; TAILQ_INSERT_BEFORE(entry, sch, link); @@ -655,7 +655,7 @@ ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm, sch->end_time = earliest_end; /* We can insert if before entry in list */ - if ((int32_t)(sch->end_time - entry->start_time) <= 0) { + if (CPUTIME_LEQ(sch->end_time, entry->start_time)) { if ((earliest_start - initial_start) <= itvl_t) { rc = 0; TAILQ_INSERT_BEFORE(entry, sch, link); @@ -770,7 +770,7 @@ ble_ll_sched_slave_new(struct ble_ll_conn_sm *connsm) while (1) { next_sch = entry->link.tqe_next; /* Insert if event ends before next starts */ - if ((int32_t)(sch->end_time - entry->start_time) <= 0) { + if (CPUTIME_LEQ(sch->end_time, entry->start_time)) { rc = 0; TAILQ_INSERT_BEFORE(entry, sch, link); break; @@ -1047,7 +1047,7 @@ ble_ll_sched_adv_new(struct ble_ll_sched_item *sch, ble_ll_sched_adv_new_cb cb, os_cputime_timer_stop(&g_ble_ll_sched_timer); TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) { /* We can insert if before entry in list */ - if ((int32_t)(sch->end_time - entry->start_time) <= 0) { + if (CPUTIME_LEQ(sch->end_time, entry->start_time)) { TAILQ_INSERT_BEFORE(entry, sch, link); break; } @@ -1111,7 +1111,7 @@ ble_ll_sched_periodic_adv(struct ble_ll_sched_item *sch, uint32_t *start, os_cputime_timer_stop(&g_ble_ll_sched_timer); TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) { /* We can insert if before entry in list */ - if ((int32_t)(sch->end_time - entry->start_time) <= 0) { + if (CPUTIME_LEQ(sch->end_time, entry->start_time)) { TAILQ_INSERT_BEFORE(entry, sch, link); break; } @@ -1200,7 +1200,7 @@ ble_ll_sched_adv_reschedule(struct ble_ll_sched_item *sch, uint32_t *start, end_overlap = entry; } } else { - if ((int32_t)(sch->end_time - entry->start_time) <= 0) { + if (CPUTIME_LEQ(sch->end_time, entry->start_time)) { before = entry; break; } @@ -1233,7 +1233,7 @@ ble_ll_sched_adv_reschedule(struct ble_ll_sched_item *sch, uint32_t *start, sch->end_time = sch->start_time + duration; while (1) { next_sch = entry->link.tqe_next; - if ((int32_t)(sch->end_time - entry->start_time) <= 0) { + if (CPUTIME_LEQ(sch->end_time, entry->start_time)) { rand_ticks = entry->start_time - sch->end_time; before = entry; TAILQ_INSERT_BEFORE(before, sch, link); @@ -1266,7 +1266,7 @@ ble_ll_sched_adv_reschedule(struct ble_ll_sched_item *sch, uint32_t *start, if (!rc) { sch->enqueued = 1; if (rand_ticks) { - sch->start_time += rand() % rand_ticks; + sch->start_time += ble_ll_rand() % rand_ticks; } sch->end_time = sch->start_time + duration; *start = sch->start_time; @@ -1580,7 +1580,7 @@ ble_ll_sched_scan_req_over_aux_ptr(uint32_t chan, uint8_t phy_mode) while (sch) { /* Let's check if there is no scheduled item which want to start within * given usecs.*/ - if ((int32_t)(sch->start_time - now + os_cputime_usecs_to_ticks(usec_dur)) > 0) { + if (CPUTIME_GT(sch->start_time, now + os_cputime_usecs_to_ticks(usec_dur))) { /* We are fine. Have time for scan req */ return 0; } @@ -1670,7 +1670,7 @@ ble_ll_sched_aux_scan(struct ble_mbuf_hdr *ble_hdr, os_cputime_timer_stop(&g_ble_ll_sched_timer); TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) { /* We can insert if before entry in list */ - if ((int32_t)(sch->end_time - entry->start_time) <= 0) { + if (CPUTIME_LEQ(sch->end_time, entry->start_time)) { rc = 0; TAILQ_INSERT_BEFORE(entry, sch, link); sch->enqueued = 1; diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_supp_cmd.c b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_supp_cmd.c index 834e0095..cae9eb7d 100644 --- a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_supp_cmd.c +++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_supp_cmd.c @@ -36,7 +36,22 @@ /* Octet 10 */ #define BLE_SUPP_CMD_RD_TX_PWR (0 << 2) -#define BLE_LL_SUPP_CMD_OCTET_10 (BLE_SUPP_CMD_RD_TX_PWR) +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL) +#define BLE_SUPP_CMD_SET_CTRL_TO_HOST_FLOW (1 << 5) +#define BLE_SUPP_CMD_HOST_BUFFER_SIZE (1 << 6) +#define BLE_SUPP_CMD_HOST_NUM_COMP_PACKETS (1 << 7) +#else +#define BLE_SUPP_CMD_SET_CTRL_TO_HOST_FLOW (0 << 5) +#define BLE_SUPP_CMD_HOST_BUFFER_SIZE (0 << 6) +#define BLE_SUPP_CMD_HOST_NUM_COMP_PACKETS (0 << 7) +#endif +#define BLE_LL_SUPP_CMD_OCTET_10 \ +( \ + BLE_SUPP_CMD_RD_TX_PWR | \ + BLE_SUPP_CMD_SET_CTRL_TO_HOST_FLOW | \ + BLE_SUPP_CMD_HOST_BUFFER_SIZE | \ + BLE_SUPP_CMD_HOST_NUM_COMP_PACKETS \ +) /* Octet 14 */ #define BLE_SUPP_CMD_RD_LOC_VER (1 << 3) @@ -404,10 +419,77 @@ #define BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER_PARAMS (0 << 0) #define BLE_SUPP_CMD_LE_PADV_DEFAULT_SYNC_TRANSFER_PARAMS (0 << 1) #endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO) +#define BLE_SUPP_CMD_LE_READ_BUF_SIZE_V2 (1 << 5) +#define BLE_SUPP_CMD_LE_READ_ISO_TX_SYNC (1 << 6) +#define BLE_SUPP_CMD_LE_SET_CIG_PARAM (1 << 7) +#else +#define BLE_SUPP_CMD_LE_READ_BUF_SIZE_V2 (0 << 5) +#define BLE_SUPP_CMD_LE_READ_ISO_TX_SYNC (0 << 6) +#define BLE_SUPP_CMD_LE_SET_CIG_PARAM (0 << 7) +#endif + #define BLE_LL_SUPP_CMD_OCTET_41 \ ( \ - BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER_PARAMS | \ - BLE_SUPP_CMD_LE_PADV_DEFAULT_SYNC_TRANSFER_PARAMS \ + BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER_PARAMS | \ + BLE_SUPP_CMD_LE_PADV_DEFAULT_SYNC_TRANSFER_PARAMS | \ + BLE_SUPP_CMD_LE_READ_BUF_SIZE_V2 | \ + BLE_SUPP_CMD_LE_READ_ISO_TX_SYNC | \ + BLE_SUPP_CMD_LE_SET_CIG_PARAM \ +) + +/* Octet 42 */ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO) +#define BLE_SUPP_CMD_LE_SET_CIG_PARAM_TEST (1 << 0) +#define BLE_SUPP_CMD_LE_CREATE_CIS (1 << 1) +#define BLE_SUPP_CMD_LE_REMOVE_CIG (1 << 2) +#define BLE_SUPP_CMD_LE_ACCEPT_CIS_REQ (1 << 3) +#define BLE_SUPP_CMD_LE_REJECT_CIS_REQ (1 << 4) +#define BLE_SUPP_CMD_LE_CREATE_BIG (1 << 5) +#define BLE_SUPP_CMD_LE_CREATE_BIG_TEST (1 << 6) +#define BLE_SUPP_CMD_LE_TERMINATE_BIG (1 << 7) +#else +#define BLE_SUPP_CMD_LE_SET_CIG_PARAM_TEST (0 << 0) +#define BLE_SUPP_CMD_LE_CREATE_CIS (0 << 1) +#define BLE_SUPP_CMD_LE_REMOVE_CIG (0 << 2) +#define BLE_SUPP_CMD_LE_ACCEPT_CIS_REQ (0 << 3) +#define BLE_SUPP_CMD_LE_REJECT_CIS_REQ (0 << 4) +#define BLE_SUPP_CMD_LE_CREATE_BIG (0 << 5) +#define BLE_SUPP_CMD_LE_CREATE_BIG_TEST (0 << 6) +#define BLE_SUPP_CMD_LE_TERMINATE_BIG (0 << 7) +#endif +#define BLE_LL_SUPP_CMD_OCTET_42 \ +( \ + BLE_SUPP_CMD_LE_SET_CIG_PARAM_TEST | \ + BLE_SUPP_CMD_LE_CREATE_CIS | \ + BLE_SUPP_CMD_LE_REMOVE_CIG | \ + BLE_SUPP_CMD_LE_ACCEPT_CIS_REQ | \ + BLE_SUPP_CMD_LE_REJECT_CIS_REQ | \ + BLE_SUPP_CMD_LE_CREATE_BIG | \ + BLE_SUPP_CMD_LE_CREATE_BIG_TEST | \ + BLE_SUPP_CMD_LE_TERMINATE_BIG \ +) + +/* Octet 43 */ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE) +#define BLE_SUPP_CMD_LE_REQUEST_PEER_SCA (1 << 2) +#else +#define BLE_SUPP_CMD_LE_REQUEST_PEER_SCA (0 << 0) +#endif +#define BLE_LL_SUPP_CMD_OCTET_43 \ +( \ + BLE_SUPP_CMD_LE_REQUEST_PEER_SCA \ +) + +/* Octet 44 */ +#if MYNEWT_VAL(BLE_VERSION) >= 52 +#define BLE_SUPP_CMD_LE_SET_HOST_FEATURE (1 << 0) +#else +#define BLE_SUPP_CMD_LE_SET_HOST_FEATURE (0 << 0) +#endif +#define BLE_LL_SUPP_CMD_OCTET_44 \ +( \ + BLE_SUPP_CMD_LE_SET_HOST_FEATURE \ ) /* Defines the array of supported commands */ @@ -455,4 +537,7 @@ const uint8_t g_ble_ll_supp_cmds[BLE_LL_SUPP_CMD_LEN] = BLE_LL_SUPP_CMD_OCTET_39, BLE_LL_SUPP_CMD_OCTET_40, /* Octet 40 */ BLE_LL_SUPP_CMD_OCTET_41, + BLE_LL_SUPP_CMD_OCTET_42, + BLE_LL_SUPP_CMD_OCTET_43, + BLE_LL_SUPP_CMD_OCTET_44, }; diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_sync.c b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_sync.c index 75f18bf2..df806082 100644 --- a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_sync.c +++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_sync.c @@ -2091,10 +2091,10 @@ ble_ll_sync_send_sync_ind(struct ble_ll_sync_sm *syncsm, if (syncsm->flags & BLE_LL_SYNC_SM_FLAG_ADDR_RESOLVED) { sync_ind[24] |= 1 << 4; } else { - sync_ind[24] |= (syncsm->adv_addr_type == BLE_ADDR_RANDOM) << 4 ; + sync_ind[24] |= (syncsm->adv_addr_type == BLE_ADDR_RANDOM) << 4; } - sync_ind[24] |= MYNEWT_VAL(BLE_LL_MASTER_SCA) << 5; + sync_ind[24] |= BLE_LL_SCA_ENUM << 5; /* PHY */ sync_ind[25] = (0x01 << (ble_ll_sync_phy_mode_to_hci(syncsm->phy_mode) - 1)); diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_utils.c b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_utils.c index 7fbb18f1..ccdf3775 100644 --- a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_utils.c +++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_utils.c @@ -50,8 +50,8 @@ ble_ll_utils_calc_access_addr(void) aa = 0; while (1) { /* Get two, 16-bit random numbers */ - aa_low = rand() & 0xFFFF; - aa_high = rand() & 0xFFFF; + aa_low = ble_ll_rand() & 0xFFFF; + aa_high = ble_ll_rand() & 0xFFFF; /* All four bytes cannot be equal */ if (aa_low == aa_high) { @@ -292,8 +292,7 @@ ble_ll_utils_calc_window_widening(uint32_t anchor_point, time_since_last_anchor = (int32_t)(anchor_point - last_anchor_point); if (time_since_last_anchor > 0) { delta_msec = os_cputime_ticks_to_usecs(time_since_last_anchor) / 1000; - total_sca_ppm = g_ble_sca_ppm_tbl[master_sca] + - MYNEWT_VAL(BLE_LL_OUR_SCA); + total_sca_ppm = g_ble_sca_ppm_tbl[master_sca] + MYNEWT_VAL(BLE_LL_SCA); window_widening = (total_sca_ppm * delta_msec) / 1000; } diff --git a/src/libs/mynewt-nimble/nimble/controller/syscfg.yml b/src/libs/mynewt-nimble/nimble/controller/syscfg.yml index 85049cb0..2c7c2cb2 100644 --- a/src/libs/mynewt-nimble/nimble/controller/syscfg.yml +++ b/src/libs/mynewt-nimble/nimble/controller/syscfg.yml @@ -38,35 +38,10 @@ syscfg.defs: type: 'task_priority' value: 0 - # Sleep clock accuracy (sca). This is the amount of drift in the system - # during when the device is sleeping (in parts per million). - # - # NOTE: 'the' master sca is an enumerated value based on the sca. Rather - # than have a piece of code calculate this value, the developer must set - # this value based on the value of the SCA using the following table: - # - # SCA between 251 and 500 ppm (inclusive); master sca = 0 - # SCA between 151 and 250 ppm (inclusive); master sca = 1 - # SCA between 101 and 150 ppm (inclusive); master sca = 2 - # SCA between 76 and 100 ppm (inclusive); master sca = 3 - # SCA between 51 and 75 ppm (inclusive); master sca = 4 - # SCA between 31 and 50 ppm (inclusive); master sca = 5 - # SCA between 21 and 30 ppm (inclusive); master sca = 6 - # SCA between 0 and 20 ppm (inclusive); master sca = 7 - # - # For example: - # if your clock drift is 101 ppm, your master should be set to 2. - # if your clock drift is 20, your master sca should be set to 7. - # - # The values provided below are merely meant to be an example and should - # be replaced by values appropriate for your platform. - BLE_LL_OUR_SCA: - description: 'The system clock accuracy of the device.' - value: '60' # in ppm - - BLE_LL_MASTER_SCA: - description: 'Enumerated value based on our sca' - value: '4' + BLE_LL_SCA: + description: Sleep clock accuracy of our device (in ppm) + value: MYNEWT_VAL(BLE_LL_OUR_SCA) + range: 0..500 BLE_LL_TX_PWR_DBM: description: 'Transmit power level.' @@ -285,6 +260,35 @@ syscfg.defs: Advertising Sync Transfer Feature. value: MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_TRANSFER) + BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL: + description: > + Enable controller-to-host flow control support. This allows host to + limit number of ACL packets sent at once from controller to avoid + congestion on HCI transport if feature is also supported by host. + value: 0 + + BLE_LL_CFG_FEAT_LL_SCA_UPDATE: + description: > + This option is used to enable/disable support for SCA update procedure + value: 0 + restrictions: + - '(BLE_VERSION >= 52) if 1' + + BLE_LL_CFG_FEAT_LL_ISO: + description: > + This option is used to enable/disable support for LE Isochronous Channels + as per Bluetooth v5.2 channels + value: MYNEWT_VAL(BLE_ISO) + restrictions: + - '(BLE_VERSION >= 52) if 1' + + BLE_LL_CFG_FEAT_LL_ISO_TEST: + description: > + This option is used to enable/disbale test commands for ISO support + value: MYNEWT_VAL(BLE_ISO_TEST) + restrictions: + - 'BLE_LL_CFG_FEAT_LL_ISO if 1' + BLE_LL_EXT_ADV_AUX_PTR_CNT: description: > This option configure a max number of scheduled outstanding auxiliary @@ -404,6 +408,10 @@ syscfg.defs: description: use BLE_LL_RFMGMT_ENABLE_TIME instead value: 0 deprecated: 1 + BLE_LL_OUR_SCA: + description: use BLE_LL_SCA instead + value: 60 + deprecated: 1 # defunct settings (to be removed eventually) BLE_DEVICE: @@ -418,6 +426,10 @@ syscfg.defs: description: Superseded by BLE_LL_NUM_COMP_PKT_ITVL_MS value: '(2 * OS_TICKS_PER_SEC)' defunct: 1 + BLE_LL_MASTER_SCA: + description: use BLE_LL_SCA instead + value: 4 + defunct: 1 syscfg.vals.BLE_LL_CFG_FEAT_LL_EXT_ADV: -- cgit v1.2.3